Complet GUI, add fly-in animation

This commit is contained in:
2022-09-12 20:35:26 +03:00
parent cf11a16d1e
commit 3d13ebef47
42 changed files with 0 additions and 1231 deletions

View File

@@ -1,12 +0,0 @@
package cc.flogi.dev.smoothchunks;
import net.fabricmc.api.ModInitializer;
/**
* @author Caden Kriese (flogic)
*
* Created on 09/21/2020
*/
public class SmoothChunks implements ModInitializer {
@Override public void onInitialize() {}
}

View File

@@ -1,28 +0,0 @@
package cc.flogi.dev.smoothchunks.client;
import cc.flogi.dev.smoothchunks.client.config.SmoothChunksConfig;
import lombok.Getter;
import me.sargunvohra.mcmods.autoconfig1u.AutoConfig;
import me.sargunvohra.mcmods.autoconfig1u.serializer.Toml4jConfigSerializer;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
/**
* @author Caden Kriese (flogic)
*
* Created on 09/21/2020
*/
@Environment(EnvType.CLIENT) public class SmoothChunksClient implements ClientModInitializer {
private static SmoothChunksClient instance;
@Getter private SmoothChunksConfig config;
public static SmoothChunksClient get() {return instance;}
@Override public void onInitializeClient() {
instance = this;
AutoConfig.register(SmoothChunksConfig.class, Toml4jConfigSerializer::new);
config = AutoConfig.getConfigHolder(SmoothChunksConfig.class).getConfig();
}
}

View File

@@ -1,13 +0,0 @@
package cc.flogi.dev.smoothchunks.client.config;
/**
* @author Caden Kriese (flogic)
*
* Created on 09/28/2020
*/
public enum LoadAnimation {
DOWNWARD,
UPWARD,
INWARD,
SCALE
}

View File

@@ -1,43 +0,0 @@
package cc.flogi.dev.smoothchunks.client.config;
import lombok.Getter;
import me.sargunvohra.mcmods.autoconfig1u.ConfigData;
import me.sargunvohra.mcmods.autoconfig1u.annotation.Config;
import me.sargunvohra.mcmods.autoconfig1u.annotation.ConfigEntry;
import me.sargunvohra.mcmods.autoconfig1u.shadowed.blue.endless.jankson.Comment;
/**
* @author Caden Kriese (flogic)
*
* Created on 09/28/2020
*/
@Config(name = "smooth-chunks") @Config.Gui.Background("minecraft:textures/block/stone.png") @Getter
public class SmoothChunksConfig implements ConfigData {
//TODO use localization for comment strings. (Somehow, not super straightforward bc annotations need const value)
@Comment("Duration of the animation in seconds.")
double duration = 1;
@Comment("The amount the chunk moves to get to its final position.")
@ConfigEntry.BoundedDiscrete(min = 1, max = 10)
int translationAmount = 5;
@Comment("Type of animation for loading chunks.")
@ConfigEntry.Gui.EnumHandler(option = ConfigEntry.Gui.EnumHandler.EnumDisplayOption.BUTTON)
LoadAnimation loadAnimation = LoadAnimation.UPWARD;
@Comment("Disable animating chunks close to you")
boolean disableNearby = true;
/*
* Custom Getters
*/
/**
* Gets the config value for translation amount, translating config value to usable value.
*
* @return The translation amount as an int 1 to 10 where higher = more translation.
*/
public double getTranslationAmount() {
return (double) translationAmount / 5d;
}
}

View File

@@ -1,21 +0,0 @@
package cc.flogi.dev.smoothchunks.client.config;
import io.github.prospector.modmenu.api.ConfigScreenFactory;
import io.github.prospector.modmenu.api.ModMenuApi;
import me.sargunvohra.mcmods.autoconfig1u.AutoConfig;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.gui.screen.Screen;
/**
* @author Caden Kriese (flogic)
*
* Created on 09/28/2020
*/
@Environment(EnvType.CLIENT)
public class SmoothChunksModMenu implements ModMenuApi {
@Override
public ConfigScreenFactory<?> getModConfigScreenFactory() {
return (ConfigScreenFactory<Screen>) parent -> AutoConfig.getConfigScreen(SmoothChunksConfig.class, parent).get();
}
}

View File

@@ -1,112 +0,0 @@
package cc.flogi.dev.smoothchunks.client.handler;
import cc.flogi.dev.smoothchunks.client.SmoothChunksClient;
import cc.flogi.dev.smoothchunks.client.config.LoadAnimation;
import cc.flogi.dev.smoothchunks.client.config.SmoothChunksConfig;
import cc.flogi.dev.smoothchunks.util.UtilEasing;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.chunk.ChunkBuilder;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3i;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* @author Caden Kriese (flogic)
*
* Created on 09/27/2020
*/
public final class ChunkAnimationHandler {
/*TODO use Reference2ReferenceLinkedHashMap from FastUtil or just inject the AnimationController directly into BuiltChunk.
* Need to solve concurrency issue as currently #addChunk is called from both render & worker threads.
*/
private static final ChunkAnimationHandler instance = new ChunkAnimationHandler();
private final Map<ChunkBuilder.BuiltChunk, AnimationController> animations = new HashMap<>();
@Getter private final Set<Vec3i> loadedChunks = new HashSet<>();
public static ChunkAnimationHandler get() {
return instance;
}
public void addChunk(ChunkBuilder.BuiltChunk chunk) {
Vec3i origin = chunk.getOrigin();
if (loadedChunks.contains(origin)) return;
loadedChunks.add(origin);
Direction direction = null;
if (SmoothChunksClient.get().getConfig().getLoadAnimation() == LoadAnimation.INWARD
&& MinecraftClient.getInstance().getCameraEntity() != null) {
BlockPos delta = chunk.getOrigin().subtract(MinecraftClient.getInstance().getCameraEntity().getBlockPos());
int dX = Math.abs(delta.getX());
int dZ = Math.abs(delta.getZ());
if (dX > dZ) {
if (delta.getX() > 0) direction = Direction.WEST;
else direction = Direction.EAST;
} else {
if (delta.getZ() > 0) direction = Direction.NORTH;
else direction = Direction.SOUTH;
}
}
animations.putIfAbsent(chunk, new AnimationController(chunk.getOrigin(), direction, System.currentTimeMillis()));
}
public void updateChunk(ChunkBuilder.BuiltChunk chunk, MatrixStack stack) {
SmoothChunksConfig config = SmoothChunksClient.get().getConfig();
AnimationController controller = animations.get(chunk);
if (controller == null || MinecraftClient.getInstance().getCameraEntity() == null) return;
BlockPos finalPos = controller.getFinalPos();
if (config.isDisableNearby()) {
double dX = finalPos.getX() - MinecraftClient.getInstance().getCameraEntity().getPos().getX();
double dZ = finalPos.getZ() - MinecraftClient.getInstance().getCameraEntity().getPos().getZ();
if (dX * dX + dZ * dZ < 32 * 32) return;
}
double completion = (double) (System.currentTimeMillis() - controller.getStartTime()) / config.getDuration() / 1000d;
completion = UtilEasing.easeOutSine(Math.min(completion, 1.0));
switch (config.getLoadAnimation()) {
default:
case DOWNWARD:
stack.translate(0, (finalPos.getY() - completion * finalPos.getY()) * config.getTranslationAmount(), 0);
break;
case UPWARD:
stack.translate(0, (-finalPos.getY() + completion * finalPos.getY()) * config.getTranslationAmount(), 0);
break;
case INWARD:
if (controller.getDirection() == null) break;
Vec3i dirVec = controller.getDirection().getVector();
double mod = -(200 - UtilEasing.easeInOutSine(completion) * 200) * config.getTranslationAmount();
stack.translate(dirVec.getX() * mod, 0, dirVec.getZ() * mod);
break;
case SCALE:
//TODO Find a way to scale centered at the middle of the chunk rather than the origin.
stack.scale((float) completion, (float) completion, (float) completion);
break;
}
if (completion >= 1.0) animations.remove(chunk);
}
@AllArgsConstructor @Data
private static class AnimationController {
private BlockPos finalPos;
private Direction direction;
private long startTime;
}
}

View File

@@ -1,28 +0,0 @@
package cc.flogi.dev.smoothchunks.mixin;
import cc.flogi.dev.smoothchunks.client.handler.ChunkAnimationHandler;
import net.minecraft.client.render.chunk.ChunkBuilder;
import net.minecraft.util.math.BlockPos;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
/**
* @author Caden Kriese (flogic)
*
* Created on 11/01/2020
*/
@Mixin(ChunkBuilder.BuiltChunk.class)
public abstract class BuiltChunkMixin {
@Shadow public abstract BlockPos getOrigin();
@Inject(
method = "clear",
at = @At(value = "TAIL")
)
public void onDelete(CallbackInfo ci) {
ChunkAnimationHandler.get().getLoadedChunks().remove(getOrigin());
}
}

View File

@@ -1,35 +0,0 @@
package cc.flogi.dev.smoothchunks.mixin;
import cc.flogi.dev.smoothchunks.client.handler.ChunkAnimationHandler;
import net.minecraft.client.render.WorldRenderer;
import net.minecraft.client.render.chunk.BlockBufferBuilderStorage;
import net.minecraft.client.render.chunk.ChunkBuilder;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.concurrent.CompletableFuture;
/**
* @author Caden Kriese (flogic)
*
* Created on 10/07/2020
*/
@SuppressWarnings("rawtypes") @Mixin(ChunkBuilder.BuiltChunk.RebuildTask.class)
public abstract class RebuildTaskMixin {
//Parent class
@SuppressWarnings("ShadowTarget") @Shadow private ChunkBuilder.BuiltChunk field_20839;
@Inject(
method = "run",
at = @At(
value = "INVOKE",
target = "Ljava/util/Set;forEach(Ljava/util/function/Consumer;)V"
)
)
public void onChunkUploads(BlockBufferBuilderStorage buffers, CallbackInfoReturnable<CompletableFuture> cir) {
ChunkAnimationHandler.get().addChunk(field_20839);
}
}

View File

@@ -1,35 +0,0 @@
package cc.flogi.dev.smoothchunks.mixin;
import cc.flogi.dev.smoothchunks.client.handler.ChunkAnimationHandler;
import it.unimi.dsi.fastutil.objects.ObjectListIterator;
import net.minecraft.client.gl.VertexBuffer;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.WorldRenderer;
import net.minecraft.client.render.chunk.ChunkBuilder;
import net.minecraft.client.util.math.MatrixStack;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
/**
* @author Caden Kriese (flogic)
*
* Created on 09/25/2020
*/
@SuppressWarnings("rawtypes") @Mixin(WorldRenderer.class)
public abstract class WorldRendererMixin {
@Inject(
method = "renderLayer",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/client/gl/VertexBuffer;bind()V"),
locals = LocalCapture.CAPTURE_FAILHARD
)
private void renderLayerInject(RenderLayer renderLayer, MatrixStack matrixStack, double d, double e, double f,
CallbackInfo ci, boolean bl, ObjectListIterator objectListIterator,
WorldRenderer.ChunkInfo chunkInfo2, ChunkBuilder.BuiltChunk builtChunk, VertexBuffer vertexBuffer) {
ChunkAnimationHandler.get().updateChunk(builtChunk, matrixStack);
}
}

View File

@@ -1,18 +0,0 @@
package cc.flogi.dev.smoothchunks.util;
/**
* @author Caden Kriese (flogic)
*
* Created on 10/24/2020
*/
public final class UtilEasing {
private static final double PI = Math.PI;
public static double easeInOutSine(double completion) {
return -((Math.cos(PI * completion) - 1) / 2);
}
public static double easeOutSine(double completion) {
return Math.sin(PI * completion / 2);
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

View File

@@ -1,7 +0,0 @@
{
"text.autoconfig.smooth-chunks.title": "Smooth Chunks Config",
"text.autoconfig.smooth-chunks.option.loadAnimation": "Load Animation",
"text.autoconfig.smooth-chunks.option.duration": "Duration",
"text.autoconfig.smooth-chunks.option.translationAmount": "Translation Amount",
"text.autoconfig.smooth-chunks.option.disableNearby": "Disable for Nearby Chunks"
}

View File

@@ -1,7 +0,0 @@
{
"text.autoconfig.smooth-chunks.title": "平滑区块加载配置Smooth Chunk",
"text.autoconfig.smooth-chunks.option.loadAnimation": "区块加载动画",
"text.autoconfig.smooth-chunks.option.duration": "动画持续时间",
"text.autoconfig.smooth-chunks.option.translationAmount": "转换幅度",
"text.autoconfig.smooth-chunks.option.disableNearby": "禁用邻近区块动画"
}

View File

@@ -1,38 +0,0 @@
{
"schemaVersion": 1,
"id": "smooth-chunks",
"version": "${version}",
"name": "Smooth Chunks",
"description": "Smooth chunk load animations.",
"authors": [
"flogic"
],
"contact": {
"website": "flogi.cc",
"repo": "repo.flogi.cc"
},
"license": "MIT",
"icon": "assets/smooth-chunks/icon.png",
"environment": "client",
"accessWidener": "smooth-chunks.accesswidener",
"modmenu:clientsideOnly": "true",
"entrypoints": {
"modmenu": [
"cc.flogi.dev.smoothchunks.client.config.SmoothChunksModMenu"
],
"client": [
"cc.flogi.dev.smoothchunks.client.SmoothChunksClient"
],
"main": [
"cc.flogi.dev.smoothchunks.SmoothChunks"
]
},
"mixins": [
"smooth-chunks.mixins.json"
],
"depends": {
"fabricloader": ">=0.9.3+build.207",
"fabric": "*",
"minecraft": ">=1.16.2"
}
}

View File

@@ -1,4 +0,0 @@
accessWidener v1 named
accessible class net/minecraft/client/render/chunk/ChunkBuilder$BuiltChunk$RebuildTask
accessible class net/minecraft/client/render/WorldRenderer$ChunkInfo

View File

@@ -1,15 +0,0 @@
{
"required": true,
"minVersion": "0.8",
"package": "cc.flogi.dev.smoothchunks.mixin",
"compatibilityLevel": "JAVA_8",
"mixins": [],
"client": [
"BuiltChunkMixin",
"RebuildTaskMixin",
"WorldRendererMixin"
],
"injectors": {
"defaultRequire": 1
}
}