diff --git a/CustomPlayerModels-1.10/gradle.properties b/CustomPlayerModels-1.10/gradle.properties index d4b03efb..1083e59c 100644 --- a/CustomPlayerModels-1.10/gradle.properties +++ b/CustomPlayerModels-1.10/gradle.properties @@ -3,4 +3,4 @@ org.gradle.jvmargs=-Xmx3G org.gradle.daemon=false -mod_version=0.4.8a +mod_version=0.5.0a diff --git a/CustomPlayerModels-1.10/src/main/java/com/tom/cpm/client/ClientProxy.java b/CustomPlayerModels-1.10/src/main/java/com/tom/cpm/client/ClientProxy.java index 828c2b82..2bc4f00a 100644 --- a/CustomPlayerModels-1.10/src/main/java/com/tom/cpm/client/ClientProxy.java +++ b/CustomPlayerModels-1.10/src/main/java/com/tom/cpm/client/ClientProxy.java @@ -1,6 +1,5 @@ package com.tom.cpm.client; -import java.util.Map.Entry; import java.util.concurrent.Executor; import net.minecraft.client.Minecraft; @@ -21,11 +20,12 @@ import net.minecraft.client.renderer.VertexBuffer; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.client.resources.I18n; -import net.minecraft.client.settings.KeyBinding; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.network.PacketBuffer; import net.minecraft.network.play.client.CPacketCustomPayload; +import net.minecraft.scoreboard.ScoreObjective; +import net.minecraft.scoreboard.Scoreboard; import net.minecraft.scoreboard.Team; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.MathHelper; @@ -33,6 +33,7 @@ import net.minecraftforge.client.event.GuiOpenEvent; import net.minecraftforge.client.event.GuiScreenEvent; +import net.minecraftforge.client.event.GuiScreenEvent.DrawScreenEvent; import net.minecraftforge.client.event.RenderLivingEvent; import net.minecraftforge.client.event.RenderPlayerEvent; import net.minecraftforge.common.MinecraftForge; @@ -139,6 +140,16 @@ public void openGui(GuiOpenEvent openGui) { } } + @SubscribeEvent + public void drawGuiPre(DrawScreenEvent.Pre evt) { + PlayerProfile.inGui = true; + } + + @SubscribeEvent + public void drawGuiPost(DrawScreenEvent.Post evt) { + PlayerProfile.inGui = false; + } + public void renderSkull(ModelBase skullModel, GameProfile profile) { manager.bindSkull(profile, null, skullModel); manager.bindSkin(skullModel, TextureSheetType.SKIN); @@ -185,11 +196,7 @@ public void clientTick(ClientTickEvent evt) { Player.setEnableRendering(!Player.isEnableRendering()); } - for (Entry e : KeyBindings.quickAccess.entrySet()) { - if(e.getValue().isPressed()) { - mc.getPlayerRenderManager().getAnimationEngine().onKeybind(e.getKey()); - } - } + mc.getPlayerRenderManager().getAnimationEngine().updateKeys(KeyBindings.quickAccess); } @SubscribeEvent @@ -202,10 +209,15 @@ public void onRenderName(RenderLivingEvent.Specials.Pre ev if(st != null) { double d0 = evt.getEntity().getDistanceSqToEntity(minecraft.getRenderViewEntity()); if (d0 < 32*32) { + Scoreboard scoreboard = ((EntityPlayer) evt.getEntity()).getWorldScoreboard(); + ScoreObjective scoreobjective = scoreboard.getObjectiveInDisplaySlot(2); + double y = evt.getY(); + if (scoreobjective != null) + y += evt.getRenderer().getFontRendererFromRenderManager().FONT_HEIGHT * 1.15F * 0.025F; GlStateManager.pushMatrix(); GlStateManager.translate(0, 0.25F, 0); String str = ((ITextComponent) st.remap()).getFormattedText(); - renderLivingLabel(evt.getEntity(), str, evt.getX(), evt.getY(), evt.getZ(), 64); + renderLivingLabel(evt.getEntity(), str, evt.getX(), y, evt.getZ(), 64); GlStateManager.popMatrix(); } } diff --git a/CustomPlayerModels-1.10/src/main/java/com/tom/cpm/client/KeyBindings.java b/CustomPlayerModels-1.10/src/main/java/com/tom/cpm/client/KeyBindings.java index 42974a2f..80fbc11b 100644 --- a/CustomPlayerModels-1.10/src/main/java/com/tom/cpm/client/KeyBindings.java +++ b/CustomPlayerModels-1.10/src/main/java/com/tom/cpm/client/KeyBindings.java @@ -1,9 +1,7 @@ package com.tom.cpm.client; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.lwjgl.input.Keyboard; @@ -20,7 +18,7 @@ public class KeyBindings implements IKeybind { private static KeyConflictCtx conflictCtx = new KeyConflictCtx(); public static KeyBinding gestureMenuBinding, renderToggleBinding; - public static Map quickAccess = new HashMap<>(); + public static IKeybind[] quickAccess = new IKeybind[IKeybind.QUICK_ACCESS_KEYBINDS_COUNT]; public static void init() { gestureMenuBinding = new KeyBinding("key.cpm.gestureMenu", KeyConflictContext.IN_GAME, Keyboard.KEY_G, "key.cpm.category"); @@ -29,7 +27,7 @@ public static void init() { renderToggleBinding = new KeyBinding("key.cpm.renderToggle", KeyConflictContext.IN_GAME, 0, "key.cpm.category"); kbs.add(new KeyBindings(renderToggleBinding, "renderToggle")); - for(int i = 1;i<=6;i++) + for(int i = 1;i<=IKeybind.QUICK_ACCESS_KEYBINDS_COUNT;i++) createQA(i); } @@ -49,8 +47,9 @@ public boolean conflicts(IKeyConflictContext other) { private static void createQA(int id) { KeyBinding kb = new KeyBinding("key.cpm.qa_" + id, conflictCtx, 0, "key.cpm.category"); - kbs.add(new KeyBindings(kb, "qa_" + id)); - quickAccess.put(id, kb); + KeyBindings kbs = new KeyBindings(kb, "qa_" + id); + KeyBindings.kbs.add(kbs); + quickAccess[id - 1] = kbs; } public static List kbs = new ArrayList<>(); @@ -77,4 +76,9 @@ public String getBoundKey() { public String getName() { return name; } + + @Override + public boolean isPressed() { + return kb.isKeyDown(); + } } diff --git a/CustomPlayerModels-1.10/src/main/java/com/tom/cpm/client/PlayerProfile.java b/CustomPlayerModels-1.10/src/main/java/com/tom/cpm/client/PlayerProfile.java index 4174d6c9..ad91f968 100644 --- a/CustomPlayerModels-1.10/src/main/java/com/tom/cpm/client/PlayerProfile.java +++ b/CustomPlayerModels-1.10/src/main/java/com/tom/cpm/client/PlayerProfile.java @@ -30,6 +30,7 @@ import com.tom.cpm.shared.skin.PlayerTextureLoader; public class PlayerProfile extends Player { + public static boolean inGui; private final GameProfile profile; private String skinType; @@ -111,6 +112,7 @@ public void updateFromPlayer(EntityPlayer player) { animState.hurtTime = player.hurtTime; animState.isOnLadder = player.isOnLadder(); animState.isBurning = player.canRenderOnFire(); + animState.inGui = inGui; if(player.getActiveItemStack() != null && player.getActiveItemStack().getItem() instanceof ItemBow) { float f = 20F; diff --git a/CustomPlayerModels-1.12/gradle.properties b/CustomPlayerModels-1.12/gradle.properties index d4b03efb..1083e59c 100644 --- a/CustomPlayerModels-1.12/gradle.properties +++ b/CustomPlayerModels-1.12/gradle.properties @@ -3,4 +3,4 @@ org.gradle.jvmargs=-Xmx3G org.gradle.daemon=false -mod_version=0.4.8a +mod_version=0.5.0a diff --git a/CustomPlayerModels-1.12/src/main/java/com/tom/cpm/client/ClientProxy.java b/CustomPlayerModels-1.12/src/main/java/com/tom/cpm/client/ClientProxy.java index 9d6433dd..2fe6e9ac 100644 --- a/CustomPlayerModels-1.12/src/main/java/com/tom/cpm/client/ClientProxy.java +++ b/CustomPlayerModels-1.12/src/main/java/com/tom/cpm/client/ClientProxy.java @@ -1,6 +1,5 @@ package com.tom.cpm.client; -import java.util.Map.Entry; import java.util.concurrent.Executor; import net.minecraft.client.Minecraft; @@ -20,11 +19,12 @@ import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.client.resources.I18n; -import net.minecraft.client.settings.KeyBinding; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.network.PacketBuffer; import net.minecraft.network.play.client.CPacketCustomPayload; +import net.minecraft.scoreboard.ScoreObjective; +import net.minecraft.scoreboard.Scoreboard; import net.minecraft.scoreboard.Team; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.MathHelper; @@ -33,6 +33,7 @@ import net.minecraftforge.client.event.GuiOpenEvent; import net.minecraftforge.client.event.GuiScreenEvent; +import net.minecraftforge.client.event.GuiScreenEvent.DrawScreenEvent; import net.minecraftforge.client.event.PlayerSPPushOutOfBlocksEvent; import net.minecraftforge.client.event.RenderLivingEvent; import net.minecraftforge.client.event.RenderPlayerEvent; @@ -140,6 +141,16 @@ public void openGui(GuiOpenEvent openGui) { } } + @SubscribeEvent + public void drawGuiPre(DrawScreenEvent.Pre evt) { + PlayerProfile.inGui = true; + } + + @SubscribeEvent + public void drawGuiPost(DrawScreenEvent.Post evt) { + PlayerProfile.inGui = false; + } + public void renderSkull(ModelBase skullModel, GameProfile profile) { manager.bindSkull(profile, null, skullModel); manager.bindSkin(skullModel, TextureSheetType.SKIN); @@ -182,11 +193,7 @@ public void clientTick(ClientTickEvent evt) { Player.setEnableRendering(!Player.isEnableRendering()); } - for (Entry e : KeyBindings.quickAccess.entrySet()) { - if(e.getValue().isPressed()) { - mc.getPlayerRenderManager().getAnimationEngine().onKeybind(e.getKey()); - } - } + mc.getPlayerRenderManager().getAnimationEngine().updateKeys(KeyBindings.quickAccess); } @SubscribeEvent @@ -199,10 +206,15 @@ public void onRenderName(RenderLivingEvent.Specials.Pre ev if(st != null) { double d0 = evt.getEntity().getDistanceSq(minecraft.getRenderViewEntity()); if (d0 < 32*32) { + Scoreboard scoreboard = ((EntityPlayer) evt.getEntity()).getWorldScoreboard(); + ScoreObjective scoreobjective = scoreboard.getObjectiveInDisplaySlot(2); + double y = evt.getY(); + if (scoreobjective != null) + y += evt.getRenderer().getFontRendererFromRenderManager().FONT_HEIGHT * 1.15F * 0.025F; GlStateManager.pushMatrix(); GlStateManager.translate(0, 0.25F, 0); String str = ((ITextComponent) st.remap()).getFormattedText(); - renderLivingLabel(evt.getEntity(), str, evt.getX(), evt.getY(), evt.getZ(), 64); + renderLivingLabel(evt.getEntity(), str, evt.getX(), y, evt.getZ(), 64); GlStateManager.popMatrix(); } } diff --git a/CustomPlayerModels-1.12/src/main/java/com/tom/cpm/client/KeyBindings.java b/CustomPlayerModels-1.12/src/main/java/com/tom/cpm/client/KeyBindings.java index 7c950770..4c0288c2 100644 --- a/CustomPlayerModels-1.12/src/main/java/com/tom/cpm/client/KeyBindings.java +++ b/CustomPlayerModels-1.12/src/main/java/com/tom/cpm/client/KeyBindings.java @@ -1,9 +1,7 @@ package com.tom.cpm.client; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.lwjgl.input.Keyboard; @@ -20,7 +18,7 @@ public class KeyBindings implements IKeybind { private static KeyConflictCtx conflictCtx = new KeyConflictCtx(); public static KeyBinding gestureMenuBinding, renderToggleBinding; - public static Map quickAccess = new HashMap<>(); + public static IKeybind[] quickAccess = new IKeybind[IKeybind.QUICK_ACCESS_KEYBINDS_COUNT]; public static void init() { gestureMenuBinding = new KeyBinding("key.cpm.gestureMenu", KeyConflictContext.IN_GAME, Keyboard.KEY_G, "key.cpm.category"); @@ -29,7 +27,7 @@ public static void init() { renderToggleBinding = new KeyBinding("key.cpm.renderToggle", KeyConflictContext.IN_GAME, 0, "key.cpm.category"); kbs.add(new KeyBindings(renderToggleBinding, "renderToggle")); - for(int i = 1;i<=6;i++) + for(int i = 1;i<=IKeybind.QUICK_ACCESS_KEYBINDS_COUNT;i++) createQA(i); } @@ -49,8 +47,9 @@ public boolean conflicts(IKeyConflictContext other) { private static void createQA(int id) { KeyBinding kb = new KeyBinding("key.cpm.qa_" + id, conflictCtx, 0, "key.cpm.category"); - kbs.add(new KeyBindings(kb, "qa_" + id)); - quickAccess.put(id, kb); + KeyBindings kbs = new KeyBindings(kb, "qa_" + id); + KeyBindings.kbs.add(kbs); + quickAccess[id - 1] = kbs; } public static List kbs = new ArrayList<>(); @@ -77,4 +76,9 @@ public String getBoundKey() { public String getName() { return name; } + + @Override + public boolean isPressed() { + return kb.isKeyDown(); + } } diff --git a/CustomPlayerModels-1.12/src/main/java/com/tom/cpm/client/PlayerProfile.java b/CustomPlayerModels-1.12/src/main/java/com/tom/cpm/client/PlayerProfile.java index baaa6bf3..634163e2 100644 --- a/CustomPlayerModels-1.12/src/main/java/com/tom/cpm/client/PlayerProfile.java +++ b/CustomPlayerModels-1.12/src/main/java/com/tom/cpm/client/PlayerProfile.java @@ -30,6 +30,7 @@ import com.tom.cpm.shared.skin.PlayerTextureLoader; public class PlayerProfile extends Player { + public static boolean inGui; private final GameProfile profile; private String skinType; @@ -111,6 +112,7 @@ public void updateFromPlayer(EntityPlayer player) { animState.hurtTime = player.hurtTime; animState.isOnLadder = player.isOnLadder(); animState.isBurning = player.canRenderOnFire(); + animState.inGui = inGui; if(player.getActiveItemStack().getItem() instanceof ItemBow) { float f = 20F; diff --git a/CustomPlayerModels-1.16/gradle.properties b/CustomPlayerModels-1.16/gradle.properties index d4b03efb..1083e59c 100644 --- a/CustomPlayerModels-1.16/gradle.properties +++ b/CustomPlayerModels-1.16/gradle.properties @@ -3,4 +3,4 @@ org.gradle.jvmargs=-Xmx3G org.gradle.daemon=false -mod_version=0.4.8a +mod_version=0.5.0a diff --git a/CustomPlayerModels-1.16/src/main/java/com/tom/cpm/client/CustomPlayerModelsClient.java b/CustomPlayerModels-1.16/src/main/java/com/tom/cpm/client/CustomPlayerModelsClient.java index 4b995633..bc68f147 100644 --- a/CustomPlayerModels-1.16/src/main/java/com/tom/cpm/client/CustomPlayerModelsClient.java +++ b/CustomPlayerModels-1.16/src/main/java/com/tom/cpm/client/CustomPlayerModelsClient.java @@ -1,7 +1,5 @@ package com.tom.cpm.client; -import java.util.Map.Entry; - import net.minecraft.client.Minecraft; import net.minecraft.client.entity.player.AbstractClientPlayerEntity; import net.minecraft.client.entity.player.ClientPlayerEntity; @@ -16,7 +14,6 @@ import net.minecraft.client.renderer.entity.model.PlayerModel; import net.minecraft.client.renderer.model.Model; import net.minecraft.client.renderer.texture.OverlayTexture; -import net.minecraft.client.settings.KeyBinding; import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.player.PlayerEntity; @@ -31,6 +28,7 @@ import net.minecraftforge.client.event.ClientPlayerNetworkEvent; import net.minecraftforge.client.event.GuiOpenEvent; import net.minecraftforge.client.event.GuiScreenEvent; +import net.minecraftforge.client.event.GuiScreenEvent.DrawScreenEvent; import net.minecraftforge.client.event.RenderPlayerEvent; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.TickEvent.ClientTickEvent; @@ -176,11 +174,7 @@ public void clientTick(ClientTickEvent evt) { Player.setEnableRendering(!Player.isEnableRendering()); } - for (Entry e : KeyBindings.quickAccess.entrySet()) { - if(e.getValue().consumeClick()) { - mc.getPlayerRenderManager().getAnimationEngine().onKeybind(e.getKey()); - } - } + mc.getPlayerRenderManager().getAnimationEngine().updateKeys(KeyBindings.quickAccess); } @SubscribeEvent @@ -193,6 +187,16 @@ public void openGui(GuiOpenEvent openGui) { } } + @SubscribeEvent + public void drawGuiPre(DrawScreenEvent.Pre evt) { + PlayerProfile.inGui = true; + } + + @SubscribeEvent + public void drawGuiPost(DrawScreenEvent.Post evt) { + PlayerProfile.inGui = false; + } + public static class Button extends net.minecraft.client.gui.widget.button.Button { public Button(int x, int y, Runnable r) { diff --git a/CustomPlayerModels-1.16/src/main/java/com/tom/cpm/client/KeyBindings.java b/CustomPlayerModels-1.16/src/main/java/com/tom/cpm/client/KeyBindings.java index b259d009..c86d6aa5 100644 --- a/CustomPlayerModels-1.16/src/main/java/com/tom/cpm/client/KeyBindings.java +++ b/CustomPlayerModels-1.16/src/main/java/com/tom/cpm/client/KeyBindings.java @@ -1,9 +1,7 @@ package com.tom.cpm.client; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.lwjgl.glfw.GLFW; @@ -21,14 +19,15 @@ public class KeyBindings implements IKeybind { private static KeyConflictCtx conflictCtx = new KeyConflictCtx(); public static KeyBinding gestureMenuBinding, renderToggleBinding; - public static Map quickAccess = new HashMap<>(); + public static IKeybind[] quickAccess = new IKeybind[IKeybind.QUICK_ACCESS_KEYBINDS_COUNT]; + public static void init() { gestureMenuBinding = new KeyBinding("key.cpm.gestureMenu", KeyConflictContext.IN_GAME, InputMappings.Type.KEYSYM.getOrCreate(GLFW.GLFW_KEY_G), "key.cpm.category"); renderToggleBinding = new KeyBinding("key.cpm.renderToggle", KeyConflictContext.IN_GAME, InputMappings.UNKNOWN, "key.cpm.category"); kbs.add(new KeyBindings(gestureMenuBinding, "gestureMenu")); kbs.add(new KeyBindings(renderToggleBinding, "renderToggle")); - for(int i = 1;i<=6;i++) + for(int i = 1;i<=IKeybind.QUICK_ACCESS_KEYBINDS_COUNT;i++) createQA(i); } @@ -48,8 +47,9 @@ public boolean conflicts(IKeyConflictContext other) { private static void createQA(int id) { KeyBinding kb = new KeyBinding("key.cpm.qa_" + id, conflictCtx, InputMappings.UNKNOWN, "key.cpm.category"); - kbs.add(new KeyBindings(kb, "qa_" + id)); - quickAccess.put(id, kb); + KeyBindings kbs = new KeyBindings(kb, "qa_" + id); + KeyBindings.kbs.add(kbs); + quickAccess[id - 1] = kbs; } public static List kbs = new ArrayList<>(); @@ -77,4 +77,9 @@ public String getBoundKey() { public String getName() { return name; } + + @Override + public boolean isPressed() { + return kb.isDown(); + } } diff --git a/CustomPlayerModels-1.16/src/main/java/com/tom/cpm/client/PlayerProfile.java b/CustomPlayerModels-1.16/src/main/java/com/tom/cpm/client/PlayerProfile.java index 145470b8..04e37e21 100644 --- a/CustomPlayerModels-1.16/src/main/java/com/tom/cpm/client/PlayerProfile.java +++ b/CustomPlayerModels-1.16/src/main/java/com/tom/cpm/client/PlayerProfile.java @@ -1,8 +1,11 @@ package com.tom.cpm.client; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; import java.util.Map; import java.util.UUID; import java.util.concurrent.CompletableFuture; +import java.util.function.BooleanSupplier; import net.minecraft.block.AbstractSkullBlock; import net.minecraft.client.Minecraft; @@ -20,6 +23,8 @@ import net.minecraft.item.ItemStack; import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fml.ModList; + import com.mojang.authlib.GameProfile; import com.mojang.authlib.minecraft.MinecraftProfileTexture; import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type; @@ -34,6 +39,27 @@ import com.tom.cpm.shared.skin.PlayerTextureLoader; public class PlayerProfile extends Player { + public static boolean inGui; + public static BooleanSupplier inFirstPerson; + static { + inFirstPerson = () -> false; + if(ModList.get().isLoaded("firstpersonmod")) { + try { + MethodHandle h = MethodHandles.lookup().unreflectGetter(Class.forName("dev.tr7zw.firstperson.FirstPersonModelCore").getDeclaredField("isRenderingPlayer")); + inFirstPerson = () -> { + try { + return (boolean) h.invoke(); + } catch (Throwable e) { + inFirstPerson = () -> false; + return false; + } + }; + inFirstPerson.getAsBoolean(); + } catch (Throwable e) { + } + } + } + private final GameProfile profile; private String skinType; @@ -137,6 +163,8 @@ public void updateFromPlayer(PlayerEntity player) { animState.hurtTime = player.hurtTime; animState.isOnLadder = player.onClimbable(); animState.isBurning = player.displayFireAnimation(); + animState.inGui = inGui; + animState.firstPersonMod = inFirstPerson.getAsBoolean(); if(player.getUseItem().getItem() instanceof CrossbowItem) { float f = CrossbowItem.getChargeDuration(player.getUseItem()); diff --git a/CustomPlayerModels-1.16/src/main/java/com/tom/cpm/client/VBufferOut.java b/CustomPlayerModels-1.16/src/main/java/com/tom/cpm/client/VBufferOut.java index fe550c55..b0b4c0b3 100644 --- a/CustomPlayerModels-1.16/src/main/java/com/tom/cpm/client/VBufferOut.java +++ b/CustomPlayerModels-1.16/src/main/java/com/tom/cpm/client/VBufferOut.java @@ -16,8 +16,8 @@ public class VBufferOut implements BufferOutput { public VBufferOut(int light, int overlay, MatrixStack matrixStackIn) { this.light = light; this.overlay = overlay; - mat4 = matrixStackIn.last().pose(); - mat3 = matrixStackIn.last().normal(); + mat4 = new Matrix4f(matrixStackIn.last().pose()); + mat3 = new Matrix3f(matrixStackIn.last().normal()); } @Override diff --git a/CustomPlayerModels-1.16/src/main/java/com/tom/cpm/mixin/PlayerRendererMixin.java b/CustomPlayerModels-1.16/src/main/java/com/tom/cpm/mixin/PlayerRendererMixin.java index 6e9b95a2..0aab1397 100644 --- a/CustomPlayerModels-1.16/src/main/java/com/tom/cpm/mixin/PlayerRendererMixin.java +++ b/CustomPlayerModels-1.16/src/main/java/com/tom/cpm/mixin/PlayerRendererMixin.java @@ -81,8 +81,15 @@ public void onRenderLeftArmPost(MatrixStack matrices, IRenderTypeBuffer vertexCo } @Inject(at = @At("HEAD"), method = "renderNameTag(Lnet/minecraft/client/entity/player/AbstractClientPlayerEntity;Lnet/minecraft/util/text/ITextComponent;Lcom/mojang/blaze3d/matrix/MatrixStack;Lnet/minecraft/client/renderer/IRenderTypeBuffer;I)V", cancellable = true) - public void onRenderName(AbstractClientPlayerEntity entityIn, ITextComponent displayNameIn, MatrixStack matrixStackIn, IRenderTypeBuffer bufferIn, int packedLightIn, CallbackInfo cbi) { + public void onRenderName1(AbstractClientPlayerEntity entityIn, ITextComponent displayNameIn, MatrixStack matrixStackIn, IRenderTypeBuffer bufferIn, int packedLightIn, CallbackInfo cbi) { if(!Player.isEnableNames())cbi.cancel(); + } + + @Inject(at = @At(value = "INVOKE", + target = "Lnet/minecraft/client/renderer/entity/LivingRenderer;renderNameTag(Lnet/minecraft/entity/Entity;Lnet/minecraft/util/text/ITextComponent;Lcom/mojang/blaze3d/matrix/MatrixStack;Lnet/minecraft/client/renderer/IRenderTypeBuffer;I)V", + ordinal = 1), + method = "renderNameTag(Lnet/minecraft/client/entity/player/AbstractClientPlayerEntity;Lnet/minecraft/util/text/ITextComponent;Lcom/mojang/blaze3d/matrix/MatrixStack;Lnet/minecraft/client/renderer/IRenderTypeBuffer;I)V") + public void onRenderName2(AbstractClientPlayerEntity entityIn, ITextComponent displayNameIn, MatrixStack matrixStackIn, IRenderTypeBuffer bufferIn, int packedLightIn, CallbackInfo cbi) { if(Player.isEnableLoadingInfo()) CustomPlayerModelsClient.renderNameTag(this, entityIn, entityIn.getGameProfile(), ModelDefinitionLoader.PLAYER_UNIQUE, matrixStackIn, bufferIn, packedLightIn); } diff --git a/CustomPlayerModels-1.17/gradle.properties b/CustomPlayerModels-1.17/gradle.properties index d4b03efb..1083e59c 100644 --- a/CustomPlayerModels-1.17/gradle.properties +++ b/CustomPlayerModels-1.17/gradle.properties @@ -3,4 +3,4 @@ org.gradle.jvmargs=-Xmx3G org.gradle.daemon=false -mod_version=0.4.8a +mod_version=0.5.0a diff --git a/CustomPlayerModels-1.17/src/main/java/com/tom/cpm/CustomPlayerModels.java b/CustomPlayerModels-1.17/src/main/java/com/tom/cpm/CustomPlayerModels.java index 3a39c805..e610fd3e 100644 --- a/CustomPlayerModels-1.17/src/main/java/com/tom/cpm/CustomPlayerModels.java +++ b/CustomPlayerModels-1.17/src/main/java/com/tom/cpm/CustomPlayerModels.java @@ -91,7 +91,7 @@ private void processIMC(final InterModProcessEvent event) { }); LOG.info("Customizable Player Models IMC processed: " + api.getPluginStatus()); api.buildCommon().player(Player.class).init(); - DistExecutor.safeRunWhenOn(Dist.CLIENT, () -> () -> CustomPlayerModelsClient.INSTANCE.apiInit()); + DistExecutor.safeRunWhenOn(Dist.CLIENT, () -> CustomPlayerModelsClient::apiInit); } @Override diff --git a/CustomPlayerModels-1.17/src/main/java/com/tom/cpm/client/CustomPlayerModelsClient.java b/CustomPlayerModels-1.17/src/main/java/com/tom/cpm/client/CustomPlayerModelsClient.java index 2ed28dae..f525b0bd 100644 --- a/CustomPlayerModels-1.17/src/main/java/com/tom/cpm/client/CustomPlayerModelsClient.java +++ b/CustomPlayerModels-1.17/src/main/java/com/tom/cpm/client/CustomPlayerModelsClient.java @@ -2,10 +2,8 @@ import java.io.IOException; import java.util.List; -import java.util.Map.Entry; import java.util.function.Consumer; -import net.minecraft.client.KeyMapping; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screens.SkinCustomizationScreen; import net.minecraft.client.gui.screens.TitleScreen; @@ -35,6 +33,7 @@ import net.minecraftforge.client.event.ClientPlayerNetworkEvent; import net.minecraftforge.client.event.GuiOpenEvent; import net.minecraftforge.client.event.GuiScreenEvent; +import net.minecraftforge.client.event.GuiScreenEvent.DrawScreenEvent; import net.minecraftforge.client.event.RegisterShadersEvent; import net.minecraftforge.client.event.RenderPlayerEvent; import net.minecraftforge.common.MinecraftForge; @@ -110,7 +109,7 @@ public void init() { ModLoadingContext.get().registerExtensionPoint(ConfigGuiHandler.ConfigGuiFactory.class, () -> new ConfigGuiHandler.ConfigGuiFactory((mc, scr) -> new GuiImpl(SettingsGui::new, scr))); } - public void apiInit() { + public static void apiInit() { CustomPlayerModels.api.buildClient().voicePlayer(net.minecraft.world.entity.player.Player.class). renderApi(Model.class, ResourceLocation.class, RenderType.class, MultiBufferSource.class, GameProfile.class, ModelTexture::new). localModelApi(GameProfile::new).init(); @@ -189,11 +188,7 @@ public void clientTick(ClientTickEvent evt) { Player.setEnableRendering(!Player.isEnableRendering()); } - for (Entry e : KeyBindings.quickAccess.entrySet()) { - if(e.getValue().consumeClick()) { - mc.getPlayerRenderManager().getAnimationEngine().onKeybind(e.getKey()); - } - } + mc.getPlayerRenderManager().getAnimationEngine().updateKeys(KeyBindings.quickAccess); } @SubscribeEvent @@ -206,6 +201,16 @@ public void openGui(GuiOpenEvent openGui) { } } + @SubscribeEvent + public void drawGuiPre(DrawScreenEvent.Pre evt) { + PlayerProfile.inGui = true; + } + + @SubscribeEvent + public void drawGuiPost(DrawScreenEvent.Post evt) { + PlayerProfile.inGui = false; + } + private void registerShaders(RegisterShadersEvent evt) { } diff --git a/CustomPlayerModels-1.17/src/main/java/com/tom/cpm/client/KeyBindings.java b/CustomPlayerModels-1.17/src/main/java/com/tom/cpm/client/KeyBindings.java index 930d30c0..3e1068d3 100644 --- a/CustomPlayerModels-1.17/src/main/java/com/tom/cpm/client/KeyBindings.java +++ b/CustomPlayerModels-1.17/src/main/java/com/tom/cpm/client/KeyBindings.java @@ -1,9 +1,7 @@ package com.tom.cpm.client; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.lwjgl.glfw.GLFW; @@ -22,14 +20,15 @@ public class KeyBindings implements IKeybind { private static KeyConflictCtx conflictCtx = new KeyConflictCtx(); public static KeyMapping gestureMenuBinding, renderToggleBinding; - public static Map quickAccess = new HashMap<>(); + public static IKeybind[] quickAccess = new IKeybind[IKeybind.QUICK_ACCESS_KEYBINDS_COUNT]; + public static void init() { gestureMenuBinding = new KeyMapping("key.cpm.gestureMenu", KeyConflictContext.IN_GAME, InputConstants.Type.KEYSYM.getOrCreate(GLFW.GLFW_KEY_G), "key.cpm.category"); renderToggleBinding = new KeyMapping("key.cpm.renderToggle", KeyConflictContext.IN_GAME, InputConstants.UNKNOWN, "key.cpm.category"); kbs.add(new KeyBindings(gestureMenuBinding, "gestureMenu")); kbs.add(new KeyBindings(renderToggleBinding, "renderToggle")); - for(int i = 1;i<=6;i++) + for(int i = 1;i<=IKeybind.QUICK_ACCESS_KEYBINDS_COUNT;i++) createQA(i); } @@ -49,8 +48,9 @@ public boolean conflicts(IKeyConflictContext other) { private static void createQA(int id) { KeyMapping kb = new KeyMapping("key.cpm.qa_" + id, conflictCtx, InputConstants.UNKNOWN, "key.cpm.category"); - kbs.add(new KeyBindings(kb, "qa_" + id)); - quickAccess.put(id, kb); + KeyBindings kbs = new KeyBindings(kb, "qa_" + id); + KeyBindings.kbs.add(kbs); + quickAccess[id - 1] = kbs; } public static List kbs = new ArrayList<>(); @@ -78,4 +78,9 @@ public String getBoundKey() { public String getName() { return name; } + + @Override + public boolean isPressed() { + return kb.isDown(); + } } diff --git a/CustomPlayerModels-1.17/src/main/java/com/tom/cpm/client/PlayerProfile.java b/CustomPlayerModels-1.17/src/main/java/com/tom/cpm/client/PlayerProfile.java index 44206ef8..2fe57351 100644 --- a/CustomPlayerModels-1.17/src/main/java/com/tom/cpm/client/PlayerProfile.java +++ b/CustomPlayerModels-1.17/src/main/java/com/tom/cpm/client/PlayerProfile.java @@ -1,8 +1,11 @@ package com.tom.cpm.client; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; import java.util.Map; import java.util.UUID; import java.util.concurrent.CompletableFuture; +import java.util.function.BooleanSupplier; import net.minecraft.client.Minecraft; import net.minecraft.client.model.PlayerModel; @@ -19,6 +22,8 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.AbstractSkullBlock; +import net.minecraftforge.fml.ModList; + import com.mojang.authlib.GameProfile; import com.mojang.authlib.minecraft.MinecraftProfileTexture; import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type; @@ -33,6 +38,27 @@ import com.tom.cpm.shared.skin.PlayerTextureLoader; public class PlayerProfile extends Player { + public static boolean inGui; + public static BooleanSupplier inFirstPerson; + static { + inFirstPerson = () -> false; + if(ModList.get().isLoaded("firstpersonmod")) { + try { + MethodHandle h = MethodHandles.lookup().unreflectGetter(Class.forName("dev.tr7zw.firstperson.FirstPersonModelCore").getDeclaredField("isRenderingPlayer")); + inFirstPerson = () -> { + try { + return (boolean) h.invoke(); + } catch (Throwable e) { + inFirstPerson = () -> false; + return false; + } + }; + inFirstPerson.getAsBoolean(); + } catch (Throwable e) { + } + } + } + private final GameProfile profile; private String skinType; @@ -135,6 +161,8 @@ public void updateFromPlayer(net.minecraft.world.entity.player.Player player) { animState.isOnLadder = player.onClimbable(); animState.isBurning = player.displayFireAnimation(); animState.isFreezing = player.getTicksFrozen() > 0; + animState.inGui = inGui; + animState.firstPersonMod = inFirstPerson.getAsBoolean(); if(player.getUseItem().getItem() instanceof CrossbowItem) { float f = CrossbowItem.getChargeDuration(player.getUseItem()); diff --git a/CustomPlayerModels-1.17/src/main/java/com/tom/cpm/client/VBufferOut.java b/CustomPlayerModels-1.17/src/main/java/com/tom/cpm/client/VBufferOut.java index b262dd3a..7d321a4a 100644 --- a/CustomPlayerModels-1.17/src/main/java/com/tom/cpm/client/VBufferOut.java +++ b/CustomPlayerModels-1.17/src/main/java/com/tom/cpm/client/VBufferOut.java @@ -15,8 +15,8 @@ public class VBufferOut implements BufferOutput { public VBufferOut(int light, int overlay, PoseStack matrixStackIn) { this.light = light; this.overlay = overlay; - mat4 = matrixStackIn.last().pose(); - mat3 = matrixStackIn.last().normal(); + mat4 = new Matrix4f(matrixStackIn.last().pose()); + mat3 = new Matrix3f(matrixStackIn.last().normal()); } @Override diff --git a/CustomPlayerModels-1.17/src/main/java/com/tom/cpm/mixin/PlayerRendererMixin.java b/CustomPlayerModels-1.17/src/main/java/com/tom/cpm/mixin/PlayerRendererMixin.java index fd11ed0e..c0290aba 100644 --- a/CustomPlayerModels-1.17/src/main/java/com/tom/cpm/mixin/PlayerRendererMixin.java +++ b/CustomPlayerModels-1.17/src/main/java/com/tom/cpm/mixin/PlayerRendererMixin.java @@ -81,8 +81,15 @@ public void onRenderLeftArmPost(PoseStack matrices, MultiBufferSource vertexCons } @Inject(at = @At("HEAD"), method = "renderNameTag(Lnet/minecraft/client/player/AbstractClientPlayer;Lnet/minecraft/network/chat/Component;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V", cancellable = true) - public void onRenderName(AbstractClientPlayer entityIn, Component displayNameIn, PoseStack matrixStackIn, MultiBufferSource bufferIn, int packedLightIn, CallbackInfo cbi) { + public void onRenderName1(AbstractClientPlayer entityIn, Component displayNameIn, PoseStack matrixStackIn, MultiBufferSource bufferIn, int packedLightIn, CallbackInfo cbi) { if(!Player.isEnableNames())cbi.cancel(); + } + + @Inject(at = @At(value = "INVOKE", + target = "Lnet/minecraft/client/renderer/entity/LivingEntityRenderer;renderNameTag(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/network/chat/Component;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V", + ordinal = 1), + method = "renderNameTag(Lnet/minecraft/client/player/AbstractClientPlayer;Lnet/minecraft/network/chat/Component;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V") + public void onRenderName2(AbstractClientPlayer entityIn, Component displayNameIn, PoseStack matrixStackIn, MultiBufferSource bufferIn, int packedLightIn, CallbackInfo cbi) { if(Player.isEnableLoadingInfo()) CustomPlayerModelsClient.renderNameTag(this, entityIn, entityIn.getGameProfile(), ModelDefinitionLoader.PLAYER_UNIQUE, matrixStackIn, bufferIn, packedLightIn); } diff --git a/CustomPlayerModels-1.18/gradle.properties b/CustomPlayerModels-1.18/gradle.properties index d4b03efb..1083e59c 100644 --- a/CustomPlayerModels-1.18/gradle.properties +++ b/CustomPlayerModels-1.18/gradle.properties @@ -3,4 +3,4 @@ org.gradle.jvmargs=-Xmx3G org.gradle.daemon=false -mod_version=0.4.8a +mod_version=0.5.0a diff --git a/CustomPlayerModels-1.18/src/main/java/com/tom/cpm/client/CustomPlayerModelsClient.java b/CustomPlayerModels-1.18/src/main/java/com/tom/cpm/client/CustomPlayerModelsClient.java index c2cc785c..15dceff3 100644 --- a/CustomPlayerModels-1.18/src/main/java/com/tom/cpm/client/CustomPlayerModelsClient.java +++ b/CustomPlayerModels-1.18/src/main/java/com/tom/cpm/client/CustomPlayerModelsClient.java @@ -2,10 +2,8 @@ import java.io.IOException; import java.util.List; -import java.util.Map.Entry; import java.util.function.Consumer; -import net.minecraft.client.KeyMapping; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screens.SkinCustomizationScreen; import net.minecraft.client.gui.screens.TitleScreen; @@ -37,6 +35,7 @@ import net.minecraftforge.client.event.RegisterShadersEvent; import net.minecraftforge.client.event.RenderPlayerEvent; import net.minecraftforge.client.event.ScreenEvent; +import net.minecraftforge.client.event.ScreenEvent.DrawScreenEvent; import net.minecraftforge.client.event.ScreenOpenEvent; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.TickEvent.ClientTickEvent; @@ -186,11 +185,7 @@ public void clientTick(ClientTickEvent evt) { Player.setEnableRendering(!Player.isEnableRendering()); } - for (Entry e : KeyBindings.quickAccess.entrySet()) { - if(e.getValue().consumeClick()) { - mc.getPlayerRenderManager().getAnimationEngine().onKeybind(e.getKey()); - } - } + mc.getPlayerRenderManager().getAnimationEngine().updateKeys(KeyBindings.quickAccess); } @SubscribeEvent @@ -203,6 +198,16 @@ public void openGui(ScreenOpenEvent openGui) { } } + @SubscribeEvent + public void drawGuiPre(DrawScreenEvent.Pre evt) { + PlayerProfile.inGui = true; + } + + @SubscribeEvent + public void drawGuiPost(DrawScreenEvent.Post evt) { + PlayerProfile.inGui = false; + } + private void registerShaders(RegisterShadersEvent evt) { } diff --git a/CustomPlayerModels-1.18/src/main/java/com/tom/cpm/client/KeyBindings.java b/CustomPlayerModels-1.18/src/main/java/com/tom/cpm/client/KeyBindings.java index 53249fc2..d71109fd 100644 --- a/CustomPlayerModels-1.18/src/main/java/com/tom/cpm/client/KeyBindings.java +++ b/CustomPlayerModels-1.18/src/main/java/com/tom/cpm/client/KeyBindings.java @@ -1,9 +1,7 @@ package com.tom.cpm.client; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.lwjgl.glfw.GLFW; @@ -22,14 +20,15 @@ public class KeyBindings implements IKeybind { private static KeyConflictCtx conflictCtx = new KeyConflictCtx(); public static KeyMapping gestureMenuBinding, renderToggleBinding; - public static Map quickAccess = new HashMap<>(); + public static IKeybind[] quickAccess = new IKeybind[IKeybind.QUICK_ACCESS_KEYBINDS_COUNT]; + public static void init() { gestureMenuBinding = new KeyMapping("key.cpm.gestureMenu", KeyConflictContext.IN_GAME, InputConstants.Type.KEYSYM.getOrCreate(GLFW.GLFW_KEY_G), "key.cpm.category"); renderToggleBinding = new KeyMapping("key.cpm.renderToggle", KeyConflictContext.IN_GAME, InputConstants.UNKNOWN, "key.cpm.category"); kbs.add(new KeyBindings(gestureMenuBinding, "gestureMenu")); kbs.add(new KeyBindings(renderToggleBinding, "renderToggle")); - for(int i = 1;i<=6;i++) + for(int i = 1;i<=IKeybind.QUICK_ACCESS_KEYBINDS_COUNT;i++) createQA(i); } @@ -49,8 +48,9 @@ public boolean conflicts(IKeyConflictContext other) { private static void createQA(int id) { KeyMapping kb = new KeyMapping("key.cpm.qa_" + id, conflictCtx, InputConstants.UNKNOWN, "key.cpm.category"); - kbs.add(new KeyBindings(kb, "qa_" + id)); - quickAccess.put(id, kb); + KeyBindings kbs = new KeyBindings(kb, "qa_" + id); + KeyBindings.kbs.add(kbs); + quickAccess[id - 1] = kbs; } public static List kbs = new ArrayList<>(); @@ -78,4 +78,9 @@ public String getBoundKey() { public String getName() { return name; } + + @Override + public boolean isPressed() { + return kb.isDown(); + } } diff --git a/CustomPlayerModels-1.18/src/main/java/com/tom/cpm/client/PlayerProfile.java b/CustomPlayerModels-1.18/src/main/java/com/tom/cpm/client/PlayerProfile.java index 86515934..382658e9 100644 --- a/CustomPlayerModels-1.18/src/main/java/com/tom/cpm/client/PlayerProfile.java +++ b/CustomPlayerModels-1.18/src/main/java/com/tom/cpm/client/PlayerProfile.java @@ -1,8 +1,11 @@ package com.tom.cpm.client; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; import java.util.Map; import java.util.UUID; import java.util.concurrent.CompletableFuture; +import java.util.function.BooleanSupplier; import net.minecraft.client.Minecraft; import net.minecraft.client.model.PlayerModel; @@ -19,6 +22,8 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.AbstractSkullBlock; +import net.minecraftforge.fml.ModList; + import com.mojang.authlib.GameProfile; import com.mojang.authlib.minecraft.MinecraftProfileTexture; import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type; @@ -33,6 +38,27 @@ import com.tom.cpm.shared.skin.PlayerTextureLoader; public class PlayerProfile extends Player { + public static boolean inGui; + public static BooleanSupplier inFirstPerson; + static { + inFirstPerson = () -> false; + if(ModList.get().isLoaded("firstpersonmod")) { + try { + MethodHandle h = MethodHandles.lookup().unreflectGetter(Class.forName("dev.tr7zw.firstperson.FirstPersonModelCore").getDeclaredField("isRenderingPlayer")); + inFirstPerson = () -> { + try { + return (boolean) h.invoke(); + } catch (Throwable e) { + inFirstPerson = () -> false; + return false; + } + }; + inFirstPerson.getAsBoolean(); + } catch (Throwable e) { + } + } + } + private final GameProfile profile; private String skinType; @@ -137,6 +163,8 @@ public void updateFromPlayer(net.minecraft.world.entity.player.Player player) { animState.isOnLadder = player.onClimbable(); animState.isBurning = player.displayFireAnimation(); animState.isFreezing = player.getTicksFrozen() > 0; + animState.inGui = inGui; + animState.firstPersonMod = inFirstPerson.getAsBoolean(); if(player.getUseItem().getItem() instanceof CrossbowItem) { float f = CrossbowItem.getChargeDuration(player.getUseItem()); diff --git a/CustomPlayerModels-1.18/src/main/java/com/tom/cpm/client/VBufferOut.java b/CustomPlayerModels-1.18/src/main/java/com/tom/cpm/client/VBufferOut.java index b262dd3a..7d321a4a 100644 --- a/CustomPlayerModels-1.18/src/main/java/com/tom/cpm/client/VBufferOut.java +++ b/CustomPlayerModels-1.18/src/main/java/com/tom/cpm/client/VBufferOut.java @@ -15,8 +15,8 @@ public class VBufferOut implements BufferOutput { public VBufferOut(int light, int overlay, PoseStack matrixStackIn) { this.light = light; this.overlay = overlay; - mat4 = matrixStackIn.last().pose(); - mat3 = matrixStackIn.last().normal(); + mat4 = new Matrix4f(matrixStackIn.last().pose()); + mat3 = new Matrix3f(matrixStackIn.last().normal()); } @Override diff --git a/CustomPlayerModels-1.18/src/main/java/com/tom/cpm/mixin/PlayerRendererMixin.java b/CustomPlayerModels-1.18/src/main/java/com/tom/cpm/mixin/PlayerRendererMixin.java index fd11ed0e..c0290aba 100644 --- a/CustomPlayerModels-1.18/src/main/java/com/tom/cpm/mixin/PlayerRendererMixin.java +++ b/CustomPlayerModels-1.18/src/main/java/com/tom/cpm/mixin/PlayerRendererMixin.java @@ -81,8 +81,15 @@ public void onRenderLeftArmPost(PoseStack matrices, MultiBufferSource vertexCons } @Inject(at = @At("HEAD"), method = "renderNameTag(Lnet/minecraft/client/player/AbstractClientPlayer;Lnet/minecraft/network/chat/Component;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V", cancellable = true) - public void onRenderName(AbstractClientPlayer entityIn, Component displayNameIn, PoseStack matrixStackIn, MultiBufferSource bufferIn, int packedLightIn, CallbackInfo cbi) { + public void onRenderName1(AbstractClientPlayer entityIn, Component displayNameIn, PoseStack matrixStackIn, MultiBufferSource bufferIn, int packedLightIn, CallbackInfo cbi) { if(!Player.isEnableNames())cbi.cancel(); + } + + @Inject(at = @At(value = "INVOKE", + target = "Lnet/minecraft/client/renderer/entity/LivingEntityRenderer;renderNameTag(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/network/chat/Component;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V", + ordinal = 1), + method = "renderNameTag(Lnet/minecraft/client/player/AbstractClientPlayer;Lnet/minecraft/network/chat/Component;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V") + public void onRenderName2(AbstractClientPlayer entityIn, Component displayNameIn, PoseStack matrixStackIn, MultiBufferSource bufferIn, int packedLightIn, CallbackInfo cbi) { if(Player.isEnableLoadingInfo()) CustomPlayerModelsClient.renderNameTag(this, entityIn, entityIn.getGameProfile(), ModelDefinitionLoader.PLAYER_UNIQUE, matrixStackIn, bufferIn, packedLightIn); } diff --git a/CustomPlayerModels-1.19/gradle.properties b/CustomPlayerModels-1.19/gradle.properties index d4b03efb..1083e59c 100644 --- a/CustomPlayerModels-1.19/gradle.properties +++ b/CustomPlayerModels-1.19/gradle.properties @@ -3,4 +3,4 @@ org.gradle.jvmargs=-Xmx3G org.gradle.daemon=false -mod_version=0.4.8a +mod_version=0.5.0a diff --git a/CustomPlayerModels-1.19/src/main/java/com/tom/cpm/client/CustomPlayerModelsClient.java b/CustomPlayerModels-1.19/src/main/java/com/tom/cpm/client/CustomPlayerModelsClient.java index 4dcad896..b89a74b3 100644 --- a/CustomPlayerModels-1.19/src/main/java/com/tom/cpm/client/CustomPlayerModelsClient.java +++ b/CustomPlayerModels-1.19/src/main/java/com/tom/cpm/client/CustomPlayerModelsClient.java @@ -2,10 +2,8 @@ import java.io.IOException; import java.util.List; -import java.util.Map.Entry; import java.util.function.Consumer; -import net.minecraft.client.KeyMapping; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screens.SkinCustomizationScreen; import net.minecraft.client.gui.screens.TitleScreen; @@ -184,11 +182,7 @@ public void clientTick(ClientTickEvent evt) { Player.setEnableRendering(!Player.isEnableRendering()); } - for (Entry e : KeyBindings.quickAccess.entrySet()) { - if(e.getValue().consumeClick()) { - mc.getPlayerRenderManager().getAnimationEngine().onKeybind(e.getKey()); - } - } + mc.getPlayerRenderManager().getAnimationEngine().updateKeys(KeyBindings.quickAccess); } @SubscribeEvent @@ -201,6 +195,16 @@ public void openGui(ScreenEvent.Opening openGui) { } } + @SubscribeEvent + public void drawGuiPre(ScreenEvent.Render.Pre evt) { + PlayerProfile.inGui = true; + } + + @SubscribeEvent + public void drawGuiPost(ScreenEvent.Render.Post evt) { + PlayerProfile.inGui = false; + } + private void registerShaders(RegisterShadersEvent evt) { } diff --git a/CustomPlayerModels-1.19/src/main/java/com/tom/cpm/client/KeyBindings.java b/CustomPlayerModels-1.19/src/main/java/com/tom/cpm/client/KeyBindings.java index b6b706c3..e73b7c1b 100644 --- a/CustomPlayerModels-1.19/src/main/java/com/tom/cpm/client/KeyBindings.java +++ b/CustomPlayerModels-1.19/src/main/java/com/tom/cpm/client/KeyBindings.java @@ -1,9 +1,7 @@ package com.tom.cpm.client; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.lwjgl.glfw.GLFW; @@ -22,7 +20,7 @@ public class KeyBindings implements IKeybind { private static KeyConflictCtx conflictCtx = new KeyConflictCtx(); public static KeyMapping gestureMenuBinding, renderToggleBinding; - public static Map quickAccess = new HashMap<>(); + public static IKeybind[] quickAccess = new IKeybind[IKeybind.QUICK_ACCESS_KEYBINDS_COUNT]; public static void init(RegisterKeyMappingsEvent evt) { gestureMenuBinding = new KeyMapping("key.cpm.gestureMenu", KeyConflictContext.IN_GAME, InputConstants.Type.KEYSYM.getOrCreate(GLFW.GLFW_KEY_G), "key.cpm.category"); @@ -30,7 +28,7 @@ public static void init(RegisterKeyMappingsEvent evt) { kbs.add(new KeyBindings(gestureMenuBinding, "gestureMenu", evt)); kbs.add(new KeyBindings(renderToggleBinding, "renderToggle", evt)); - for(int i = 1;i<=6;i++) + for(int i = 1;i<=IKeybind.QUICK_ACCESS_KEYBINDS_COUNT;i++) createQA(i, evt); } @@ -50,8 +48,9 @@ public boolean conflicts(IKeyConflictContext other) { private static void createQA(int id, RegisterKeyMappingsEvent evt) { KeyMapping kb = new KeyMapping("key.cpm.qa_" + id, conflictCtx, InputConstants.UNKNOWN, "key.cpm.category"); - kbs.add(new KeyBindings(kb, "qa_" + id, evt)); - quickAccess.put(id, kb); + KeyBindings kbs = new KeyBindings(kb, "qa_" + id, evt); + KeyBindings.kbs.add(kbs); + quickAccess[id - 1] = kbs; } public static List kbs = new ArrayList<>(); @@ -79,4 +78,9 @@ public String getBoundKey() { public String getName() { return name; } + + @Override + public boolean isPressed() { + return kb.isDown(); + } } diff --git a/CustomPlayerModels-1.19/src/main/java/com/tom/cpm/client/PlayerProfile.java b/CustomPlayerModels-1.19/src/main/java/com/tom/cpm/client/PlayerProfile.java index 86515934..382658e9 100644 --- a/CustomPlayerModels-1.19/src/main/java/com/tom/cpm/client/PlayerProfile.java +++ b/CustomPlayerModels-1.19/src/main/java/com/tom/cpm/client/PlayerProfile.java @@ -1,8 +1,11 @@ package com.tom.cpm.client; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; import java.util.Map; import java.util.UUID; import java.util.concurrent.CompletableFuture; +import java.util.function.BooleanSupplier; import net.minecraft.client.Minecraft; import net.minecraft.client.model.PlayerModel; @@ -19,6 +22,8 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.AbstractSkullBlock; +import net.minecraftforge.fml.ModList; + import com.mojang.authlib.GameProfile; import com.mojang.authlib.minecraft.MinecraftProfileTexture; import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type; @@ -33,6 +38,27 @@ import com.tom.cpm.shared.skin.PlayerTextureLoader; public class PlayerProfile extends Player { + public static boolean inGui; + public static BooleanSupplier inFirstPerson; + static { + inFirstPerson = () -> false; + if(ModList.get().isLoaded("firstpersonmod")) { + try { + MethodHandle h = MethodHandles.lookup().unreflectGetter(Class.forName("dev.tr7zw.firstperson.FirstPersonModelCore").getDeclaredField("isRenderingPlayer")); + inFirstPerson = () -> { + try { + return (boolean) h.invoke(); + } catch (Throwable e) { + inFirstPerson = () -> false; + return false; + } + }; + inFirstPerson.getAsBoolean(); + } catch (Throwable e) { + } + } + } + private final GameProfile profile; private String skinType; @@ -137,6 +163,8 @@ public void updateFromPlayer(net.minecraft.world.entity.player.Player player) { animState.isOnLadder = player.onClimbable(); animState.isBurning = player.displayFireAnimation(); animState.isFreezing = player.getTicksFrozen() > 0; + animState.inGui = inGui; + animState.firstPersonMod = inFirstPerson.getAsBoolean(); if(player.getUseItem().getItem() instanceof CrossbowItem) { float f = CrossbowItem.getChargeDuration(player.getUseItem()); diff --git a/CustomPlayerModels-1.19/src/main/java/com/tom/cpm/client/VBufferOut.java b/CustomPlayerModels-1.19/src/main/java/com/tom/cpm/client/VBufferOut.java index b262dd3a..7d321a4a 100644 --- a/CustomPlayerModels-1.19/src/main/java/com/tom/cpm/client/VBufferOut.java +++ b/CustomPlayerModels-1.19/src/main/java/com/tom/cpm/client/VBufferOut.java @@ -15,8 +15,8 @@ public class VBufferOut implements BufferOutput { public VBufferOut(int light, int overlay, PoseStack matrixStackIn) { this.light = light; this.overlay = overlay; - mat4 = matrixStackIn.last().pose(); - mat3 = matrixStackIn.last().normal(); + mat4 = new Matrix4f(matrixStackIn.last().pose()); + mat3 = new Matrix3f(matrixStackIn.last().normal()); } @Override diff --git a/CustomPlayerModels-1.19/src/main/java/com/tom/cpm/mixin/PlayerRendererMixin.java b/CustomPlayerModels-1.19/src/main/java/com/tom/cpm/mixin/PlayerRendererMixin.java index fd11ed0e..c0290aba 100644 --- a/CustomPlayerModels-1.19/src/main/java/com/tom/cpm/mixin/PlayerRendererMixin.java +++ b/CustomPlayerModels-1.19/src/main/java/com/tom/cpm/mixin/PlayerRendererMixin.java @@ -81,8 +81,15 @@ public void onRenderLeftArmPost(PoseStack matrices, MultiBufferSource vertexCons } @Inject(at = @At("HEAD"), method = "renderNameTag(Lnet/minecraft/client/player/AbstractClientPlayer;Lnet/minecraft/network/chat/Component;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V", cancellable = true) - public void onRenderName(AbstractClientPlayer entityIn, Component displayNameIn, PoseStack matrixStackIn, MultiBufferSource bufferIn, int packedLightIn, CallbackInfo cbi) { + public void onRenderName1(AbstractClientPlayer entityIn, Component displayNameIn, PoseStack matrixStackIn, MultiBufferSource bufferIn, int packedLightIn, CallbackInfo cbi) { if(!Player.isEnableNames())cbi.cancel(); + } + + @Inject(at = @At(value = "INVOKE", + target = "Lnet/minecraft/client/renderer/entity/LivingEntityRenderer;renderNameTag(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/network/chat/Component;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V", + ordinal = 1), + method = "renderNameTag(Lnet/minecraft/client/player/AbstractClientPlayer;Lnet/minecraft/network/chat/Component;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V") + public void onRenderName2(AbstractClientPlayer entityIn, Component displayNameIn, PoseStack matrixStackIn, MultiBufferSource bufferIn, int packedLightIn, CallbackInfo cbi) { if(Player.isEnableLoadingInfo()) CustomPlayerModelsClient.renderNameTag(this, entityIn, entityIn.getGameProfile(), ModelDefinitionLoader.PLAYER_UNIQUE, matrixStackIn, bufferIn, packedLightIn); } diff --git a/CustomPlayerModels-1.7/gradle.properties b/CustomPlayerModels-1.7/gradle.properties index 7403a6ed..a11f374f 100644 --- a/CustomPlayerModels-1.7/gradle.properties +++ b/CustomPlayerModels-1.7/gradle.properties @@ -3,5 +3,5 @@ org.gradle.jvmargs=-Xmx3G org.gradle.daemon=false -mod_version=0.4.8a +mod_version=0.5.0a project_type=forge diff --git a/CustomPlayerModels-1.7/src/main/java/com/tom/cpm/client/ClientProxy.java b/CustomPlayerModels-1.7/src/main/java/com/tom/cpm/client/ClientProxy.java index 66b53993..ce8fa5b1 100644 --- a/CustomPlayerModels-1.7/src/main/java/com/tom/cpm/client/ClientProxy.java +++ b/CustomPlayerModels-1.7/src/main/java/com/tom/cpm/client/ClientProxy.java @@ -1,8 +1,5 @@ package com.tom.cpm.client; -import java.io.IOException; -import java.io.InputStream; -import java.util.Map.Entry; import java.util.concurrent.Executor; import org.lwjgl.opengl.GL11; @@ -21,17 +18,18 @@ import net.minecraft.client.renderer.OpenGlHelper; import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.resources.I18n; -import net.minecraft.client.settings.KeyBinding; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.network.play.client.C17PacketCustomPayload; +import net.minecraft.scoreboard.ScoreObjective; +import net.minecraft.scoreboard.Scoreboard; import net.minecraft.util.IChatComponent; import net.minecraft.util.MathHelper; -import net.minecraft.util.ResourceLocation; import net.minecraftforge.client.event.GuiOpenEvent; import net.minecraftforge.client.event.GuiScreenEvent; +import net.minecraftforge.client.event.GuiScreenEvent.DrawScreenEvent; import net.minecraftforge.client.event.RenderLivingEvent; import net.minecraftforge.client.event.RenderPlayerEvent; import net.minecraftforge.common.MinecraftForge; @@ -42,6 +40,7 @@ import com.tom.cpl.text.FormatText; import com.tom.cpm.CommonProxy; import com.tom.cpm.CustomPlayerModels; +import com.tom.cpm.common.NetHandlerExt; import com.tom.cpm.lefix.FixSSL; import com.tom.cpm.shared.config.ConfigKeys; import com.tom.cpm.shared.config.ModConfig; @@ -50,10 +49,8 @@ import com.tom.cpm.shared.definition.ModelDefinitionLoader; import com.tom.cpm.shared.editor.gui.EditorGui; import com.tom.cpm.shared.gui.GestureGui; -import com.tom.cpm.shared.io.IOHelper; import com.tom.cpm.shared.model.RenderManager; import com.tom.cpm.shared.model.TextureSheetType; -import com.tom.cpm.shared.network.NetHandler; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.eventhandler.SubscribeEvent; @@ -66,7 +63,7 @@ public class ClientProxy extends CommonProxy { private Minecraft minecraft; public static ClientProxy INSTANCE; public RenderManager manager; - public NetH netHandler; + public NetHandlerExt netHandler; @Override public void init() { @@ -80,7 +77,7 @@ public void init() { KeyBindings.init(); manager = new RenderManager<>(mc.getPlayerRenderManager(), mc.getDefinitionLoader(), EntityPlayer::getGameProfile); manager.setGPGetters(GameProfile::getProperties, Property::getValue); - netHandler = new NetH(); + netHandler = new NetHandlerExt<>(); Executor ex = minecraft::func_152344_a; netHandler.setExecutor(() -> ex); netHandler.setSendPacketClient((c, rl, pb) -> c.addToSendQueue(new C17PacketCustomPayload(rl.toString(), pb))); @@ -146,6 +143,16 @@ public void openGui(GuiOpenEvent openGui) { } } + @SubscribeEvent + public void drawGuiPre(DrawScreenEvent.Pre evt) { + PlayerProfile.inGui = true; + } + + @SubscribeEvent + public void drawGuiPost(DrawScreenEvent.Post evt) { + PlayerProfile.inGui = false; + } + public void renderSkull(ModelBase skullModel, GameProfile profile) { manager.bindSkull(profile, null, skullModel); manager.bindSkin(skullModel, TextureSheetType.SKIN); @@ -179,11 +186,7 @@ public void clientTick(ClientTickEvent evt) { Player.setEnableRendering(!Player.isEnableRendering()); } - for (Entry e : KeyBindings.quickAccess.entrySet()) { - if(e.getValue().isPressed()) { - mc.getPlayerRenderManager().getAnimationEngine().onKeybind(e.getKey()); - } - } + mc.getPlayerRenderManager().getAnimationEngine().updateKeys(KeyBindings.quickAccess); } @SubscribeEvent @@ -199,6 +202,11 @@ public void onRenderName(RenderLivingEvent.Specials.Pre evt) { double d3 = evt.entity.getDistanceSqToEntity(net.minecraft.client.renderer.entity.RenderManager.instance.livingPlayer); if (d3 < 32*32) { + Scoreboard scoreboard = ((EntityPlayer) evt.entity).getWorldScoreboard(); + ScoreObjective scoreobjective = scoreboard.func_96539_a(2); + double y = evt.y; + if (scoreobjective != null) + y += evt.renderer.getFontRendererFromRenderManager().FONT_HEIGHT * 1.15F * 0.025F; GL11.glPushMatrix(); GL11.glTranslated(0, 0.125F, 0); String s = ((IChatComponent) st.remap()).getFormattedText(); @@ -206,7 +214,7 @@ public void onRenderName(RenderLivingEvent.Specials.Pre evt) { if (evt.entity.isSneaking()) { FontRenderer fontrenderer = minecraft.fontRenderer; GL11.glPushMatrix(); - GL11.glTranslatef((float)evt.x + 0.0F, (float)evt.y + evt.entity.height + 0.5F, (float)evt.z); + GL11.glTranslatef((float)evt.x + 0.0F, (float)y + evt.entity.height + 0.5F, (float)evt.z); GL11.glNormal3f(0.0F, 1.0F, 0.0F); GL11.glRotatef(-net.minecraft.client.renderer.entity.RenderManager.instance.playerViewY, 0.0F, 1.0F, 0.0F); GL11.glRotatef(net.minecraft.client.renderer.entity.RenderManager.instance.playerViewX, 1.0F, 0.0F, 0.0F); @@ -234,7 +242,7 @@ public void onRenderName(RenderLivingEvent.Specials.Pre evt) { GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); GL11.glPopMatrix(); } else { - this.renderLivingLabel(evt.entity, evt.x, evt.y, evt.z, s, f1, d3); + this.renderLivingLabel(evt.entity, evt.x, y, evt.z, s, f1, d3); } GL11.glPopMatrix(); } @@ -308,38 +316,6 @@ public void onLogout() { mc.onLogOut(); } - public static class NetH extends NetHandler { - - public NetH() { - super(ResourceLocation::new); - } - - @Override - public void receiveClient(ResourceLocation key, InputStream data, com.tom.cpm.shared.network.NetH net) { - if(key.equals(setLayer)) { - try { - IOHelper h = new IOHelper(data); - int entId = h.readVarInt(); - int layer = h.readByte(); - Minecraft.getMinecraft().func_152344_a(() -> { - Entity ent = Minecraft.getMinecraft().theWorld.getEntityByID(entId); - if(ent instanceof EntityPlayer) { - PlayerProfile profile = (PlayerProfile) ClientProxy.mc.getDefinitionLoader().loadPlayer(((EntityPlayer) ent).getGameProfile(), ModelDefinitionLoader.PLAYER_UNIQUE); - profile.encGesture = layer; - } - }); - } catch(IOException e) {} - } else - super.receiveClient(key, data, net); - } - - public void sendLayer(int value) { - if(hasModClient()) { - sendPacketToServer(setLayer, new byte[] {(byte) value}); - } - } - } - //Copy from RenderPlayer.renderEquippedItems public static void renderCape(AbstractClientPlayer playerIn, float partialTicks, ModelBiped model, ModelDefinition modelDefinition) { GL11.glPushMatrix(); diff --git a/CustomPlayerModels-1.7/src/main/java/com/tom/cpm/client/KeyBindings.java b/CustomPlayerModels-1.7/src/main/java/com/tom/cpm/client/KeyBindings.java index 7e1ee49e..e8b1feff 100644 --- a/CustomPlayerModels-1.7/src/main/java/com/tom/cpm/client/KeyBindings.java +++ b/CustomPlayerModels-1.7/src/main/java/com/tom/cpm/client/KeyBindings.java @@ -1,9 +1,7 @@ package com.tom.cpm.client; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.lwjgl.input.Keyboard; @@ -17,7 +15,7 @@ public class KeyBindings implements IKeybind { public static KeyBinding gestureMenuBinding, renderToggleBinding; - public static Map quickAccess = new HashMap<>(); + public static IKeybind[] quickAccess = new IKeybind[IKeybind.QUICK_ACCESS_KEYBINDS_COUNT]; public static void init() { gestureMenuBinding = new KeyBinding("key.cpm.gestureMenu", Keyboard.KEY_G, "key.cpm.category"); @@ -26,14 +24,15 @@ public static void init() { renderToggleBinding = new KeyBinding("key.cpm.renderToggle", 0, "key.cpm.category"); kbs.add(new KeyBindings(renderToggleBinding, "renderToggle")); - for(int i = 1;i<=6;i++) + for(int i = 1;i<=IKeybind.QUICK_ACCESS_KEYBINDS_COUNT;i++) createQA(i); } private static void createQA(int id) { KeyBinding kb = new KeyBinding("key.cpm.qa_" + id, 0, "key.cpm.category"); - kbs.add(new KeyBindings(kb, "qa_" + id)); - quickAccess.put(id, kb); + KeyBindings kbs = new KeyBindings(kb, "qa_" + id); + KeyBindings.kbs.add(kbs); + quickAccess[id - 1] = kbs; } public static List kbs = new ArrayList<>(); @@ -60,4 +59,9 @@ public String getBoundKey() { public String getName() { return name; } + + @Override + public boolean isPressed() { + return kb.getIsKeyPressed(); + } } diff --git a/CustomPlayerModels-1.7/src/main/java/com/tom/cpm/client/PlayerProfile.java b/CustomPlayerModels-1.7/src/main/java/com/tom/cpm/client/PlayerProfile.java index ac696c1b..3ff0cf84 100644 --- a/CustomPlayerModels-1.7/src/main/java/com/tom/cpm/client/PlayerProfile.java +++ b/CustomPlayerModels-1.7/src/main/java/com/tom/cpm/client/PlayerProfile.java @@ -27,6 +27,7 @@ import com.tom.cpm.shared.skin.PlayerTextureLoader; public class PlayerProfile extends Player { + public static boolean inGui; private final GameProfile profile; public int encGesture; @@ -142,6 +143,7 @@ public void updateFromPlayer(EntityPlayer player) { animState.hurtTime = player.hurtTime; animState.isOnLadder = player.isOnLadder(); animState.isBurning = player.canRenderOnFire(); + animState.inGui = inGui; if(player.getItemInUse() != null && player.getItemInUse().getItem() instanceof ItemBow) { float f = 20F; diff --git a/CustomPlayerModels-1.7/src/main/java/com/tom/cpm/common/NetHandlerExt.java b/CustomPlayerModels-1.7/src/main/java/com/tom/cpm/common/NetHandlerExt.java new file mode 100644 index 00000000..d635b260 --- /dev/null +++ b/CustomPlayerModels-1.7/src/main/java/com/tom/cpm/common/NetHandlerExt.java @@ -0,0 +1,105 @@ +package com.tom.cpm.common; + +import java.io.IOException; + +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.util.ResourceLocation; + +import com.mojang.authlib.GameProfile; + +import com.tom.cpm.PlayerDataExt; +import com.tom.cpm.client.ClientProxy; +import com.tom.cpm.client.PlayerProfile; +import com.tom.cpm.shared.config.PlayerData; +import com.tom.cpm.shared.definition.ModelDefinitionLoader; +import com.tom.cpm.shared.io.IOHelper; +import com.tom.cpm.shared.network.IC2SPacket; +import com.tom.cpm.shared.network.IS2CPacket; +import com.tom.cpm.shared.network.NetH; +import com.tom.cpm.shared.network.NetH.ServerNetH; +import com.tom.cpm.shared.network.NetHandler; + +public class NetHandlerExt extends NetHandler { + public static final String SKIN_LAYERS = "layer"; + + public NetHandlerExt() { + super(ResourceLocation::new); + + register(packetC2S, SKIN_LAYERS, LayerC2S.class, LayerC2S::new); + register(packetS2C, SKIN_LAYERS, LayerS2C.class, LayerS2C::new); + } + + @Override + protected PlayerData newData() { + return new PlayerDataExt(); + } + + public static class LayerC2S implements IC2SPacket { + private int layer; + + public LayerC2S(int layer) { + this.layer = layer; + } + + public LayerC2S() { + } + + @Override + public void read(IOHelper pb) throws IOException { + layer = pb.readByte(); + } + + @Override + public void write(IOHelper pb) throws IOException { + pb.writeByte(layer); + } + + @Override + public

void handle(NetHandler handler, ServerNetH from, P pl) { + EntityPlayerMP player = (EntityPlayerMP) pl; + PlayerDataExt.setSkinLayer(player, layer); + handler.sendPacketToTracking(pl, new LayerS2C(player.getEntityId(), layer)); + } + } + + public static class LayerS2C implements IS2CPacket { + private int entId, layer; + + public LayerS2C() { + } + + public LayerS2C(int entId, int layer) { + this.entId = entId; + this.layer = layer; + } + + @Override + public void read(IOHelper pb) throws IOException { + entId = pb.readVarInt(); + layer = pb.readByte(); + } + + @Override + public void write(IOHelper pb) throws IOException { + pb.writeVarInt(entId); + pb.writeByte(layer); + } + + @Override + public void handle(NetHandler handler, NetH from) { + handle0(handler, from); + } + + private

void handle0(NetHandler handler, NetH from) { + P ent = handler.getPlayerById(entId); + PlayerProfile profile = (PlayerProfile) ClientProxy.mc.getDefinitionLoader().loadPlayer((GameProfile) handler.getLoaderId(ent), ModelDefinitionLoader.PLAYER_UNIQUE); + profile.encGesture = layer; + } + } + + public void sendLayer(int value) { + if(hasModClient()) { + sendPacketToServer(new LayerC2S(value)); + } + } +} diff --git a/CustomPlayerModels-1.7/src/main/java/com/tom/cpm/common/ServerHandler.java b/CustomPlayerModels-1.7/src/main/java/com/tom/cpm/common/ServerHandler.java index 90003bdc..dbe4262b 100644 --- a/CustomPlayerModels-1.7/src/main/java/com/tom/cpm/common/ServerHandler.java +++ b/CustomPlayerModels-1.7/src/main/java/com/tom/cpm/common/ServerHandler.java @@ -1,7 +1,5 @@ package com.tom.cpm.common; -import java.io.IOException; -import java.io.InputStream; import java.util.Set; import net.minecraft.entity.EntityTrackerEntry; @@ -11,17 +9,12 @@ import net.minecraft.network.play.server.S02PacketChat; import net.minecraft.network.play.server.S3FPacketCustomPayload; import net.minecraft.server.MinecraftServer; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.WorldServer; import net.minecraftforge.event.entity.living.LivingEvent.LivingJumpEvent; import net.minecraftforge.event.entity.player.PlayerEvent; -import com.tom.cpm.PlayerDataExt; -import com.tom.cpm.shared.config.PlayerData; -import com.tom.cpm.shared.io.IOHelper; import com.tom.cpm.shared.network.NetH.ServerNetH; -import com.tom.cpm.shared.network.NetHandler; import cpw.mods.fml.common.eventhandler.SubscribeEvent; import cpw.mods.fml.common.gameevent.PlayerEvent.PlayerLoggedInEvent; @@ -29,28 +22,10 @@ import cpw.mods.fml.common.gameevent.TickEvent.ServerTickEvent; public class ServerHandler { - public static NetHandler netHandler; + public static NetHandlerExt netHandler; static { - netHandler = new NetHandler(ResourceLocation::new) { - @Override - protected PlayerData newData() { - return new PlayerDataExt(); - } - - @Override - public void receiveServer(ResourceLocation key, InputStream data, ServerNetH net) { - EntityPlayerMP pl = getPlayer.apply((NetHandlerPlayServer) net); - if(key.equals(setLayer)) { - try { - PlayerDataExt.setSkinLayer(pl, data.read()); - sendPacketToTracking(pl, setLayer, writeLayerData(pl)); - } catch (IOException e) { - } - } else - super.receiveServer(key, data, net); - } - }; + netHandler = new NetHandlerExt<>(); netHandler.setGetPlayerUUID(EntityPlayerMP::getUniqueID); netHandler.setSendPacketServer(a -> a, (c, rl, pb) -> c.sendPacket(new S3FPacketCustomPayload(rl.toString(), pb)), ent -> ((WorldServer)ent.worldObj).getEntityTracker().getTrackingPlayers(ent), e -> (EntityPlayerMP) e); netHandler.setFindTracking((p, f) -> { @@ -98,15 +73,4 @@ public void onJump(LivingJumpEvent evt) { netHandler.onJump((EntityPlayerMP) evt.entityLiving); } } - - private static byte[] writeLayerData(EntityPlayerMP playerEntity) { - try { - IOHelper h = new IOHelper(); - h.writeVarInt(playerEntity.getEntityId()); - h.writeByte(PlayerDataExt.getSkinLayer(playerEntity)); - return h.toBytes(); - } catch (IOException e) { - throw new RuntimeException(e); - } - } } diff --git a/CustomPlayerModels-1.8/gradle.properties b/CustomPlayerModels-1.8/gradle.properties index 3f81918b..82c80604 100644 --- a/CustomPlayerModels-1.8/gradle.properties +++ b/CustomPlayerModels-1.8/gradle.properties @@ -3,6 +3,6 @@ org.gradle.jvmargs=-Xmx3G org.gradle.daemon=false -mod_version=0.4.8a +mod_version=0.5.0a project_type=forge diff --git a/CustomPlayerModels-1.8/src/main/java/com/tom/cpm/client/ClientProxy.java b/CustomPlayerModels-1.8/src/main/java/com/tom/cpm/client/ClientProxy.java index 41af21db..40d41d25 100644 --- a/CustomPlayerModels-1.8/src/main/java/com/tom/cpm/client/ClientProxy.java +++ b/CustomPlayerModels-1.8/src/main/java/com/tom/cpm/client/ClientProxy.java @@ -1,6 +1,5 @@ package com.tom.cpm.client; -import java.util.Map.Entry; import java.util.concurrent.Executor; import org.lwjgl.opengl.GL11; @@ -22,12 +21,13 @@ import net.minecraft.client.renderer.WorldRenderer; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.client.resources.I18n; -import net.minecraft.client.settings.KeyBinding; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.network.PacketBuffer; import net.minecraft.network.play.client.C17PacketCustomPayload; +import net.minecraft.scoreboard.ScoreObjective; +import net.minecraft.scoreboard.Scoreboard; import net.minecraft.scoreboard.Team; import net.minecraft.util.IChatComponent; import net.minecraft.util.MathHelper; @@ -35,6 +35,7 @@ import net.minecraftforge.client.event.GuiOpenEvent; import net.minecraftforge.client.event.GuiScreenEvent; +import net.minecraftforge.client.event.GuiScreenEvent.DrawScreenEvent; import net.minecraftforge.client.event.RenderLivingEvent; import net.minecraftforge.client.event.RenderPlayerEvent; import net.minecraftforge.common.MinecraftForge; @@ -141,6 +142,16 @@ public void openGui(GuiOpenEvent openGui) { } } + @SubscribeEvent + public void drawGuiPre(DrawScreenEvent.Pre evt) { + PlayerProfile.inGui = true; + } + + @SubscribeEvent + public void drawGuiPost(DrawScreenEvent.Post evt) { + PlayerProfile.inGui = false; + } + public void renderSkull(ModelBase skullModel, GameProfile profile) { manager.bindSkull(profile, null, skullModel); manager.bindSkin(skullModel, TextureSheetType.SKIN); @@ -182,11 +193,7 @@ public void clientTick(ClientTickEvent evt) { Player.setEnableRendering(!Player.isEnableRendering()); } - for (Entry e : KeyBindings.quickAccess.entrySet()) { - if(e.getValue().isPressed()) { - mc.getPlayerRenderManager().getAnimationEngine().onKeybind(e.getKey()); - } - } + mc.getPlayerRenderManager().getAnimationEngine().updateKeys(KeyBindings.quickAccess); } @SubscribeEvent @@ -199,6 +206,12 @@ public void onRenderName(RenderLivingEvent.Specials.Pre ev if(st != null) { double d0 = evt.entity.getDistanceSqToEntity(minecraft.getRenderViewEntity()); if (d0 < 32*32) { + Scoreboard scoreboard = ((EntityPlayer) evt.entity).getWorldScoreboard(); + ScoreObjective scoreobjective = scoreboard.getObjectiveInDisplaySlot(2); + double y = evt.y; + if (scoreobjective != null) + y += evt.renderer.getFontRendererFromRenderManager().FONT_HEIGHT * 1.15F * 0.025F; + GlStateManager.pushMatrix(); GlStateManager.translate(0, 0.125F, 0); String str = ((IChatComponent) st.remap()).getFormattedText(); @@ -207,7 +220,7 @@ public void onRenderName(RenderLivingEvent.Specials.Pre ev if (evt.entity.isSneaking()) { FontRenderer fontrenderer = minecraft.fontRendererObj; GlStateManager.pushMatrix(); - GlStateManager.translate((float)evt.x, (float)evt.y + evt.entity.height + 0.5F - (evt.entity.isChild() ? evt.entity.height / 2.0F : 0.0F), (float)evt.z); + GlStateManager.translate((float)evt.x, (float)y + evt.entity.height + 0.5F - (evt.entity.isChild() ? evt.entity.height / 2.0F : 0.0F), (float)evt.z); GL11.glNormal3f(0.0F, 1.0F, 0.0F); GlStateManager.rotate(-minecraft.getRenderManager().playerViewY, 0.0F, 1.0F, 0.0F); GlStateManager.rotate(minecraft.getRenderManager().playerViewX, 1.0F, 0.0F, 0.0F); @@ -235,7 +248,7 @@ public void onRenderName(RenderLivingEvent.Specials.Pre ev GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); GlStateManager.popMatrix(); } else { - renderLivingLabel(evt.entity, str, evt.x, evt.y - (evt.entity.isChild() ? (double)(evt.entity.height / 2.0F) : 0.0D), evt.z, 64); + renderLivingLabel(evt.entity, str, evt.x, y - (evt.entity.isChild() ? (double)(evt.entity.height / 2.0F) : 0.0D), evt.z, 64); } } GlStateManager.popMatrix(); diff --git a/CustomPlayerModels-1.8/src/main/java/com/tom/cpm/client/KeyBindings.java b/CustomPlayerModels-1.8/src/main/java/com/tom/cpm/client/KeyBindings.java index 49feaecf..efc475ad 100644 --- a/CustomPlayerModels-1.8/src/main/java/com/tom/cpm/client/KeyBindings.java +++ b/CustomPlayerModels-1.8/src/main/java/com/tom/cpm/client/KeyBindings.java @@ -1,9 +1,7 @@ package com.tom.cpm.client; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.lwjgl.input.Keyboard; @@ -17,7 +15,7 @@ public class KeyBindings implements IKeybind { public static KeyBinding gestureMenuBinding, renderToggleBinding; - public static Map quickAccess = new HashMap<>(); + public static IKeybind[] quickAccess = new IKeybind[IKeybind.QUICK_ACCESS_KEYBINDS_COUNT]; public static void init() { gestureMenuBinding = new KeyBinding("key.cpm.gestureMenu", Keyboard.KEY_G, "key.cpm.category"); @@ -26,14 +24,15 @@ public static void init() { renderToggleBinding = new KeyBinding("key.cpm.renderToggle", 0, "key.cpm.category"); kbs.add(new KeyBindings(renderToggleBinding, "renderToggle")); - for(int i = 1;i<=6;i++) + for(int i = 1;i<=IKeybind.QUICK_ACCESS_KEYBINDS_COUNT;i++) createQA(i); } private static void createQA(int id) { KeyBinding kb = new KeyBinding("key.cpm.qa_" + id, 0, "key.cpm.category"); - kbs.add(new KeyBindings(kb, "qa_" + id)); - quickAccess.put(id, kb); + KeyBindings kbs = new KeyBindings(kb, "qa_" + id); + KeyBindings.kbs.add(kbs); + quickAccess[id - 1] = kbs; } public static List kbs = new ArrayList<>(); @@ -60,4 +59,9 @@ public String getBoundKey() { public String getName() { return name; } + + @Override + public boolean isPressed() { + return kb.isKeyDown(); + } } diff --git a/CustomPlayerModels-1.8/src/main/java/com/tom/cpm/client/PlayerProfile.java b/CustomPlayerModels-1.8/src/main/java/com/tom/cpm/client/PlayerProfile.java index 2494ce0b..9767b4e7 100644 --- a/CustomPlayerModels-1.8/src/main/java/com/tom/cpm/client/PlayerProfile.java +++ b/CustomPlayerModels-1.8/src/main/java/com/tom/cpm/client/PlayerProfile.java @@ -28,6 +28,7 @@ import com.tom.cpm.shared.skin.PlayerTextureLoader; public class PlayerProfile extends Player { + public static boolean inGui; private final GameProfile profile; private String skinType; @@ -154,6 +155,7 @@ public void updateFromPlayer(EntityPlayer player) { animState.hurtTime = player.hurtTime; animState.isOnLadder = player.isOnLadder(); animState.isBurning = player.canRenderOnFire(); + animState.inGui = inGui; if(player.getItemInUse() != null && player.getItemInUse().getItem() instanceof ItemBow) { float f = 20F; diff --git a/CustomPlayerModels-Bukkit/gradle.properties b/CustomPlayerModels-Bukkit/gradle.properties index d4b03efb..1083e59c 100644 --- a/CustomPlayerModels-Bukkit/gradle.properties +++ b/CustomPlayerModels-Bukkit/gradle.properties @@ -3,4 +3,4 @@ org.gradle.jvmargs=-Xmx3G org.gradle.daemon=false -mod_version=0.4.8a +mod_version=0.5.0a diff --git a/CustomPlayerModels/gradle.properties b/CustomPlayerModels/gradle.properties index 60308a5f..4d8ab0b5 100644 --- a/CustomPlayerModels/gradle.properties +++ b/CustomPlayerModels/gradle.properties @@ -3,4 +3,4 @@ org.gradle.jvmargs=-Xmx3G org.gradle.daemon=false -mod_version=0.4.8 +mod_version=0.5.0 diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpl/gui/IKeybind.java b/CustomPlayerModels/src/shared/java/com/tom/cpl/gui/IKeybind.java index a105dae2..13b1d291 100644 --- a/CustomPlayerModels/src/shared/java/com/tom/cpl/gui/IKeybind.java +++ b/CustomPlayerModels/src/shared/java/com/tom/cpl/gui/IKeybind.java @@ -1,7 +1,10 @@ package com.tom.cpl.gui; public interface IKeybind { + public static final int QUICK_ACCESS_KEYBINDS_COUNT = 6; + boolean isPressed(KeyboardEvent evt); String getBoundKey(); String getName(); + boolean isPressed(); } diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpl/gui/elements/ListPicker.java b/CustomPlayerModels/src/shared/java/com/tom/cpl/gui/elements/ListPicker.java index dba97dce..9d2668d8 100644 --- a/CustomPlayerModels/src/shared/java/com/tom/cpl/gui/elements/ListPicker.java +++ b/CustomPlayerModels/src/shared/java/com/tom/cpl/gui/elements/ListPicker.java @@ -76,11 +76,14 @@ private class Popup extends PopupPanel { protected Popup() { super(ListPicker.this.gui); - ListPanel list = new ListPanel<>(gui, values, 200, 300); + int w = Math.min(frame.getBounds().w / 4 * 3, 210); + int h = Math.min(frame.getBounds().h / 4 * 3, 335); + + ListPanel list = new ListPanel<>(gui, values, w - 10, h - 35); if(listLoader != null) listLoader.accept(list); list.setSelected(getSelected()); - list.setBounds(new Box(5, 5, 200, 300)); + list.setBounds(new Box(5, 5, w - 10, h - 35)); addElement(list); Button btn = new Button(gui, gui.i18nFormat("button.cpm.ok"), () -> { @@ -89,10 +92,10 @@ protected Popup() { if(action != null) action.run(); }); - btn.setBounds(new Box(5, 310, 60, 20)); + btn.setBounds(new Box(5, h - 25, 60, 20)); addElement(btn); - setBounds(new Box(0, 0, 210, 335)); + setBounds(new Box(0, 0, w, h)); } @Override diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpl/util/MarkdownParser.java b/CustomPlayerModels/src/shared/java/com/tom/cpl/util/MarkdownParser.java index f94340ef..41374ac2 100644 --- a/CustomPlayerModels/src/shared/java/com/tom/cpl/util/MarkdownParser.java +++ b/CustomPlayerModels/src/shared/java/com/tom/cpl/util/MarkdownParser.java @@ -110,7 +110,7 @@ public MarkdownParser(String input) { String h = lnt.replaceAll("^#+", "").trim(); sb.append(h); Line line = parseLine(sb, scl, prefix); - headerLines.put(line, h.replaceAll("[^a-zA-Z0-9]", "-").toLowerCase()); + headerLines.put(line, h.replaceAll("[^a-zA-Z0-9_\\-\\s]", "").replaceAll("[\\s\\-]", "-").toLowerCase()); if(scl > 1.3f)lines.add(new HorizontalLine()); else lines.add(new EmptyLine(4)); diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpm/api/ClientApi.java b/CustomPlayerModels/src/shared/java/com/tom/cpm/api/ClientApi.java index 1f7cf976..f6ac0deb 100644 --- a/CustomPlayerModels/src/shared/java/com/tom/cpm/api/ClientApi.java +++ b/CustomPlayerModels/src/shared/java/com/tom/cpm/api/ClientApi.java @@ -17,9 +17,9 @@ import com.tom.cpl.text.FormatText; import com.tom.cpm.shared.MinecraftClientAccess; import com.tom.cpm.shared.animation.AnimationEngine.AnimationMode; -import com.tom.cpm.shared.animation.AnimationRegistry.Gesture; import com.tom.cpm.shared.animation.AnimationState; import com.tom.cpm.shared.animation.CustomPose; +import com.tom.cpm.shared.animation.Gesture; import com.tom.cpm.shared.config.Player; import com.tom.cpm.shared.definition.ModelDefinition; import com.tom.cpm.shared.editor.Generators; diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/animation/AnimationEngine.java b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/animation/AnimationEngine.java index 57a787ff..3d393b6e 100644 --- a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/animation/AnimationEngine.java +++ b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/animation/AnimationEngine.java @@ -1,18 +1,22 @@ package com.tom.cpm.shared.animation; +import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Objects; import com.tom.cpl.config.ConfigEntry; +import com.tom.cpl.gui.IGui; +import com.tom.cpl.gui.IKeybind; import com.tom.cpm.shared.MinecraftClientAccess; import com.tom.cpm.shared.MinecraftClientAccess.ServerStatus; -import com.tom.cpm.shared.animation.AnimationRegistry.Gesture; import com.tom.cpm.shared.config.ConfigKeys; import com.tom.cpm.shared.config.ModConfig; import com.tom.cpm.shared.config.Player; import com.tom.cpm.shared.definition.ModelDefinition; import com.tom.cpm.shared.model.ScaleData; +import com.tom.cpm.shared.network.ServerCaps; +import com.tom.cpm.shared.network.packet.GestureC2S; import com.tom.cpm.shared.util.Log; import com.tom.cpm.shared.util.ScalingOptions; @@ -22,12 +26,31 @@ public class AnimationEngine { private ScaleData modelScale; private ScaleData modelScaleToReset; private long resetCounter; + private boolean[] quickAccessPressed = new boolean[IKeybind.QUICK_ACCESS_KEYBINDS_COUNT]; + private int gestureAutoResetTimer = -1; + private byte[] gestureData = new byte[2]; public void tick() { tickCounter++; if(MinecraftClientAccess.get().isInGame()) { Player player = MinecraftClientAccess.get().getCurrentClientPlayer();//Keep client player loaded ModelDefinition def = player.getModelDefinition(); + if(def != null) { + int lc = def.getAnimations().getLayerCount(); + + if(gestureData.length != lc) { + byte v0 = gestureData[0]; + byte v1 = gestureData[1]; + gestureData = new byte[lc]; + gestureData[0] = v0; + gestureData[1] = v1; + sendGestureData(); + } + if(player.animState.gestureData == null) { + player.animState.gestureData = Arrays.copyOf(gestureData, gestureData.length); + sendGestureData(); + } + } if(MinecraftClientAccess.get().getServerSideStatus() == ServerStatus.INSTALLED) { if(def != null && def.doRender()) { player.sendEventSubs(); @@ -49,8 +72,14 @@ public void tick() { modelScale = null; } } + if(gestureAutoResetTimer >= 0)gestureAutoResetTimer--; + if(gestureAutoResetTimer == 0 && def != null) { + playGesture(def.getAnimations(), null); + } } else { modelScale = null; + Arrays.fill(quickAccessPressed, false); + gestureAutoResetTimer = -1; } } @@ -77,16 +106,38 @@ public void handleAnimation(Player player, AnimationMode mode) { { player.animState.preAnimate(); VanillaPose pose = player.animState.getMainPose(time, reg); - int gesture = player.animState.encodedState; - if(pose != player.prevPose || gesture == reg.getPoseResetId()) { - player.currentPose = pose; + if (MinecraftClientAccess.get().getNetHandler().hasServerCap(ServerCaps.GESTURES) && player.animState.gestureData != null && player.animState.gestureData.length > 1) { + if(player.animState.gestureData[0] == 0) { + player.currentPose = pose; + } else { + player.currentPose = reg.getPose(player.animState.gestureData[0], player.currentPose); + player.prevPose = pose; + } + List anim = reg.getPoseAnimations(player.currentPose); + h.addAnimations(anim, player.currentPose); + player.animState.collectAnimations(p -> h.addAnimations(reg.getPoseAnimations(p), p)); + h.setGesture(reg.getGesture(player.animState.gestureData[1])); + reg.forEachLayer((g, id) -> { + if(player.animState.gestureData.length > id) { + if(g.name.startsWith(Gesture.VALUE_LAYER_PREFIX)) { + h.addAnimations(g.animation, new ValueLayerPose(id)); + } else if(player.animState.gestureData[id] != 0) { + h.addAnimations(g.animation, null); + } + } + }); + } else { + int gesture = player.animState.encodedState; + if(pose != player.prevPose || gesture == reg.getPoseResetId()) { + player.currentPose = pose; + } + player.currentPose = reg.getPose(gesture, player.currentPose); + player.prevPose = pose; + List anim = reg.getPoseAnimations(player.currentPose); + h.addAnimations(anim, player.currentPose); + player.animState.collectAnimations(p -> h.addAnimations(reg.getPoseAnimations(p), p)); + h.setGesture(reg.getGesture(gesture)); } - player.currentPose = reg.getPose(gesture, player.currentPose); - player.prevPose = pose; - List anim = reg.getPoseAnimations(player.currentPose); - h.addAnimations(anim, player.currentPose); - player.animState.collectAnimations(p -> h.addAnimations(reg.getPoseAnimations(p), p)); - h.setGesture(reg.getGesture(gesture)); } break; @@ -111,6 +162,27 @@ public void handleAnimation(Player player, AnimationMode mode) { } } + private static class ValueLayerPose implements IPose { + private final int id; + + public ValueLayerPose(int id) { + this.id = id; + } + + @Override + public String getName(IGui gui, String display) { + return "value"; + } + + @Override + public long getTime(AnimationState state, long time) { + if(state.gestureData.length > id) + return (long) ((Byte.toUnsignedInt(state.gestureData[id]) / 256f) * VanillaPose.DYNAMIC_DURATION_MUL); + else + return 0L; + } + } + public void handleGuiAnimation(AnimationHandler h, ModelDefinition def) { try { List anim = def.getAnimations().getPoseAnimations(VanillaPose.STANDING); @@ -125,7 +197,7 @@ public void handleGuiAnimation(AnimationHandler h, ModelDefinition def) { } } - public void onKeybind(int id) { + private void onKeybind(int id) { ModelDefinition def = MinecraftClientAccess.get().getCurrentClientPlayer().getModelDefinition(); if(def != null) { ConfigEntry ce = ModConfig.getCommonConfig().getEntry(ConfigKeys.KEYBINDS); @@ -150,26 +222,69 @@ public void setCustomPose(AnimationRegistry reg, CustomPose pose) { ServerStatus status = MinecraftClientAccess.get().getServerSideStatus(); if(status == ServerStatus.OFFLINE || status == ServerStatus.UNAVAILABLE)return; int enc = pose == null ? reg.getPoseResetId() : reg.getEncoded(pose); - if(enc != -1) { - if(enc == MinecraftClientAccess.get().getCurrentClientPlayer().animState.encodedState) { - enc = reg.getPoseResetId(); + if (MinecraftClientAccess.get().getNetHandler().hasServerCap(ServerCaps.GESTURES)) { + gestureData[0] = pose == null || gestureData[0] == enc ? 0 : (byte) enc; + sendGestureData(); + } else { + if(enc != -1) { + if(enc == MinecraftClientAccess.get().getCurrentClientPlayer().animState.encodedState) { + enc = reg.getPoseResetId(); + } + MinecraftClientAccess.get().setEncodedGesture(enc); } - MinecraftClientAccess.get().setEncodedGesture(enc); } } public void playGesture(AnimationRegistry reg, Gesture g) { ServerStatus status = MinecraftClientAccess.get().getServerSideStatus(); + boolean serverGc = MinecraftClientAccess.get().getNetHandler().hasServerCap(ServerCaps.GESTURES); if(status == ServerStatus.OFFLINE || status == ServerStatus.UNAVAILABLE)return; + if(g != null) { + if (g.name.startsWith(Gesture.LAYER_PREFIX)) { + if(serverGc) { + int id = reg.getLayerId(g); + gestureData[id] = (byte) (gestureData[id] != 0 ? 0 : 1); + sendGestureData(); + } + return; + } + } else if (serverGc) { + gestureData[1] = 0; + sendGestureData(); + return; + } + if(g != null && !g.isLoop && ModConfig.getCommonConfig().getBoolean(ConfigKeys.GESTURE_AUTO_RESET, true)) { + int len = g.animation.stream().mapToInt(IAnimation::getDuration).max().orElse(-1); + gestureAutoResetTimer = len == -1 ? -1 : ((int) Math.ceil(len / 50f) + 5); + } int enc = g == null ? reg.getBlankGesture() : reg.getEncoded(g); - if(enc != -1) { - if(enc == MinecraftClientAccess.get().getCurrentClientPlayer().animState.encodedState) { - enc = reg.getBlankGesture(); + if (serverGc) { + gestureData[1] = g == null || gestureData[1] == enc ? 0 : (byte) enc; + sendGestureData(); + } else { + if(enc != -1) { + if(enc == MinecraftClientAccess.get().getCurrentClientPlayer().animState.encodedState) { + enc = reg.getBlankGesture(); + } + MinecraftClientAccess.get().setEncodedGesture(enc); } - MinecraftClientAccess.get().setEncodedGesture(enc); } } + public void setLayerValue(AnimationRegistry reg, Gesture g, float value) { + if(!MinecraftClientAccess.get().getNetHandler().hasServerCap(ServerCaps.GESTURES))return; + if (g.name.startsWith(Gesture.VALUE_LAYER_PREFIX)) { + int id = reg.getLayerId(g); + if(id == -1)return; + gestureData[id] = (byte) (value * 0xff); + sendGestureData(); + } + } + + private void sendGestureData() { + MinecraftClientAccess.get().getNetHandler().sendPacketToServer(new GestureC2S(gestureData)); + } + public int getTicks() { return (int) tickCounter; } @@ -184,4 +299,40 @@ public void setServerScaling(Map scaling) { modelScaleToReset = new ScaleData(scaling); resetCounter = tickCounter + 100; } + + public void updateKeys(IKeybind[] kbs) { + ModelDefinition def = MinecraftClientAccess.get().getCurrentClientPlayer().getModelDefinition(); + if(def != null) { + for (int i = 1; i <= kbs.length; i++) { + IKeybind kb = kbs[i - 1]; + boolean pr = kb.isPressed(); + boolean prevPr = quickAccessPressed[i - 1]; + if (!prevPr && pr) { + onKeybind(i); + } else if (prevPr && !pr) { + ConfigEntry ce = ModConfig.getCommonConfig().getEntry(ConfigKeys.KEYBINDS); + String mode = ce.getString("qa_" + i + "_mode", "press"); + String c = ce.getString("qa_" + i, null); + if(c != null && mode.equals("hold")) { + if(c.startsWith("p")) { + setCustomPose(def.getAnimations(), null); + } else if(c.startsWith("g")) { + Gesture g = def.getAnimations().getGestures().get(c.substring(1)); + if(g != null && g.isLoop) + playGesture(def.getAnimations(), null); + } + } + } + quickAccessPressed[i - 1] = pr; + } + } else { + Arrays.fill(quickAccessPressed, false); + } + } + + public byte getGestureValue(AnimationRegistry reg, Gesture g) { + int id = reg.getLayerId(g); + if(id == -1)return 0; + return gestureData[id]; + } } diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/animation/AnimationHandler.java b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/animation/AnimationHandler.java index 8ff7710b..ecd3bf65 100644 --- a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/animation/AnimationHandler.java +++ b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/animation/AnimationHandler.java @@ -5,7 +5,6 @@ import java.util.List; import java.util.function.Supplier; -import com.tom.cpm.shared.animation.AnimationRegistry.Gesture; import com.tom.cpm.shared.definition.ModelDefinition; public class AnimationHandler { diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/animation/AnimationRegistry.java b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/animation/AnimationRegistry.java index e59ce916..d430f96d 100644 --- a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/animation/AnimationRegistry.java +++ b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/animation/AnimationRegistry.java @@ -5,6 +5,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.function.BiConsumer; import com.tom.cpm.shared.model.CopyTransform; @@ -15,6 +16,7 @@ public class AnimationRegistry { private Map encodedToGesture = new HashMap<>(); private Map poseToEncoded = new HashMap<>(); private Map gestureToEncoded = new HashMap<>(); + private Map layerToId = new HashMap<>(); private Map gestures = new HashMap<>(); private Map customPoses = new HashMap<>(); private List copyTransforms = new ArrayList<>(); @@ -33,18 +35,6 @@ public Gesture getGesture(int gesture) { return encodedToGesture.get(gesture); } - public static class Gesture { - public List animation; - public boolean isLoop; - public String name; - - public Gesture(List animation, String name, boolean isLoop) { - this.animation = animation; - this.name = name; - this.isLoop = isLoop; - } - } - public void register(IPose pose, IAnimation anim) { animations.computeIfAbsent(pose, k -> new ArrayList<>()).add(anim); } @@ -60,6 +50,8 @@ public void register(CustomPose pose) { public void register(Gesture gesture) { gestures.put(gesture.name, gesture); + if(gesture.name.startsWith(Gesture.LAYER_PREFIX) || gesture.name.startsWith(Gesture.VALUE_LAYER_PREFIX)) + layerToId.put(gesture, layerToId.size() + 2); } public void register(int gid, Gesture gesture) { @@ -71,6 +63,10 @@ public int getEncoded(Gesture g) { return gestureToEncoded.getOrDefault(g, -1); } + public int getLayerId(Gesture g) { + return layerToId.getOrDefault(g, -1); + } + public int getEncoded(CustomPose pose) { return poseToEncoded.getOrDefault(pose, -1); } @@ -124,4 +120,12 @@ public void addCopy(CopyTransform ct) { public void applyCopy() { copyTransforms.forEach(CopyTransform::apply); } + + public int getLayerCount() { + return 2 + layerToId.size(); + } + + public void forEachLayer(BiConsumer g) { + layerToId.forEach(g); + } } diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/animation/AnimationState.java b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/animation/AnimationState.java index 8d4de570..071b20b1 100644 --- a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/animation/AnimationState.java +++ b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/animation/AnimationState.java @@ -8,6 +8,7 @@ import com.tom.cpm.shared.MinecraftClientAccess; import com.tom.cpm.shared.model.render.PlayerModelSetup.ArmPose; import com.tom.cpm.shared.network.ModelEventType; +import com.tom.cpm.shared.network.NetworkUtil; public class AnimationState { public int encodedState; @@ -20,7 +21,8 @@ public class AnimationState { public Hand mainHand = Hand.RIGHT, activeHand = Hand.RIGHT, swingingHand = Hand.RIGHT; public ArmPose leftArm = ArmPose.EMPTY, rightArm = ArmPose.EMPTY; public HandAnimation usingAnimation = HandAnimation.NONE; - public boolean parrotLeft, parrotRight, isFreezing, isBurning, isOnLadder, isClimbing; + public boolean parrotLeft, parrotRight, isFreezing, isBurning, isOnLadder, isClimbing, inGui, firstPersonMod; + public byte[] gestureData; public void resetPlayer() { sleeping = false; @@ -99,6 +101,8 @@ public void collectAnimations(Consumer h) { if(isBurning)h.accept(VanillaPose.ON_FIRE); if(isFreezing)h.accept(VanillaPose.FREEZING); if(speakLevel > 0.1F)h.accept(VanillaPose.SPEAKING); + if(inGui)h.accept(VanillaPose.IN_GUI); + if(firstPersonMod)h.accept(VanillaPose.FIRST_PERSON_MOD); } private static VanillaPose getArmPose(ArmPose pose, boolean left) { @@ -133,6 +137,7 @@ public void receiveEvent(NBTTagCompound tag, boolean isClient) { if(tag.hasKey(ModelEventType.CREATIVE_FLYING.getName()))creativeFlyingServer = tag.getBoolean(ModelEventType.CREATIVE_FLYING.getName()); if(tag.hasKey(ModelEventType.JUMPING.getName()))jumping = tag.getBoolean(ModelEventType.JUMPING.getName()) ? MinecraftClientAccess.get().getPlayerRenderManager().getAnimationEngine().getTime() : 0; } + if(tag.hasKey(NetworkUtil.GESTURE))gestureData = tag.getByteArray(NetworkUtil.GESTURE); } public void jump() { diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/animation/CustomPose.java b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/animation/CustomPose.java index e1a71395..9ed5b503 100644 --- a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/animation/CustomPose.java +++ b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/animation/CustomPose.java @@ -1,8 +1,9 @@ package com.tom.cpm.shared.animation; import com.tom.cpl.gui.IGui; +import com.tom.cpm.shared.MinecraftClientAccess; -public class CustomPose implements IPose { +public class CustomPose implements IPose, IManualGesture { private String name; public CustomPose(String name) { this.name = name; @@ -13,6 +14,7 @@ public String getName(IGui gui, String display) { return name; } + @Override public String getName() { return name; } @@ -28,4 +30,14 @@ public String getId() { public String toString() { return "Custom Pose: " + name; } + + @Override + public String getGestureId() { + return "p" + name; + } + + @Override + public void play(AnimationRegistry reg) { + MinecraftClientAccess.get().getPlayerRenderManager().getAnimationEngine().setCustomPose(reg, this); + } } diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/animation/Gesture.java b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/animation/Gesture.java new file mode 100644 index 00000000..778e2dcf --- /dev/null +++ b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/animation/Gesture.java @@ -0,0 +1,34 @@ +package com.tom.cpm.shared.animation; + +import java.util.List; + +import com.tom.cpm.shared.MinecraftClientAccess; + +public class Gesture implements IManualGesture { + public static final String LAYER_PREFIX = "$layer$"; + public static final String VALUE_LAYER_PREFIX = "$value$"; + public List animation; + public boolean isLoop; + public String name; + + public Gesture(List animation, String name, boolean isLoop) { + this.animation = animation; + this.name = name; + this.isLoop = isLoop; + } + + @Override + public String getName() { + return name; + } + + @Override + public String getGestureId() { + return "g" + name; + } + + @Override + public void play(AnimationRegistry reg) { + MinecraftClientAccess.get().getPlayerRenderManager().getAnimationEngine().playGesture(reg, this); + } +} \ No newline at end of file diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/animation/IManualGesture.java b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/animation/IManualGesture.java new file mode 100644 index 00000000..0710e0fa --- /dev/null +++ b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/animation/IManualGesture.java @@ -0,0 +1,7 @@ +package com.tom.cpm.shared.animation; + +public interface IManualGesture { + String getName(); + String getGestureId(); + void play(AnimationRegistry reg); +} diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/animation/VanillaPose.java b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/animation/VanillaPose.java index b474a487..9bb07765 100644 --- a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/animation/VanillaPose.java +++ b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/animation/VanillaPose.java @@ -56,6 +56,8 @@ public enum VanillaPose implements IPose { SPEAKING(s -> s.speakLevel), TOOT_HORN_LEFT, TOOT_HORN_RIGHT, + IN_GUI, + FIRST_PERSON_MOD, ; private final String i18nKey; private ToFloatFunction stateGetter; diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/config/ConfigKeys.java b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/config/ConfigKeys.java index ece3e302..d3f0898a 100644 --- a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/config/ConfigKeys.java +++ b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/config/ConfigKeys.java @@ -52,6 +52,7 @@ public class ConfigKeys { public static final String EDITOR_LAST_VERSION = "editorLastVersion"; public static final String WIKI_OFFLINE_MODE = "wikiOfflineMode"; public static final String EDITOR_AUTOSAVE_TIME = "editorAutosaveTime"; + public static final String GESTURE_AUTO_RESET = "gestureAutoReset"; public static final PlayerSpecificConfigKey ENABLE_MODEL_LOADING = PlayerSpecificConfigKey.createBool("models", true); public static final PlayerSpecificConfigKey ENABLE_ANIMATED_TEXTURES = PlayerSpecificConfigKey.createBool("animatedTex", false, KeyGroup.FRIEND, true); diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/config/Player.java b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/config/Player.java index 68bb258f..924efd92 100644 --- a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/config/Player.java +++ b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/config/Player.java @@ -111,7 +111,7 @@ public static boolean isEnableLoadingInfo() { public void cleanup() { ModelDefinition def = getModelDefinition0(); - if(def != null)def.cleanup(); + if(def != null)MinecraftClientAccess.get().executeLater(def::cleanup); } public boolean isClientPlayer() { diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/config/PlayerData.java b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/config/PlayerData.java index 9db081bd..87cc0a1a 100644 --- a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/config/PlayerData.java +++ b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/config/PlayerData.java @@ -15,6 +15,7 @@ public class PlayerData { public boolean forced, save; public Map scale = new EnumMap<>(ScalingOptions.class); public EnumSet eventSubs = EnumSet.noneOf(ModelEventType.class); + public byte[] gestureData = new byte[0]; public PlayerData() { } diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/definition/ModelDefinition.java b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/definition/ModelDefinition.java index 9d291f62..171c1ba8 100644 --- a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/definition/ModelDefinition.java +++ b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/definition/ModelDefinition.java @@ -469,7 +469,7 @@ public void setError(Throwable ex) { else resolveState = ModelLoadingState.ERRORRED; error = ex; - if(!(ex instanceof IOException)) + if(!(ex instanceof IOException || ex instanceof SafetyException)) Log.error("Failed to load model", ex); clear(); } diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/definition/SafetyException.java b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/definition/SafetyException.java index cb8a7c43..26014f29 100644 --- a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/definition/SafetyException.java +++ b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/definition/SafetyException.java @@ -4,6 +4,7 @@ public class SafetyException extends RuntimeException { private BlockReason blockReason; public SafetyException(BlockReason blockReason) { + super(blockReason.name()); this.blockReason = blockReason; } diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/editor/Editor.java b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/editor/Editor.java index 427415e0..058c44c5 100644 --- a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/editor/Editor.java +++ b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/editor/Editor.java @@ -153,7 +153,7 @@ public class Editor { public BooleanUpdater displayGizmo = updaterReg.createBool(true); public EnumMap handDisplay = new EnumMap<>(ItemSlot.class); public Set modelDisplayLayers = new HashSet<>(); - public float animTestSlider; + public Map animTestSliders = new HashMap<>(); public Set testPoses = EnumSet.noneOf(VanillaPose.class); public ScalingElement scalingElem = new ScalingElement(this); public UpdaterWithValue perfaceFaceDir = updaterReg.createValue(Direction.UP); diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/editor/anim/AnimationDisplayData.java b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/editor/anim/AnimationDisplayData.java index 4a5e3f8f..15366a5e 100644 --- a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/editor/anim/AnimationDisplayData.java +++ b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/editor/anim/AnimationDisplayData.java @@ -57,6 +57,8 @@ public enum AnimationDisplayData { SPEAKING(VanillaPose.SPEAKING, null, null, Type.LAYERS), TOOT_HORN_LEFT(VanillaPose.TOOT_HORN_LEFT, ItemSlot.LEFT_HAND, DisplayItem.GOAT_HORN, Type.HAND), TOOT_HORN_RIGHT(VanillaPose.TOOT_HORN_RIGHT, ItemSlot.RIGHT_HAND, DisplayItem.GOAT_HORN, Type.HAND), + IN_GUI(VanillaPose.IN_GUI, null, null, Type.LAYERS), + FIRST_PERSON_MOD(VanillaPose.FIRST_PERSON_MOD, null, null, Type.LAYERS), ; public final VanillaPose pose; public final ItemSlot slot; diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/editor/anim/EditorAnim.java b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/editor/anim/EditorAnim.java index c563a08a..8f651656 100644 --- a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/editor/anim/EditorAnim.java +++ b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/editor/anim/EditorAnim.java @@ -9,6 +9,7 @@ import com.tom.cpl.math.Vec3f; import com.tom.cpm.shared.animation.CustomPose; +import com.tom.cpm.shared.animation.Gesture; import com.tom.cpm.shared.animation.IPose; import com.tom.cpm.shared.animation.InterpolatorChannel; import com.tom.cpm.shared.animation.VanillaPose; @@ -73,10 +74,20 @@ public void apply() { public void applyPlay(long millis) { if(components == null || psfs == null)calculateSplines(); float step; + boolean remap = false; if(pose != null && pose instanceof VanillaPose && ((VanillaPose)pose).hasStateGetter()) { - int dd = (int) (editor.animTestSlider * VanillaPose.DYNAMIC_DURATION_MUL); - step = (float) dd % VanillaPose.DYNAMIC_DURATION_DIV / VanillaPose.DYNAMIC_DURATION_DIV * frames.size(); + step = editor.animTestSliders.getOrDefault("__pose", 0f); + remap = true; + } else if(displayName.startsWith(Gesture.VALUE_LAYER_PREFIX)) { + step = editor.animTestSliders.getOrDefault(getId(), 0f); + remap = true; } else step = (float) millis % duration / duration * frames.size(); + + if(remap) { + int dd = (int) (step * VanillaPose.DYNAMIC_DURATION_MUL); + step = (float) dd % VanillaPose.DYNAMIC_DURATION_DIV / VanillaPose.DYNAMIC_DURATION_DIV * frames.size(); + } + for (int i = 0; i < components.size(); i++) { ModelElement component = components.get(i); component.rc.setRotation(add, @@ -179,8 +190,9 @@ public List getComponentsFiltered() { @Override public String toString() { - if(pose != null)return editor.gui().i18nFormat("label.cpm.anim_pose", pose.getName(editor.gui(), displayName)); - return editor.gui().i18nFormat("label.cpm.anim_gesture", displayName); + if(pose != null)return editor.gui().i18nFormat("label.cpm.anim_pose", pose.getName(editor.gui(), getDisplayName())); + else if(isLayer())return editor.gui().i18nFormat("label.cpm.anim_layer", getDisplayName()); + return editor.gui().i18nFormat("label.cpm.anim_gesture", getDisplayName()); } public AnimFrame getSelectedFrame() { @@ -246,10 +258,22 @@ public IPose getPose() { } public String getId() { - int i = displayName.indexOf('#'); - if(i == -1)return displayName; + String nm = displayName; + int i = nm.indexOf('#'); + if(i == -1)return nm; + if(i == 0)return ""; + return nm.substring(0, i); + } + + public String getDisplayGroup() { + String nm = getDisplayName(); + int i = nm.indexOf('#'); + if(i == -1)return nm; if(i == 0)return ""; - return displayName.substring(0, i); + nm = nm.substring(0, i); + if(pose != null)return editor.gui().i18nFormat("label.cpm.anim_pose", pose.getName(editor.gui(), nm)); + else if(isLayer())return editor.gui().i18nFormat("label.cpm.anim_layer", nm); + return editor.gui().i18nFormat("label.cpm.anim_gesture", nm); } public void updateGui() { @@ -315,4 +339,14 @@ public void endDrag() { public void dragVal(VecType type, Vec3f vec) { if(currentFrame != null)currentFrame.dragVal(type, vec); } + + public String getDisplayName() { + if(displayName.startsWith(Gesture.LAYER_PREFIX))return displayName.substring(Gesture.LAYER_PREFIX.length()); + if(displayName.startsWith(Gesture.VALUE_LAYER_PREFIX))return displayName.substring(Gesture.VALUE_LAYER_PREFIX.length()); + return displayName; + } + + public boolean isLayer() { + return displayName.startsWith(Gesture.LAYER_PREFIX) || displayName.startsWith(Gesture.VALUE_LAYER_PREFIX); + } } diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/editor/gui/AnimTestPanel.java b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/editor/gui/AnimTestPanel.java index a8e3d458..c140a06a 100644 --- a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/editor/gui/AnimTestPanel.java +++ b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/editor/gui/AnimTestPanel.java @@ -12,17 +12,22 @@ import com.tom.cpl.gui.IGui; import com.tom.cpl.gui.MouseEvent; +import com.tom.cpl.gui.elements.Button; +import com.tom.cpl.gui.elements.ButtonIcon; import com.tom.cpl.gui.elements.Checkbox; import com.tom.cpl.gui.elements.DropDownBox; import com.tom.cpl.gui.elements.Label; import com.tom.cpl.gui.elements.Panel; +import com.tom.cpl.gui.elements.PopupMenu; import com.tom.cpl.gui.elements.Slider; import com.tom.cpl.gui.util.FlowLayout; import com.tom.cpl.math.Box; +import com.tom.cpl.math.Vec2i; import com.tom.cpl.util.ItemSlot; import com.tom.cpl.util.NamedElement; import com.tom.cpm.shared.MinecraftClientAccess; import com.tom.cpm.shared.animation.CustomPose; +import com.tom.cpm.shared.animation.Gesture; import com.tom.cpm.shared.animation.IPose; import com.tom.cpm.shared.animation.VanillaPose; import com.tom.cpm.shared.editor.Editor; @@ -41,6 +46,8 @@ public class AnimTestPanel extends Panel { private DropDownPanel otherHandRight; private List> poseBoxes; private Checkbox chbxLeftParrot, chbxRightParrot; + private PopupMenu customLayers; + private Set enabledLayers = new HashSet<>(); public AnimTestPanel(IGui gui, EditorGui e) { super(gui); @@ -56,6 +63,7 @@ public AnimTestPanel(IGui gui, EditorGui e) { editor.updateGui.add(() -> { poses.clear(); gestures.clear(); + customLayers = new PopupMenu(gui, e); gestures.add(new NamedElement<>(null, k -> gui.i18nFormat("label.cpm.no_gesture"))); for (VanillaPose p : VanillaPose.VALUES) { if(p == VanillaPose.CUSTOM || p == VanillaPose.GLOBAL)continue; @@ -64,6 +72,7 @@ public AnimTestPanel(IGui gui, EditorGui e) { poses.add(new NamedElement(p, this::poseToString)); } Set addedGestures = new HashSet<>(); + Set addedLayers = new HashSet<>(); Set addedPoses = new HashSet<>(); editor.animations.forEach(a -> { if(a.isCustom()) { @@ -73,14 +82,44 @@ public AnimTestPanel(IGui gui, EditorGui e) { addedPoses.add(name); poses.add(new NamedElement<>(a.pose, k -> name)); } + } else if(a.isLayer()) { + String id = a.getId(); + String name = a.getDisplayGroup(); + if(!addedLayers.contains(id)) { + addedLayers.add(id); + if(a.displayName.startsWith(Gesture.VALUE_LAYER_PREFIX)) { + Slider progressSlider = new Slider(gui, name + ": 0"); + progressSlider.setBounds(new Box(0, 0, 160, 20)); + progressSlider.setValue(editor.animTestSliders.getOrDefault(id, 0f)); + progressSlider.setAction(() -> { + progressSlider.setText(name + ": " + ((int) (progressSlider.getValue() * 100))); + editor.animTestSliders.put(id, progressSlider.getValue()); + }); + customLayers.add(progressSlider); + } else { + customLayers.addCheckbox(name, b -> { + if(enabledLayers.contains(id)) { + enabledLayers.remove(id); + } else { + enabledLayers.add(id); + } + b.setSelected(enabledLayers.contains(id)); + }).setSelected(enabledLayers.contains(id)); + } + } } else { - if(!addedGestures.contains(a.getId())) { - addedGestures.add(a.getId()); - gestures.add(new NamedElement<>(a.getId(), k -> k)); + String id = a.getId(); + String name = a.getDisplayGroup(); + if(!addedGestures.contains(id)) { + addedGestures.add(id); + gestures.add(new NamedElement<>(id, k -> name)); } } } }); + if(addedLayers.isEmpty()) { + customLayers.add(new Label(gui, gui.i18nFormat("label.cpm.no_elements")).setBounds(new Box(5, 5, 0, 0))); + } }); poseSel = createDropDown("label.cpm.pose", poses); @@ -122,10 +161,10 @@ public AnimTestPanel(IGui gui, EditorGui e) { progressSlider = new Slider(gui, gui.i18nFormat("label.cpm.animProgress", 0)); progressSlider.setVisible(false); progressSlider.setBounds(new Box(5, 0, 160, 20)); - progressSlider.setValue(editor.animTestSlider); + progressSlider.setValue(editor.animTestSliders.getOrDefault("__pose", 0f)); progressSlider.setAction(() -> { progressSlider.setText(gui.i18nFormat("label.cpm.animProgress", (int) (progressSlider.getValue() * 100))); - editor.animTestSlider = progressSlider.getValue(); + editor.animTestSliders.put("__pose", progressSlider.getValue()); }); addElement(progressSlider); @@ -177,6 +216,25 @@ public AnimTestPanel(IGui gui, EditorGui e) { chbxRightParrot.setAction(() -> chbxRightParrot.setSelected(!chbxRightParrot.isSelected())); addElement(chbxRightParrot); + Panel layersPanel = new Panel(gui); + layersPanel.setBounds(new Box(5, 0, 160, 20)); + layersPanel.addElement(new Label(gui, gui.i18nFormat("label.cpm.customLayers")).setBounds(new Box(0, 6, 0, 0))); + + Button layersDropDown = new ButtonIcon(gui, "editor", 24, 8, null) { + + @Override + public void mouseClick(MouseEvent evt) { + if(evt.isHovered(bounds)) { + Vec2i p = evt.getPos(); + customLayers.display(p.x - evt.x, p.y - evt.y + bounds.h + bounds.y, 160); + evt.consume(); + } + } + }; + layersDropDown.setBounds(new Box(140, 4, 12, 12)); + layersPanel.addElement(layersDropDown); + addElement(layersPanel); + layout.reflow(); editor.gestureFinished.add(() -> gestureSel.dropDown.setSelected(null)); @@ -241,7 +299,7 @@ public void draw(MouseEvent event, float partialTicks) { NamedElement gesture = gestureSel.getSelected(); if(gesture != null && gesture.getElem() != null) { for (EditorAnim anim : editor.animations) { - if(anim.isCustom() && anim.pose == null && anim.getId().equals(gesture.getElem())) { + if(anim.isCustom() && anim.pose == null && !anim.isLayer() && anim.getId().equals(gesture.getElem())) { editor.animsToPlay.add(anim); } } @@ -254,6 +312,18 @@ public void draw(MouseEvent event, float partialTicks) { }); if(chbxLeftParrot.isSelected())handlePose(VanillaPose.PARROT_LEFT); if(chbxRightParrot.isSelected())handlePose(VanillaPose.PARROT_RIGHT); + enabledLayers.forEach(l -> { + for (EditorAnim anim : editor.animations) { + if(anim.isCustom() && anim.pose == null && anim.isLayer() && anim.getId().equals(l)) { + editor.animsToPlay.add(anim); + } + } + }); + for (EditorAnim anim : editor.animations) { + if(anim.isCustom() && anim.pose == null && anim.isLayer() && anim.displayName.startsWith(Gesture.VALUE_LAYER_PREFIX)) { + editor.animsToPlay.add(anim); + } + } } private void handlePose(VanillaPose p) { diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/editor/gui/ViewportPanelAnim.java b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/editor/gui/ViewportPanelAnim.java index 53c864f7..2594525f 100644 --- a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/editor/gui/ViewportPanelAnim.java +++ b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/editor/gui/ViewportPanelAnim.java @@ -69,7 +69,7 @@ protected int getItemState(ItemSlot slot, int maxStates) { progress = getAnimProgress(); } else if(anims != null) { data = anims.stream().filter(p -> p.slot == slot && p.layerSlot != null).findFirst().orElse(null); - progress = data != null ? editor.animTestSlider : 0f; + progress = data != null ? editor.animTestSliders.getOrDefault("__pose", 0f) : 0f; } DisplayItem i = getHeldItem(slot); if(i == DisplayItem.CROSSBOW) { @@ -90,7 +90,7 @@ protected Hand poseModel0(VanillaPlayerModel p, MatrixStack matrixstack, float p progress = getAnimProgress(); } else if(anims != null) { data = anims.stream().filter(e -> e.type == Type.HAND).findFirst().orElse(null); - progress = data != null ? editor.animTestSlider : 0f; + progress = data != null ? editor.animTestSliders.getOrDefault("__pose", 0f) : 0f; } if(data == AnimationDisplayData.CROSSBOW_CH_LEFT || data == AnimationDisplayData.CROSSBOW_CH_RIGHT) { p.useAmount = progress; diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/editor/gui/popup/AnimationSettinsPopup.java b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/editor/gui/popup/AnimationSettinsPopup.java index 9a3bac24..59009b15 100644 --- a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/editor/gui/popup/AnimationSettinsPopup.java +++ b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/editor/gui/popup/AnimationSettinsPopup.java @@ -17,6 +17,7 @@ import com.tom.cpl.util.NamedElement; import com.tom.cpl.util.NamedElement.NameMapper; import com.tom.cpm.shared.animation.CustomPose; +import com.tom.cpm.shared.animation.Gesture; import com.tom.cpm.shared.animation.IPose; import com.tom.cpm.shared.animation.VanillaPose; import com.tom.cpm.shared.animation.interpolator.InterpolatorType; @@ -49,9 +50,19 @@ public AnimationSettinsPopup(IGui gui, Editor editor, boolean edit) { ats.add(typePose); AnimType typeGesture = new AnimType("gesture", true); ats.add(typeGesture); + AnimType typeLayer = new AnimType("layer", false); + ats.add(typeLayer); + AnimType typeValue = new AnimType("value", false); + ats.add(typeValue); if(edit && editor.selectedAnim != null && sel == null) { - if(editor.selectedAnim.pose == null)sel = typeGesture; - else sel = typePose; + if(editor.selectedAnim.pose == null) { + if(editor.selectedAnim.displayName.startsWith(Gesture.LAYER_PREFIX)) + sel = typeLayer; + else if(editor.selectedAnim.displayName.startsWith(Gesture.VALUE_LAYER_PREFIX)) + sel = typeValue; + else + sel = typeGesture; + } else sel = typePose; } ListPicker typeDd = new ListPicker<>(editor.frame, ats); @@ -79,7 +90,7 @@ public AnimationSettinsPopup(IGui gui, Editor editor, boolean edit) { this.addElement(new Label(gui, gui.i18nFormat("label.cpm.name")).setBounds(new Box(5, 70, 0, 0))); TextField nameField = new TextField(gui); - if(edit && editor.selectedAnim != null)nameField.setText(editor.selectedAnim.displayName); + if(edit && editor.selectedAnim != null)nameField.setText(editor.selectedAnim.getDisplayName()); nameField.setBounds(new Box(5, 80, 190, 20)); this.addElement(nameField); @@ -110,14 +121,20 @@ public AnimationSettinsPopup(IGui gui, Editor editor, boolean edit) { }); Button okBtn = new Button(gui, gui.i18nFormat("button.cpm.ok"), () -> { + String name = nameField.getText(); + AnimType at = typeDd.getSelected(); + IPose pose = at.pose == null && at.option.equals("pose") ? new CustomPose(name) : at.pose; + if(at.pose == null) { + if(at.option.equals("layer")) { + name = Gesture.LAYER_PREFIX + name; + } else if(at.option.equals("value")) { + name = Gesture.VALUE_LAYER_PREFIX + name; + } + } if(edit) { - AnimType at = typeDd.getSelected(); - IPose pose = at.pose == null && at.option.equals("pose") ? new CustomPose(nameField.getText()) : at.pose; - editor.editAnim(pose, nameField.getText(), boxAdd.isSelected(), at.loop && boxLoop.isSelected(), intBox.getSelected().getElem()); + editor.editAnim(pose, name, boxAdd.isSelected(), at.loop && boxLoop.isSelected(), intBox.getSelected().getElem()); } else { - AnimType at = typeDd.getSelected(); - IPose pose = at.pose == null && at.option.equals("pose") ? new CustomPose(nameField.getText()) : at.pose; - editor.addNewAnim(pose, nameField.getText(), boxAdd.isSelected(), at.loop && boxLoop.isSelected(), intBox.getSelected().getElem()); + editor.addNewAnim(pose, name, boxAdd.isSelected(), at.loop && boxLoop.isSelected(), intBox.getSelected().getElem()); } this.close(); }); diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/editor/gui/popup/ColorButton.java b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/editor/gui/popup/ColorButton.java index ce71b110..19fa292d 100644 --- a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/editor/gui/popup/ColorButton.java +++ b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/editor/gui/popup/ColorButton.java @@ -20,7 +20,7 @@ public class ColorButton extends Button { private int color; public ColorButton(IGui gui, Frame frame, IntConsumer action) { super(gui, "", null); - this.action = () -> frame.openPopup(new ColorPopup(gui)); + this.action = () -> frame.openPopup(new ColorPopup(frame)); this.actionColor = action; } @@ -67,8 +67,10 @@ public class ColorPopup extends PopupPanel { private TextField hexField; - public ColorPopup(IGui gui) { - super(gui); + public ColorPopup(Frame frm) { + super(frm.getGui()); + + boolean small = frm.getBounds().h < 320; sliderR = new SliderGradient(gui); sliderG = new SliderGradient(gui); @@ -97,23 +99,23 @@ public ColorPopup(IGui gui) { spinnerB.setValue(b); updateColorRGB_spinner(); - sliderR.setBounds(new Box(5, 120, 100, 20)); - sliderG.setBounds(new Box(5, 150, 100, 20)); - sliderB.setBounds(new Box(5, 180, 100, 20)); + sliderR.setBounds(new Box(5, small ? 30 : 120, 100, 20)); + sliderG.setBounds(new Box(5, small ? 60 : 150, 100, 20)); + sliderB.setBounds(new Box(5, small ? 90 : 180, 100, 20)); sliderH.setBounds(new Box(5, 30, 100, 20)); sliderS.setBounds(new Box(5, 60, 100, 20)); sliderV.setBounds(new Box(5, 90, 100, 20)); - spinnerR.setBounds(new Box(110, 120, 40, 20)); - spinnerG.setBounds(new Box(110, 150, 40, 20)); - spinnerB.setBounds(new Box(110, 180, 40, 20)); + spinnerR.setBounds(new Box(110, small ? 30 : 120, 40, 20)); + spinnerG.setBounds(new Box(110, small ? 60 : 150, 40, 20)); + spinnerB.setBounds(new Box(110, small ? 90 : 180, 40, 20)); spinnerH.setBounds(new Box(110, 30, 40, 20)); spinnerS.setBounds(new Box(110, 60, 40, 20)); spinnerV.setBounds(new Box(110, 90, 40, 20)); - hexField.setBounds(new Box(5, 210, 100, 20)); + hexField.setBounds(new Box(5, small ? 120 : 210, 100, 20)); spinnerR.setDp(0); spinnerG.setDp(0); @@ -149,13 +151,15 @@ public ColorPopup(IGui gui) { addElement(spinnerG); addElement(spinnerB); - addElement(sliderH); - addElement(sliderS); - addElement(sliderV); + if(!small) { + addElement(sliderH); + addElement(sliderS); + addElement(sliderV); - addElement(spinnerH); - addElement(spinnerS); - addElement(spinnerV); + addElement(spinnerH); + addElement(spinnerS); + addElement(spinnerV); + } addElement(hexField); @@ -167,18 +171,18 @@ public ColorPopup(IGui gui) { actionColor.accept(color); close(); }); - ok.setBounds(new Box(5, 265, 100, 16)); + ok.setBounds(new Box(5, small ? 175 : 265, 100, 16)); addElement(ok); for(int i = 0;i<6;i++) { int c = i < colorCache.size() ? colorCache.get(colorCache.size() - i - 1) : 0xffffffff; ColorButton btn = new ColorButton(gui, () -> loadColor(c)); btn.setColor(c); - btn.setBounds(new Box(5 + i * 25, 240, 20, 16)); + btn.setBounds(new Box(5 + i * 25, small ? 150 : 240, 20, 16)); addElement(btn); } - setBounds(new Box(0, 0, 160, 290)); + setBounds(new Box(0, 0, 160, small ? 200 : 290)); updateDisplayText(); } diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/editor/gui/popup/SettingsPopup.java b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/editor/gui/popup/SettingsPopup.java index 98d1d30d..faa0d0b8 100644 --- a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/editor/gui/popup/SettingsPopup.java +++ b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/editor/gui/popup/SettingsPopup.java @@ -17,10 +17,13 @@ public SettingsPopup(Frame frm) { super(frm.getGui()); this.frm = frm; - panel = new SettingsPanel(frm, this, 400, 300, this::close); + int w = Math.min(frm.getBounds().w / 4 * 3, 400); + int h = Math.min(frm.getBounds().h / 4 * 3, 300); + + panel = new SettingsPanel(frm, this, w, h, this::close); addElement(panel); - setBounds(new Box(0, 0, 400, 300)); + setBounds(new Box(0, 0, w, h)); } @Override diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/gui/GestureGui.java b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/gui/GestureGui.java index fe5ced11..d4131801 100644 --- a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/gui/GestureGui.java +++ b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/gui/GestureGui.java @@ -13,14 +13,16 @@ import com.tom.cpl.gui.elements.Checkbox; import com.tom.cpl.gui.elements.Label; import com.tom.cpl.gui.elements.Panel; +import com.tom.cpl.gui.elements.ScrollPanel; +import com.tom.cpl.gui.elements.Slider; import com.tom.cpl.gui.elements.Tooltip; import com.tom.cpl.gui.util.FlowLayout; import com.tom.cpl.math.Box; import com.tom.cpm.shared.MinecraftClientAccess; import com.tom.cpm.shared.MinecraftClientAccess.ServerStatus; import com.tom.cpm.shared.MinecraftObjectHolder; -import com.tom.cpm.shared.animation.AnimationRegistry.Gesture; -import com.tom.cpm.shared.animation.CustomPose; +import com.tom.cpm.shared.animation.Gesture; +import com.tom.cpm.shared.animation.IManualGesture; import com.tom.cpm.shared.config.ConfigChangeRequest; import com.tom.cpm.shared.config.ConfigKeys; import com.tom.cpm.shared.config.ModConfig; @@ -31,14 +33,16 @@ import com.tom.cpm.shared.editor.gui.EditorGui; import com.tom.cpm.shared.editor.gui.FirstPersonHandPosGui; import com.tom.cpm.shared.model.TextureSheetType; +import com.tom.cpm.shared.network.ServerCaps; import com.tom.cpm.shared.skin.TextureProvider; import com.tom.cpm.shared.util.Log; public class GestureGui extends Frame { private GestureButton hoveredBtn; - private Panel panel; + private Panel panel, contentPanel; private int tickCounter; - private Tooltip qaTip; + private ModelDefinition def; + private ModelLoadingState state; public GestureGui(IGui gui) { super(gui); @@ -53,7 +57,7 @@ public GestureGui(IGui gui) { public void keyPressed(KeyboardEvent event) { if(hoveredBtn != null) { ConfigEntry ce = ModConfig.getCommonConfig().getEntry(ConfigKeys.KEYBINDS); - String hoveredID = hoveredBtn.pose != null ? "p" + hoveredBtn.pose.getName() : "g" + hoveredBtn.gesture.name; + String hoveredID = hoveredBtn.gesture.getGestureId(); String keybindPressed = null; List dup = new ArrayList<>(); for(IKeybind kb : MinecraftClientAccess.get().getKeybinds()) { @@ -70,6 +74,7 @@ public void keyPressed(KeyboardEvent event) { } if(keybindPressed != null) { ce.setString(keybindPressed, hoveredID); + ce.setString(keybindPressed + "_mode", !hoveredBtn.layer && gui.isCtrlDown() ? "hold" : "press"); for (String k : dup) { ce.setString(k, ""); } @@ -103,19 +108,75 @@ public void tick() { @Override public void initFrame(int width, int height) { - ModelDefinition def = MinecraftClientAccess.get().getCurrentClientPlayer().getModelDefinition0(); + contentPanel = new Panel(gui); + contentPanel.setBounds(new Box(0, 0, width, height)); + def = MinecraftClientAccess.get().getCurrentClientPlayer().getModelDefinition0(); + initContent(contentPanel); + addElement(contentPanel); + } + + private void initContent(Panel p) { + int width = p.getBounds().w; + int height = p.getBounds().h; Log.debug(def); + if(def != null) + this.state = def.getResolveState(); ServerStatus status = MinecraftClientAccess.get().getServerSideStatus(); if(status == ServerStatus.OFFLINE) { String str = "How did you get here?"; Label lbl = new Label(gui, str); lbl.setBounds(new Box(width / 2 - gui.textWidth(str) / 2, height / 2 - 4, 0, 0)); - addElement(lbl); + p.addElement(lbl); return; } - qaTip = new Tooltip(this, gui.i18nFormat("tooltip.cpm.gestureQuickAccess")); + List keys = new ArrayList<>(); + { + int i = 0; + for(IKeybind kb : MinecraftClientAccess.get().getKeybinds()) { + if(kb.getName().startsWith("qa")) { + i++; + String k = kb.getBoundKey(); + if(k.isEmpty())k = gui.i18nFormat("label.cpm.key_unbound"); + keys.add(gui.i18nFormat("label.cpm.quick_key_bound", i, k)); + } + } + i++; + keys.add(gui.i18nFormat("label.cpm.quick_key_info")); + } + if((bounds.w - 360) / 2 > 100) { + String tt = gui.i18nFormat("tooltip.cpm.gestureQuickAccess"); + Panel qk = new Panel(gui); + int i = 0; + int mw = 0; + for (String k : keys) { + i++; + qk.addElement(new Label(gui, k).setBounds(new Box(0, i * 10, 0, 10))); + mw = Math.max(gui.textWidth(k), mw); + } + i++; + qk.setBounds(new Box(10, 0, 200, i * 10)); + + Label lbl = new Label(gui, ""); + lbl.setTooltip(new Tooltip(this, tt)); + qk.addElement(lbl.setBounds(new Box(0, 0, 200, i * 10))); + p.addElement(qk); + } else { + StringBuilder tt = new StringBuilder(); + for (String key : keys) { + tt.append(key); + tt.append('\\'); + } + + tt.append(gui.i18nFormat("label.cpm.quick_key_info")); + tt.append("\\\\"); + tt.append(gui.i18nFormat("tooltip.cpm.gestureQuickAccess")); + String text = gui.i18nFormat("label.cpm.quick_key_short"); + Label lbl = new Label(gui, text); + lbl.setTooltip(new Tooltip(this, tt.toString())); + p.addElement(lbl.setBounds(new Box(10, 10, gui.textWidth(text), 10))); + } int h; - if(def != null && def.getResolveState() == ModelLoadingState.LOADED && status != ServerStatus.UNAVAILABLE) { + if(def != null && this.state == ModelLoadingState.LOADED && status != ServerStatus.UNAVAILABLE) { int[] id = new int[] {0}; panel = new Panel(gui); def.getAnimations().getGestures().forEach((nm, g) -> panel.addElement(new GestureButton(g, id[0]++))); @@ -124,16 +185,26 @@ public void initFrame(int width, int height) { String str = gui.i18nFormat("label.cpm.nothing_here"); Label lbl = new Label(gui, str); lbl.setBounds(new Box(width / 2 - gui.textWidth(str) / 2, height / 2 - 4, 0, 0)); - addElement(lbl); + p.addElement(lbl); h = 10; } else { h = (id[0] / 4 + 1) * 40; - panel.setBounds(new Box(width / 2 - 180, height / 2 - h / 2, 360, h)); - addElement(panel); + + if(h < height - 150) { + panel.setBounds(new Box(width / 2 - 180, height / 2 - h / 2, 360, h)); + p.addElement(panel); + } else { + panel.setBounds(new Box(0, 0, 360, h)); + ScrollPanel scp = new ScrollPanel(gui); + h = height - 120; + scp.setBounds(new Box(width / 2 - 180, 60, 363, height - 150)); + scp.setDisplay(panel); + p.addElement(scp); + } } - } else if(def != null && (def.getResolveState() == ModelLoadingState.ERRORRED || def.getResolveState() == ModelLoadingState.SAFETY_BLOCKED)) { + } else if(def != null && (this.state == ModelLoadingState.ERRORRED || this.state == ModelLoadingState.SAFETY_BLOCKED)) { String txt = ""; - switch (def.getResolveState()) { + switch (this.state) { case ERRORRED: txt = gui.i18nFormat("label.cpm.errorLoadingModel", def.getError().toString()); break; @@ -145,34 +216,34 @@ public void initFrame(int width, int height) { default: break; } - addElement(new Label(gui, txt).setBounds(new Box(width / 2 - gui.textWidth(txt) / 2, height / 2 - 4, 0, 0))); + p.addElement(new Label(gui, txt).setBounds(new Box(width / 2 - gui.textWidth(txt) / 2, height / 2 - 4, 0, 0))); txt = gui.i18nFormat("label.cpm.checkErrorLog"); - addElement(new Label(gui, txt).setBounds(new Box(width / 2 - gui.textWidth(txt) / 2, height / 2 - 4 + 10, 0, 0))); + p.addElement(new Label(gui, txt).setBounds(new Box(width / 2 - gui.textWidth(txt) / 2, height / 2 - 4 + 10, 0, 0))); h = 20; } else if(status == ServerStatus.UNAVAILABLE) { String str = gui.i18nFormat("label.cpm.feature_unavailable"); Label lbl = new Label(gui, str); lbl.setBounds(new Box(width / 2 - gui.textWidth(str) / 2, height / 2 - 4, 0, 0)); - addElement(lbl); + p.addElement(lbl); h = 10; } else { String str = gui.i18nFormat("label.cpm.nothing_here"); Label lbl = new Label(gui, str); lbl.setBounds(new Box(width / 2 - gui.textWidth(str) / 2, height / 2 - 4, 0, 0)); - addElement(lbl); + p.addElement(lbl); h = 10; } Panel btnPanel = new Panel(gui); btnPanel.setBounds(new Box(width / 2 - 180, height / 2 - h / 2 - 30, 360, 20)); - addElement(btnPanel); + p.addElement(btnPanel); if(status != ServerStatus.UNAVAILABLE) { - Button btnRstG = new Button(gui, gui.i18nFormat("button.cpm.anim_reset_gesture"), () -> setGesture(null)); + Button btnRstG = new Button(gui, gui.i18nFormat("button.cpm.anim_reset_gesture"), this::clearGesture); btnRstG.setBounds(new Box(0, 0, 100, 20)); btnPanel.addElement(btnRstG); - Button btnRstP = new Button(gui, gui.i18nFormat("button.cpm.anim_reset_pose"), () -> setPose(null)); + Button btnRstP = new Button(gui, gui.i18nFormat("button.cpm.anim_reset_pose"), this::clearPose); btnRstP.setBounds(new Box(110, 0, 100, 20)); btnPanel.addElement(btnRstP); } @@ -189,7 +260,7 @@ public void initFrame(int width, int height) { Panel btnPanel2 = new Panel(gui); btnPanel2.setBounds(new Box(width - 162, 0, 160, 0)); - addElement(btnPanel2); + p.addElement(btnPanel2); FlowLayout fl = new FlowLayout(btnPanel2, 0, 1); @@ -231,7 +302,7 @@ public void initFrame(int width, int height) { Panel btnPanel3 = new Panel(gui); btnPanel3.setBounds(new Box(0, height - 60, 160, 60)); - addElement(btnPanel3); + p.addElement(btnPanel3); Button btnSkinMenu = new Button(gui, gui.i18nFormat("button.cpm.models"), () -> MinecraftClientAccess.get().openGui(ModelsGui::new)); btnSkinMenu.setBounds(new Box(0, 40, 160, 20)); @@ -256,20 +327,14 @@ public void initFrame(int width, int height) { public void draw(MouseEvent event, float partialTicks) { hoveredBtn = null; super.draw(event, partialTicks); - int i = 0; - for(IKeybind kb : MinecraftClientAccess.get().getKeybinds()) { - if(kb.getName().startsWith("qa")) { - i++; - String k = kb.getBoundKey(); - if(k.isEmpty())k = gui.i18nFormat("label.cpm.key_unbound"); - gui.drawText(10, i * 10, gui.i18nFormat("label.cpm.quick_key_bound", i, k), 0xffffffff); - } - } - if(event.isInBounds(new Box(10, 10, 100, 60))) { - qaTip.set(); + + ModelDefinition def = MinecraftClientAccess.get().getCurrentClientPlayer().getModelDefinition0(); + if(def != this.def || (def != null && def.getResolveState() != state)) { + contentPanel.getElements().clear(); + this.def = def; + initContent(contentPanel); } - ModelDefinition def = MinecraftClientAccess.get().getCurrentClientPlayer().getModelDefinition(); if(MinecraftObjectHolder.DEBUGGING && gui.isAltDown() && def != null) { TextureProvider skin = def.getTexture(TextureSheetType.SKIN, true); if(skin != null && skin.texture != null) { @@ -282,53 +347,82 @@ public void draw(MouseEvent event, float partialTicks) { } } - private void setGesture(Gesture g) { - ModelDefinition def = MinecraftClientAccess.get().getCurrentClientPlayer().getModelDefinition(); - if(def != null)MinecraftClientAccess.get().getPlayerRenderManager().getAnimationEngine().playGesture(def.getAnimations(), g); + private void clearGesture() { + if(def != null)MinecraftClientAccess.get().getPlayerRenderManager().getAnimationEngine().playGesture(def.getAnimations(), null); } - private void setPose(CustomPose pose) { - ModelDefinition def = MinecraftClientAccess.get().getCurrentClientPlayer().getModelDefinition(); - if(def != null)MinecraftClientAccess.get().getPlayerRenderManager().getAnimationEngine().setCustomPose(def.getAnimations(), pose); + private void clearPose() { + if(def != null)MinecraftClientAccess.get().getPlayerRenderManager().getAnimationEngine().setCustomPose(def.getAnimations(), null); } - private class GestureButton extends Button { - private Gesture gesture; - private CustomPose pose; - private String kb; + private void setManualGesture(IManualGesture g) { + if(def != null)g.play(def.getAnimations()); + } - public GestureButton(String name, int id) { - super(getGui(), name, null); + private class GestureButton extends Panel { + private IManualGesture gesture; + private String kb, kbMode, name; + private boolean layer, value; + + public GestureButton(int id) { + super(GestureGui.this.gui); setBounds(new Box((id % 4) * 90, (id / 4) * 40, 80, 30)); } - public GestureButton(Gesture g, int id) { - this(g.name, id); - setAction(() -> setGesture(g)); + public GestureButton(IManualGesture g, int id) { + this(id); + String nm = g.getName(); + if(g instanceof Gesture) { + layer = nm.startsWith(Gesture.LAYER_PREFIX); + value = nm.startsWith(Gesture.VALUE_LAYER_PREFIX); + } + if(layer)nm = nm.substring(Gesture.LAYER_PREFIX.length()); + else if(value)nm = nm.substring(Gesture.VALUE_LAYER_PREFIX.length()); + else { + Button btn = new Button(gui, "", () -> setManualGesture(g)); + btn.setBounds(new Box(0, 0, bounds.w, bounds.h)); + addElement(btn); + } + this.name = nm; this.gesture = g; getKb(); - } - - public GestureButton(CustomPose pose, int id) { - this(pose.getName(), id); - setAction(() -> setPose(pose)); - this.pose = pose; - getKb(); + if(layer || value) { + if(!MinecraftClientAccess.get().getNetHandler().hasServerCap(ServerCaps.GESTURES)) { + setEnabled(false); + Slider s = new Slider(gui, nm); + s.setBounds(new Box(0, 0, bounds.w, bounds.h)); + s.setEnabled(false); + s.setTooltip(new Tooltip(GestureGui.this, gui.i18nFormat("label.cpm.feature_unavailable"))); + addElement(s); + } else if(value) { + Slider s = new Slider(gui, nm); + s.setBounds(new Box(0, 0, bounds.w, bounds.h)); + s.setAction(() -> { + if(def != null) + MinecraftClientAccess.get().getPlayerRenderManager().getAnimationEngine().setLayerValue(def.getAnimations(), (Gesture) g, s.getValue()); + }); + if(def != null) + s.setValue(Byte.toUnsignedInt(MinecraftClientAccess.get().getPlayerRenderManager().getAnimationEngine().getGestureValue(def.getAnimations(), (Gesture) g)) / 255f); + addElement(s); + } else if(layer) { + Button btn = new Button(gui, "", () -> setManualGesture(g)); + btn.setBounds(new Box(0, 0, bounds.w, bounds.h)); + addElement(btn); + } + } } public void getKb() { ConfigEntry ce = ModConfig.getCommonConfig().getEntry(ConfigKeys.KEYBINDS); this.kb = null; + this.kbMode = null; for(IKeybind kb : MinecraftClientAccess.get().getKeybinds()) { if(kb.getName().startsWith("qa")) { String c = ce.getString(kb.getName(), null); if(c != null) { - if(pose != null && c.startsWith("p") && c.substring(1).equals(pose.getName())) { - this.kb = kb.getName(); - break; - } - if(gesture != null && c.startsWith("g") && c.substring(1).equals(gesture.name)) { + if(c.equals(gesture.getGestureId())) { this.kb = kb.getName(); + this.kbMode = ce.getString(kb.getName() + "_mode", "press"); break; } } @@ -338,6 +432,10 @@ public void getKb() { @Override public void draw(MouseEvent event, float partialTicks) { + if(value) { + super.draw(event, partialTicks); + return; + } int w = gui.textWidth(name); int bgColor = gui.getColors().button_fill; int color = gui.getColors().button_text_color; @@ -349,20 +447,40 @@ public void draw(MouseEvent event, float partialTicks) { bgColor = gui.getColors().button_hover; } gui.drawBox(bounds.x, bounds.y, bounds.w, bounds.h, gui.getColors().button_border); - gui.drawBox(bounds.x+1, bounds.y+1, bounds.w-2, bounds.h-2, bgColor); + if(layer) { + if(def != null) { + boolean on = MinecraftClientAccess.get().getPlayerRenderManager().getAnimationEngine().getGestureValue(def.getAnimations(), (Gesture) gesture) != 0; + int bw = bounds.w-2; + gui.drawBox(bounds.x + 1, bounds.y + 1, bw / 2, bounds.h - 2, on ? 0xff00ff00 : bgColor); + gui.drawBox(bounds.x + 1 + bw / 2, bounds.y + 1, bw / 2, bounds.h - 2, on ? bgColor : 0xffff0000); + } + } else { + gui.drawBox(bounds.x+1, bounds.y+1, bounds.w-2, bounds.h-2, bgColor); + } gui.drawText(bounds.x + bounds.w / 2 - w / 2, bounds.y + bounds.h / 2 - 8, name, color); + String boundKey = gui.i18nFormat("label.cpm.key_unbound"); if(kb != null) { for(IKeybind kb : MinecraftClientAccess.get().getKeybinds()) { if(kb.getName().equals(this.kb)) { String k = kb.getBoundKey(); if(k.isEmpty())k = gui.i18nFormat("label.cpm.key_unbound"); + boundKey = k; gui.drawText(bounds.x + bounds.w / 2 - w / 2, bounds.y + bounds.h / 2 + 4, k, color); break; } } } if(event.isHovered(bounds)) { - hoveredBtn = this; + if(!enabled) { + new Tooltip(GestureGui.this, gui.i18nFormat("label.cpm.feature_unavailable")).set(); + } else { + hoveredBtn = this; + String kbMode = this.kbMode != null ? gui.i18nFormat("label.cpm.gestureMode." + this.kbMode) : gui.i18nFormat("label.cpm.key_unbound"); + if(layer) + new Tooltip(GestureGui.this, gui.i18nFormat("tooltip.cpm.gestureButton", name, boundKey)).set(); + else + new Tooltip(GestureGui.this, gui.i18nFormat("tooltip.cpm.gestureButton.mode", name, boundKey, kbMode)).set(); + } } } } diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/gui/panel/SettingsPanel.java b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/gui/panel/SettingsPanel.java index b27bfab2..531a7495 100644 --- a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/gui/panel/SettingsPanel.java +++ b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/gui/panel/SettingsPanel.java @@ -88,6 +88,8 @@ private SettingsPanel(Frame frm, PopupPanel popup, int width, int height, Config makeCheckbox(general, ConfigKeys.WIKI_OFFLINE_MODE, false); + makeCheckbox(general, ConfigKeys.GESTURE_AUTO_RESET, true); + MinecraftClientAccess.get().populatePlatformSettings("general", general); layout.reflow(); @@ -128,7 +130,7 @@ private SettingsPanel(Frame frm, PopupPanel popup, int width, int height, Config buttonPosMode = new Button(gui, "", null); buttonPosMode.setAction(() -> { - ce.setBoolean(ConfigKeys.EDITOR_POSITION_MODE, !ce.getSetBoolean(ConfigKeys.EDITOR_POSITION_MODE, false)); + ce.setBoolean(ConfigKeys.EDITOR_POSITION_MODE, !ce.getBoolean(ConfigKeys.EDITOR_POSITION_MODE, false)); updatePosModeBtn(); }); buttonPosMode.setBounds(new Box(5, 0, 250, 20)); @@ -219,7 +221,7 @@ private void addAlphaSlider(Panel panel, String key, int def) { ce.setFloat(key, alphaSlider.getValue()); alphaSlider.setText(formatAlphaSlider(key, def)); }); - alphaSlider.setValue(ce.getSetFloat(key, def / 255f)); + alphaSlider.setValue(ce.getFloat(key, def / 255f)); alphaSlider.setTooltip(new Tooltip(frm, gui.i18nFormat("tooltip.cpm.config." + key))); p.addElement(alphaSlider); @@ -244,7 +246,7 @@ private Slider addScaleSlider(Panel panel, String key, float def, float div, flo ce.setFloat(key, scaleSlider.getValue() * (max - min) + min); scaleSlider.setText(formatScaleSlider(key, def)); }); - scaleSlider.setValue((ce.getSetFloat(key, def) - min) / (max - min)); + scaleSlider.setValue((ce.getFloat(key, def) - min) / (max - min)); scaleSlider.setTooltip(new Tooltip(frm, gui.i18nFormat("tooltip.cpm.config." + key))); p.addElement(scaleSlider); @@ -270,7 +272,7 @@ private String formatScaleSlider(String key, float def) { private void makeCheckbox(Panel panel, String key, boolean def) { Checkbox chxbx = new Checkbox(gui, gui.i18nFormat("label.cpm.config." + key)); - chxbx.setSelected(ce.getSetBoolean(key, def)); + chxbx.setSelected(ce.getBoolean(key, def)); chxbx.setAction(() -> { boolean b = !ce.getBoolean(key, def); chxbx.setSelected(b); diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/model/render/ModelRenderManager.java b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/model/render/ModelRenderManager.java index edf00948..82ff4f8f 100644 --- a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/model/render/ModelRenderManager.java +++ b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/model/render/ModelRenderManager.java @@ -263,6 +263,7 @@ protected void bindDefaultTexture(S cbi, TextureSheetType tex) {} protected void bindFirstSetup() { if(playerObj != null)playerObj.updateFromModel(model); + def.itemTransforms.clear(); for (int i = 0; i < redirectRenderers.size(); i++) { RedirectRenderer

re = redirectRenderers.get(i); VanillaModelPart part = re.getPart(); @@ -499,7 +500,7 @@ public default void render(RenderedCube elem, MatrixStack matrixStackIn, VBuffer } matrixStackIn.translate(c.offset.x / 16f, c.offset.y / 16f, c.offset.z / 16f); matrixStackIn.scale(c.scale.x, c.scale.y, c.scale.z); - holder.def.storeTransform(cube.itemRenderer, matrixStackIn, !doRenderRoot || (doRenderElems && cube.display)); + holder.def.storeTransform(cube.itemRenderer, matrixStackIn, (!doRenderRoot || doRenderElems) && cube.display); matrixStackIn.pop(); continue; } diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/IC2SPacket.java b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/IC2SPacket.java new file mode 100644 index 00000000..5746c9b2 --- /dev/null +++ b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/IC2SPacket.java @@ -0,0 +1,18 @@ +package com.tom.cpm.shared.network; + +import com.tom.cpm.shared.network.NetH.ServerNetH; + +public interface IC2SPacket extends IPacket { + + @Override + default void handle(NetHandler handler, NetH from) { + handle0(handler, from); + } + + default

void handle0(NetHandler handler, NetH from) { + ServerNetH h = (ServerNetH) from; + handle(handler, h, handler.getPlayer(h)); + } + +

void handle(NetHandler handler, ServerNetH from, P player); +} diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/IPacket.java b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/IPacket.java new file mode 100644 index 00000000..fb916887 --- /dev/null +++ b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/IPacket.java @@ -0,0 +1,15 @@ +package com.tom.cpm.shared.network; + +import java.io.IOException; + +import com.tom.cpm.shared.io.IOHelper; + +public interface IPacket { + void read(IOHelper pb) throws IOException; + void write(IOHelper pb) throws IOException; + void handle(NetHandler handler, NetH from); + + default void handleRaw(NetHandler handler, NetH from) { + handler.execute(from, () -> handle(handler, from)); + } +} diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/IS2CPacket.java b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/IS2CPacket.java new file mode 100644 index 00000000..c0004090 --- /dev/null +++ b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/IS2CPacket.java @@ -0,0 +1,5 @@ +package com.tom.cpm.shared.network; + +public interface IS2CPacket extends IPacket { + +} diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/NetHandler.java b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/NetHandler.java index daf3cb36..44847d6a 100644 --- a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/NetHandler.java +++ b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/NetHandler.java @@ -1,6 +1,5 @@ package com.tom.cpm.shared.network; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; @@ -25,60 +24,48 @@ import com.tom.cpl.config.ConfigEntry; import com.tom.cpl.function.ToFloatFunction; import com.tom.cpl.function.TriFunction; -import com.tom.cpl.math.MathHelper; import com.tom.cpl.nbt.NBTTag; import com.tom.cpl.nbt.NBTTagCompound; import com.tom.cpl.nbt.NBTTagList; import com.tom.cpl.nbt.NBTTagString; -import com.tom.cpl.text.FormatText; import com.tom.cpl.text.IText; -import com.tom.cpl.text.KeybindText; import com.tom.cpl.text.LiteralText; import com.tom.cpl.util.Pair; import com.tom.cpl.util.ThrowingConsumer; import com.tom.cpl.util.TriConsumer; -import com.tom.cpm.shared.MinecraftClientAccess; import com.tom.cpm.shared.MinecraftObjectHolder; import com.tom.cpm.shared.animation.VanillaPose; -import com.tom.cpm.shared.config.BuiltInSafetyProfiles; import com.tom.cpm.shared.config.ConfigChangeRequest; import com.tom.cpm.shared.config.ConfigKeys; import com.tom.cpm.shared.config.ModConfig; -import com.tom.cpm.shared.config.Player; import com.tom.cpm.shared.config.PlayerData; -import com.tom.cpm.shared.config.PlayerSpecificConfigKey; -import com.tom.cpm.shared.config.PlayerSpecificConfigKey.KeyGroup; -import com.tom.cpm.shared.config.SocialConfig; import com.tom.cpm.shared.definition.ModelDefinition; -import com.tom.cpm.shared.definition.ModelDefinitionLoader; import com.tom.cpm.shared.io.IOHelper; -import com.tom.cpm.shared.io.ModelFile; import com.tom.cpm.shared.model.ScaleData; import com.tom.cpm.shared.network.NetH.ServerNetH; +import com.tom.cpm.shared.network.packet.GestureC2S; +import com.tom.cpm.shared.network.packet.GetSkinS2C; +import com.tom.cpm.shared.network.packet.HelloC2S; +import com.tom.cpm.shared.network.packet.HelloS2C; +import com.tom.cpm.shared.network.packet.ReceiveEventS2C; +import com.tom.cpm.shared.network.packet.RecommendSafetyS2C; +import com.tom.cpm.shared.network.packet.ScaleInfoS2C; +import com.tom.cpm.shared.network.packet.SetScaleC2S; +import com.tom.cpm.shared.network.packet.SetSkinC2S; +import com.tom.cpm.shared.network.packet.SetSkinS2C; +import com.tom.cpm.shared.network.packet.SubEventC2S; import com.tom.cpm.shared.util.Log; import com.tom.cpm.shared.util.ScalingOptions; -@SuppressWarnings("resource") public class NetHandler { public static final String GET_SKIN = "get_skin"; public static final String SET_SKIN = "set_skin"; public static final String HELLO = "hello"; - public static final String SKIN_LAYERS = "layer"; public static final String SET_SCALE = "set_scl"; public static final String RECOMMEND_SAFETY = "rec_sfy"; public static final String SUBSCRIBE_EVENT = "sub_evt"; public static final String RECEIVE_EVENT = "rec_evt"; - - public static final String FORCED_TAG = "forced"; - public static final String DATA_TAG = "data"; - public static final String PROFILE_TAG = "profile"; - public static final String PROFILE_DATA = "data"; - public static final String SERVER_CAPS = "caps"; - public static final String EVENT_LIST = "eventList"; - public static final String KICK_TIME = "kickTime"; - public static final String SCALING = "scaling"; - - public static final FormatText FORCED_CHAT_MSG = new FormatText("chat.cpm.skinForced"); + public static final String GESTURE = "gesture"; protected Function getPlayerUUID; private TriConsumer sendPacket; @@ -99,62 +86,73 @@ public class NetHandler { protected Predicate

getIsCreativeFlying; protected Map> scaleSetters = new EnumMap<>(ScalingOptions.class); - public final RL helloPacket; - public final RL setSkin; - public final RL getSkin; - public final RL setLayer; - public final RL setScale; - public final RL recommendSafety; - public final RL subEvent; - public final RL receiveEvent; - private List> recommendedSettingChanges = new ArrayList<>(); private EnumSet serverCaps = EnumSet.noneOf(ServerCaps.class); private boolean scalingWarning; + protected Map> packetS2C = new HashMap<>(), packetC2S = new HashMap<>(); + protected Map, RL> packetLookup = new HashMap<>(); + private BiFunction keyFactory; + public NetHandler(BiFunction keyFactory) { - helloPacket = keyFactory.apply(MinecraftObjectHolder.NETWORK_ID, HELLO); - setSkin = keyFactory.apply(MinecraftObjectHolder.NETWORK_ID, SET_SKIN); - getSkin = keyFactory.apply(MinecraftObjectHolder.NETWORK_ID, GET_SKIN); - setLayer = keyFactory.apply(MinecraftObjectHolder.NETWORK_ID, SKIN_LAYERS); - setScale = keyFactory.apply(MinecraftObjectHolder.NETWORK_ID, SET_SCALE); - recommendSafety = keyFactory.apply(MinecraftObjectHolder.NETWORK_ID, RECOMMEND_SAFETY); - subEvent = keyFactory.apply(MinecraftObjectHolder.NETWORK_ID, SUBSCRIBE_EVENT); - receiveEvent = keyFactory.apply(MinecraftObjectHolder.NETWORK_ID, RECEIVE_EVENT); + this.keyFactory = keyFactory; + + register(packetC2S, HELLO, HelloC2S.class, HelloC2S::new); + register(packetS2C, HELLO, HelloS2C.class, HelloS2C::new); + + register(packetC2S, SET_SKIN, SetSkinC2S.class, SetSkinC2S::new); + register(packetS2C, SET_SKIN, SetSkinS2C.class, SetSkinS2C::new); + + register(packetS2C, GET_SKIN, GetSkinS2C.class, GetSkinS2C::new); + + register(packetC2S, SET_SCALE, SetScaleC2S.class, SetScaleC2S::new); + register(packetS2C, SET_SCALE, ScaleInfoS2C.class, ScaleInfoS2C::new); + + register(packetS2C, RECOMMEND_SAFETY, RecommendSafetyS2C.class, RecommendSafetyS2C::new); + + register(packetC2S, SUBSCRIBE_EVENT, SubEventC2S.class, SubEventC2S::new); + + register(packetS2C, RECEIVE_EVENT, ReceiveEventS2C.class, ReceiveEventS2C::new); + + register(packetC2S, GESTURE, GestureC2S.class, GestureC2S::new); } + @SuppressWarnings("unchecked") + protected void register(Map> map, String name, Class clazz, Supplier factory) { + RL key = keyFactory.apply(MinecraftObjectHolder.NETWORK_ID, name); + map.put(key, (Supplier) factory); + packetLookup.put(clazz, key); + } + + @SuppressWarnings("unchecked") public void onJoin(P player) { - try { - IOHelper pb = new IOHelper(); - NBTTagCompound data = new NBTTagCompound(); - int kickTimer = ModConfig.getWorldConfig().getInt(ConfigKeys.KICK_PLAYERS_WITHOUT_MOD, 0); - data.setInteger(KICK_TIME, kickTimer); - data.setTag(SERVER_CAPS, writeCaps()); - - PlayerData pd = newData(); - getSNetH(player).cpm$setEncodedModelData(pd); - pd.load(getID(player)); - - NBTTagCompound scaling = new NBTTagCompound(); - data.setTag(SCALING, scaling); - for(ScalingOptions o : scaleSetters.keySet()) { - float v = pd.scale.getOrDefault(o, 1F); - if(v != 1) { - scaling.setFloat(o.getNetKey(), v); - } + NBTTagCompound data = new NBTTagCompound(); + int kickTimer = ModConfig.getWorldConfig().getInt(ConfigKeys.KICK_PLAYERS_WITHOUT_MOD, 0); + data.setInteger(NetworkUtil.KICK_TIME, kickTimer); + data.setTag(NetworkUtil.SERVER_CAPS, writeCaps()); + + ServerNetH net = getSNetH(player); + PlayerData pd = newData(); + net.cpm$setEncodedModelData(pd); + pd.load(getID(player)); + + NBTTagCompound scaling = new NBTTagCompound(); + data.setTag(NetworkUtil.SCALING, scaling); + for(ScalingOptions o : scaleSetters.keySet()) { + float v = pd.scale.getOrDefault(o, 1F); + if(v != 1) { + scaling.setFloat(o.getNetKey(), v); } - - pb.writeNBT(data); - sendPacketTo(getNet.apply(player), helloPacket, pb.toBytes()); - } catch (IOException e) { - throw new RuntimeException(e); } + + sendPacketTo0((NET) net, new HelloS2C(data)); } private NBTTag writeCaps() { NBTTagCompound data = new NBTTagCompound(); scaleSetters.keySet().stream().map(ScalingOptions::getCaps).filter(e -> e != null).distinct().forEach(c -> setCap(data, c)); setCap(data, ServerCaps.MODEL_EVENT_SUBS); + setCap(data, ServerCaps.GESTURES); return data; } @@ -166,255 +164,29 @@ protected PlayerData newData() { return new PlayerData(); } - @SuppressWarnings("unchecked") public void receiveServer(RL key, InputStream data, ServerNetH net) { - try { - NET from = (NET) net; - P pl = getPlayer.apply(from); - if(key.equals(helloPacket)) { - executor.apply(from).execute(() -> { - net.cpm$setHasMod(true); - findTracking.accept(pl, p -> sendPlayerData(p, pl)); - PlayerData pd = net.cpm$getEncodedModelData(); - if(pd.canChangeModel()) { - sendPacketTo(from, getSkin, new byte[] {0}); - } else { - sendPacketTo(from, setSkin, writeSkinData(pd, pl)); - } - if(ModConfig.getWorldConfig().getBoolean(ConfigKeys.RECOMMEND_SAFETY_SETTINGS, false)) { - sendSafetySettings(from); - } - }); - } else if(key.equals(setSkin)) { - PlayerData pd = net.cpm$getEncodedModelData(); - if(pd.canChangeModel()) { - IOHelper pb = new IOHelper(data); - NBTTagCompound tag = pb.readNBT(); - executor.apply(from).execute(() -> { - pd.setModel(tag.hasKey(DATA_TAG) ? tag.getByteArray(DATA_TAG) : null, false, false); - sendPacketToTracking(pl, setSkin, writeSkinData(pd, pl)); - pd.save(getID(pl)); - }); - } else { - sendChat.accept(pl, FORCED_CHAT_MSG); - } - } else if(key.equals(setScale)) { - IOHelper pb = new IOHelper(data); - NBTTagCompound tag = pb.readNBT(); - executor.apply(from).execute(() -> { - PlayerData pd = net.cpm$getEncodedModelData(); - List blocked = new ArrayList<>(); - for(Entry> e : scaleSetters.entrySet()) { - float oldV = pd.scale.getOrDefault(e.getKey(), 1F); - float selNewV = tag.getFloat(e.getKey().getNetKey()); - float newV = selNewV; - Pair l = getScalingLimits(e.getKey(), getID(pl)); - newV = newV == 0 || l == null ? 1F : MathHelper.clamp(newV, l.getKey(), l.getValue()); - Log.debug("Scaling " + e.getKey() + " " + oldV + " -> " + newV); - if(newV != oldV) { - e.getValue().accept(pl, newV); - pd.scale.put(e.getKey(), newV); - } - if(newV != selNewV && selNewV != 0) { - blocked.add(e.getKey()); - } - } - pd.save(getID(pl)); - NBTTagCompound ret = new NBTTagCompound(); - if(!blocked.isEmpty()) { - NBTTagList list = new NBTTagList(); - blocked.forEach(sc -> list.appendTag(new NBTTagString(sc.getNetKey()))); - ret.setTag(SCALING, list); - } - try { - IOHelper pb2 = new IOHelper(); - pb2.writeNBT(ret); - sendPacketTo(from, setScale, pb2.toBytes()); - } catch (IOException e) { - e.printStackTrace(); - } - }); - } else if(key.equals(subEvent)) { - IOHelper pb = new IOHelper(data); - NBTTagCompound tag = pb.readNBT(); - PlayerData pd = net.cpm$getEncodedModelData(); - pd.eventSubs.clear(); - NBTTagList list = tag.getTagList(EVENT_LIST, NBTTag.TAG_STRING); - for (int i = 0;i map = new HashMap<>(); - ConfigEntry main = ModConfig.getWorldConfig().getEntry(ConfigKeys.SAFETY_SETTINGS); - ConfigEntry ce = new ConfigEntry(map, () -> {}); - for(PlayerSpecificConfigKey key : ConfigKeys.SAFETY_KEYS) { - Object v = key.getValue(main, KeyGroup.GLOBAL); - sendSafetySettings$setValue(ce, key, v); - } - tag.setString(PROFILE_DATA, MinecraftObjectHolder.gson.toJson(map)); - } - try { - IOHelper pb = new IOHelper(); - pb.writeNBT(tag); - sendPacketTo(to, recommendSafety, pb.toBytes()); - } catch (IOException e) { - e.printStackTrace(); - } - } + processPacket(packetC2S, key, data, net); } - @SuppressWarnings("unchecked") - private static void sendSafetySettings$setValue(ConfigEntry ce, PlayerSpecificConfigKey key, Object value) { - key.setValue(ce, (T) value); + public void receiveClient(RL key, InputStream data, NetH net) { + processPacket(packetS2C, key, data, net); } - @SuppressWarnings("unchecked") - public void receiveClient(RL key, InputStream data, NetH net) { + private void processPacket(Map> map, RL key, InputStream data, NetH net) { try { - NET from = (NET) net; - if(key.equals(helloPacket)) { - IOHelper pb = new IOHelper(data); - NBTTagCompound tag = pb.readNBT(); - NBTTagCompound scaling = tag.getCompoundTag(SCALING); - Map scalingMap = new EnumMap<>(ScalingOptions.class); - for(ScalingOptions o : ScalingOptions.VALUES) { - float v = scaling.getFloat(o.getNetKey()); - scalingMap.put(o, v); - } - executor.apply(from).execute(() -> { - handleServerCaps(tag.getCompoundTag(SERVER_CAPS)); - String server = MinecraftClientAccess.get().getConnectedServer(); - ConfigEntry cc = ModConfig.getCommonConfig(); - ConfigEntry ss = cc.getEntry(ConfigKeys.SERVER_SETTINGS); - if(server != null && ss.hasEntry(server)) { - if(ss.getEntry(server).getBoolean(ConfigKeys.DISABLE_NETWORK, false)) { - int kickTime = tag.getInteger(KICK_TIME); - if(kickTime > 0) { - recommendedSettingChanges.clear(); - recommendedSettingChanges.add(new ConfigChangeRequest<>(ConfigKeys.DISABLE_NETWORK, true, false)); - displayText.accept(new FormatText("chat.cpm.serverRequiresCPM", new KeybindText("key.cpm.gestureMenu", "gestureMenu"))); - } - return; - } - } - net.cpm$setHasMod(true); - MinecraftClientAccess.get().getDefinitionLoader().clearServerData(); - sendPacketTo(from, helloPacket, new byte[] {0}); - MinecraftClientAccess.get().getPlayerRenderManager().getAnimationEngine().setServerScaling(scalingMap); - }); - } else if(net.cpm$hasMod()) { - if(key.equals(setSkin)) { - IOHelper pb = new IOHelper(data); - int plid = pb.readVarInt(); - NBTTagCompound tag = pb.readNBT(); - executor.apply(from).execute(() -> { - P player = getPlayerById.apply(plid); - if(player != null) { - MinecraftClientAccess.get().getDefinitionLoader().setModel(playerToLoader.apply(player), tag.hasKey(DATA_TAG) ? tag.getByteArray(DATA_TAG) : null, tag.getBoolean(FORCED_TAG)); - } - }); - } else if(key.equals(getSkin)) { - sendSkinData(from); - } else if(key.equals(recommendSafety)) { - IOHelper pb = new IOHelper(data); - NBTTagCompound tag = pb.readNBT(); - executor.apply(from).execute(() -> { - String server = MinecraftClientAccess.get().getConnectedServer(); - ConfigEntry cc = ModConfig.getCommonConfig(); - ConfigEntry ss = cc.getEntry(ConfigKeys.SERVER_SETTINGS); - if(server != null && ss.hasEntry(server)) { - if(ss.getEntry(server).getBoolean(ConfigKeys.IGNORE_SAFETY_RECOMMENDATIONS, false))return; - } - - BuiltInSafetyProfiles netProfile = BuiltInSafetyProfiles.get(tag.getString(PROFILE_TAG)); - - ConfigEntry ce = null; - if(netProfile == BuiltInSafetyProfiles.CUSTOM) { - try { - Map map = (Map) MinecraftObjectHolder.gson.fromJson(tag.getString(PROFILE_DATA), Object.class); - ce = new ConfigEntry(map, () -> {}); - } catch (Exception e) { - return; - } - } - - recommendedSettingChanges.clear(); - for(PlayerSpecificConfigKey k : ConfigKeys.SAFETY_KEYS) { - Object rv = ce != null ? k.getValue(ce, KeyGroup.GLOBAL) : k.getValue(netProfile); - Object sv = k.getValueFor(server, null, cc); - if(!rv.equals(sv)) { - recommendedSettingChanges.add(new ConfigChangeRequest<>(k, sv, rv)); - } - } - if(!recommendedSettingChanges.isEmpty()) { - ConfigEntry gs = cc.getEntry(ConfigKeys.GLOBAL_SETTINGS); - String[] spf = gs.getString(ConfigKeys.SAFETY_PROFILE, BuiltInSafetyProfiles.MEDIUM.name().toLowerCase()).split(":", 2); - BuiltInSafetyProfiles profile = SocialConfig.getProfile(spf); - - if(server != null && ss.hasEntry(server)) { - ConfigEntry e = ss.getEntry(server); - if(e.hasEntry(ConfigKeys.SAFETY_PROFILE)) { - spf = e.getString(ConfigKeys.SAFETY_PROFILE, BuiltInSafetyProfiles.MEDIUM.name().toLowerCase()).split(":", 2); - profile = SocialConfig.getProfile(spf); - } - } - - String old; - if(profile == BuiltInSafetyProfiles.CUSTOM) { - old = "custom:" + spf[1]; - } else { - old = profile.name().toLowerCase(); - } - - if(netProfile == BuiltInSafetyProfiles.CUSTOM) { - recommendedSettingChanges.add(new ConfigChangeRequest<>(ConfigKeys.SAFETY_PROFILE, old, "custom:import-" + server)); - } else { - recommendedSettingChanges.add(new ConfigChangeRequest<>(ConfigKeys.SAFETY_PROFILE, old, netProfile.name().toLowerCase())); - } - - displayText.accept(new FormatText("chat.cpm.serverSafetySettings", new KeybindText("key.cpm.gestureMenu", "gestureMenu"))); - } - }); - } else if(key.equals(receiveEvent)) { - IOHelper pb = new IOHelper(data); - int plid = pb.readVarInt(); - NBTTagCompound tag = pb.readNBT(); - executor.apply(from).execute(() -> { - P player = getPlayerById.apply(plid); - if(player != null) { - Player pl = MinecraftClientAccess.get().getDefinitionLoader().loadPlayer(playerToLoader.apply(player), ModelDefinitionLoader.PLAYER_UNIQUE); - pl.animState.receiveEvent(tag, pl.isClientPlayer()); - } - }); - } else if(key.equals(setScale)) { - IOHelper pb = new IOHelper(data); - NBTTagCompound tag = pb.readNBT(); - executor.apply(from).execute(() -> { - if(tag.hasKey(SCALING) && !scalingWarning) { - displayText.accept(new FormatText("chat.cpm.scalingBlocked")); - scalingWarning = true; - } - }); - } + Supplier factory = map.get(key); + if(factory != null) { + IPacket pckt = factory.get(); + IOHelper h = new IOHelper(data); + pckt.read(h); + pckt.handleRaw(this, net); } } catch (Throwable e) { Log.error("Exception while processing cpm packet: " + key, e); } } - private void handleServerCaps(NBTTagCompound tag) { + public void handleServerCaps(NBTTagCompound tag) { serverCaps.clear(); for(ServerCaps c : ServerCaps.VALUES) { if(tag.getBoolean(c.name().toLowerCase())) { @@ -425,89 +197,37 @@ private void handleServerCaps(NBTTagCompound tag) { public void sendSkinData() { if(hasModClient()) - sendSkinData(getClientNet()); - } - - private void sendSkinData(NET pl) { - String model = ModConfig.getCommonConfig().getString(ConfigKeys.SELECTED_MODEL, null); - if(model != null) { - File modelsDir = new File(MinecraftClientAccess.get().getGameDir(), "player_models"); - try { - ModelFile file = ModelFile.load(new File(modelsDir, model)); - IOHelper pb = new IOHelper(); - NBTTagCompound data = new NBTTagCompound(); - data.setByteArray(DATA_TAG, file.getDataBlock()); - pb.writeNBT(data); - file.registerLocalCache(MinecraftClientAccess.get().getDefinitionLoader()); - sendPacketTo(pl, setSkin, pb.toBytes()); - } catch (IOException e) { - } - } else { - try { - IOHelper pb = new IOHelper(); - NBTTagCompound data = new NBTTagCompound(); - pb.writeNBT(data); - sendPacketTo(pl, setSkin, pb.toBytes()); - } catch (IOException e) { - } - } - } - - public void sendPlayerData(P target, P to) { - PlayerData dt = getSNetH(target).cpm$getEncodedModelData(); - if(dt == null)return; - sendPacketTo(getNet.apply(to), setSkin, writeSkinData(dt, target)); - } - - private byte[] writeSkinData(PlayerData dt, P target) { - try { - IOHelper pb = new IOHelper(); - pb.writeVarInt(getPlayerId.applyAsInt(target)); - NBTTagCompound data = new NBTTagCompound(); - if(dt.data != null) { - data.setBoolean(FORCED_TAG, dt.forced); - data.setByteArray(DATA_TAG, dt.data); - } - pb.writeNBT(data); - return pb.toBytes(); - } catch (IOException e) { - throw new RuntimeException(e); - } + NetworkUtil.sendSkinDataToServer(this); } public void setSkin(P pl, String skin, boolean force, boolean save) { - PlayerData pd = getSNetH(pl).cpm$getEncodedModelData(); + ServerNetH h = getSNetH(pl); + PlayerData pd = h.cpm$getEncodedModelData(); pd.setModel(skin, force, save); if(skin == null) { - sendPacketTo(getNet.apply(pl), getSkin, new byte[] {0}); + sendPacketTo(h, new GetSkinS2C()); } - sendPacketToTracking(pl, setSkin, writeSkinData(pd, pl)); + sendPacketToTracking(pl, NetworkUtil.writeSkinData(this, pd, pl)); pd.save(getID(pl)); } public void setSkin(P pl, byte[] skin, boolean force) { PlayerData pd = getSNetH(pl).cpm$getEncodedModelData(); pd.setModel(skin, force, false); - sendPacketToTracking(pl, setSkin, writeSkinData(pd, pl)); + sendPacketToTracking(pl, NetworkUtil.writeSkinData(this, pd, pl)); pd.save(getID(pl)); } public void setScale(ScaleData scl) { if(hasModClient() && serverCaps.contains(ServerCaps.SCALING)) { - try { - if(scl == null)scl = ScaleData.NULL; - NBTTagCompound nbt = new NBTTagCompound(); - for(Entry e : scl.getScaling().entrySet()) { - if(serverCaps.contains(e.getKey().getCaps())) { - nbt.setFloat(e.getKey().getNetKey(), e.getValue()); - } + if(scl == null)scl = ScaleData.NULL; + NBTTagCompound nbt = new NBTTagCompound(); + for(Entry e : scl.getScaling().entrySet()) { + if(serverCaps.contains(e.getKey().getCaps())) { + nbt.setFloat(e.getKey().getNetKey(), e.getValue()); } - IOHelper pb = new IOHelper(); - pb.writeNBT(nbt); - sendPacketToServer(setScale, pb.toBytes()); - } catch (IOException e) { - throw new RuntimeException(e); } + sendPacketToServer(new SetScaleC2S(nbt)); } } @@ -537,13 +257,7 @@ public void tick() { if(dt.eventSubs.contains(ModelEventType.FALLING))evt.setFloat(ModelEventType.FALLING.getName(), getFallDistance.apply(p)); if(dt.eventSubs.contains(ModelEventType.CREATIVE_FLYING))evt.setBoolean(ModelEventType.CREATIVE_FLYING.getName(), getIsCreativeFlying.test(p)); if(evt.tagCount() > 0) { - IOHelper h = new IOHelper(); - try { - h.writeVarInt(getPlayerId.applyAsInt(p)); - h.writeNBT(evt); - sendPacketToTracking(p, receiveEvent, h.toBytes()); - } catch (IOException e) { - } + sendPacketToTracking(p, new ReceiveEventS2C(getPlayerId.applyAsInt(p), evt)); } } } @@ -564,65 +278,49 @@ public void sendEventSubs(ModelDefinition def) { if(serverCaps.contains(ServerCaps.MODEL_EVENT_SUBS)) { NBTTagCompound tag = new NBTTagCompound(); NBTTagList list = new NBTTagList(); - tag.setTag(EVENT_LIST, list); + tag.setTag(NetworkUtil.EVENT_LIST, list); def.getAnimations().getAnimations().keySet().stream().filter(e -> e instanceof VanillaPose). map(ModelEventType::getType).filter(e -> e != null).distinct().map(ModelEventType::getName). map(NBTTagString::new).forEach(list::appendTag); - IOHelper h = new IOHelper(); - try { - h.writeNBT(tag); - sendPacketToServer(subEvent, h.toBytes()); - } catch (IOException e) { - } + sendPacketToServer(new SubEventC2S(tag)); } } + public boolean hasServerCap(ServerCaps cap) { + return hasModClient() && serverCaps.contains(cap); + } + public void onJump(P p) { ServerNetH net = getSNetH(p); PlayerData dt = net.cpm$getEncodedModelData(); if(dt != null && dt.eventSubs.contains(ModelEventType.JUMPING)) { NBTTagCompound evt = new NBTTagCompound(); evt.setBoolean(ModelEventType.JUMPING.getName(), true); - IOHelper h = new IOHelper(); - try { - h.writeVarInt(getPlayerId.applyAsInt(p)); - h.writeNBT(evt); - sendPacketToTracking(p, receiveEvent, h.toBytes()); - } catch (IOException e) { - } + sendPacketToTracking(p, new ReceiveEventS2C(getPlayerId.applyAsInt(p), evt)); } } - protected void sendPacketTo(NET net, RL rl, byte[] dt) { - if(dt.length == 0)new Throwable("Empty packet sending: " + rl).printStackTrace(); - sendPacket.accept(net, rl, dt); - } - - protected void sendPacketToServer(RL rl, byte[] dt) { - sendPacketTo(getClientNet(), rl, dt); - } - - protected void sendPacketToTracking(P p, RL rl, byte[] dt) { - if(dt.length == 0)new Throwable("Empty packet sending: " + rl).printStackTrace(); - sendToAllTracking.accept(p, rl, dt); - } - public String getID(P pl) { return getPlayerUUID.apply(pl).toString(); } - public P getClient() { - return getClient.get(); - } - public NET getClientNet() { - return getNet.apply(getClient()); + return getNet.apply(getClient.get()); } - private ServerNetH getSNetH(P player) { + public ServerNetH getSNetH(P player) { return (ServerNetH) getNet.apply(player); } + public void sendPlayerData(P target, P to) { + NetworkUtil.sendPlayerData(this, target, to); + } + + @SuppressWarnings("unchecked") + public void execute(NetH net, Runnable task) { + executor.apply((NET) net).execute(task); + } + public List> getRecommendedSettingChanges() { return recommendedSettingChanges; } @@ -724,17 +422,15 @@ public void setGetPlayerAnimGetters(ToFloatFunction

getFallDistance, Predicat } public void registerOut(ThrowingConsumer reg) throws E { - reg.accept(helloPacket); - reg.accept(setSkin); - reg.accept(getSkin); - reg.accept(recommendSafety); - reg.accept(receiveEvent); + for (RL e : packetS2C.keySet()) { + reg.accept(e); + } } public void registerIn(ThrowingConsumer reg) throws E { - reg.accept(helloPacket); - reg.accept(setSkin); - reg.accept(subEvent); + for (RL e : packetC2S.keySet()) { + reg.accept(e); + } } public void setScaler(ScalerInterface intf) { @@ -781,4 +477,86 @@ private T getValue(ConfigEntry pl, ConfigEntry g, String id, String opt, Str g = g.getEntry(opt); return getter.apply(g, key, def); } + + @SuppressWarnings("unchecked") + public P getPlayer(ServerNetH net) { + return getPlayer.apply((NET) net); + } + + public void forEachTracking(P pl, Consumer

cons) { + findTracking.accept(pl, cons); + } + + @SuppressWarnings("unchecked") + public void sendPacketTo(ServerNetH net, IPacket packet) { + if(!net.cpm$hasMod())return; + sendPacketTo0((NET) net, packet); + } + + public void sendPacketToServer(IPacket packet) { + if(!hasModClient())return; + sendPacketTo0(getClientNet(), packet); + } + + private void sendPacketTo0(NET net, IPacket packet) { + RL id = packetLookup.get(packet.getClass()); + if(id == null)return; + byte[] data; + try { + data = packet2byte(packet); + } catch (IOException e) { + return; + } + sendPacket.accept(net, id, data); + } + + public void sendPacketToTracking(P player, IPacket packet) { + RL id = packetLookup.get(packet.getClass()); + if(id == null)return; + byte[] data; + try { + data = packet2byte(packet); + } catch (IOException e) { + return; + } + sendToAllTracking.accept(player, id, data); + } + + private byte[] packet2byte(IPacket pckt) throws IOException { + IOHelper h = new IOHelper(); + pckt.write(h); + return h.toBytes(); + } + + public int getPlayerId(P target) { + return getPlayerId.applyAsInt(target); + } + + public void sendChat(P player, IText chatMsg) { + sendChat.accept(player, chatMsg); + } + + public Map> getScaleSetters() { + return scaleSetters; + } + + public void displayText(IText text) { + displayText.accept(text); + } + + public P getPlayerById(int entityId) { + return getPlayerById.apply(entityId); + } + + public Object getLoaderId(P player) { + return playerToLoader.apply(player); + } + + public void setScalingWarning() { + this.scalingWarning = true; + } + + public boolean hasScalingWarning() { + return scalingWarning; + } } diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/NetworkUtil.java b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/NetworkUtil.java new file mode 100644 index 00000000..d865cc55 --- /dev/null +++ b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/NetworkUtil.java @@ -0,0 +1,128 @@ +package com.tom.cpm.shared.network; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import com.tom.cpl.config.ConfigEntry; +import com.tom.cpl.function.TriFunction; +import com.tom.cpl.nbt.NBTTagCompound; +import com.tom.cpl.text.FormatText; +import com.tom.cpl.util.Pair; +import com.tom.cpm.shared.MinecraftClientAccess; +import com.tom.cpm.shared.MinecraftObjectHolder; +import com.tom.cpm.shared.config.BuiltInSafetyProfiles; +import com.tom.cpm.shared.config.ConfigKeys; +import com.tom.cpm.shared.config.ModConfig; +import com.tom.cpm.shared.config.PlayerData; +import com.tom.cpm.shared.config.PlayerSpecificConfigKey; +import com.tom.cpm.shared.config.PlayerSpecificConfigKey.KeyGroup; +import com.tom.cpm.shared.io.ModelFile; +import com.tom.cpm.shared.network.NetH.ServerNetH; +import com.tom.cpm.shared.network.packet.ReceiveEventS2C; +import com.tom.cpm.shared.network.packet.RecommendSafetyS2C; +import com.tom.cpm.shared.network.packet.SetSkinC2S; +import com.tom.cpm.shared.network.packet.SetSkinS2C; +import com.tom.cpm.shared.util.ScalingOptions; + +public class NetworkUtil { + public static final String FORCED_TAG = "forced"; + public static final String DATA_TAG = "data"; + public static final String PROFILE_TAG = "profile"; + public static final String PROFILE_DATA = "data"; + public static final String SERVER_CAPS = "caps"; + public static final String EVENT_LIST = "eventList"; + public static final String KICK_TIME = "kickTime"; + public static final String SCALING = "scaling"; + public static final String GESTURE = "gesture"; + + public static final FormatText FORCED_CHAT_MSG = new FormatText("chat.cpm.skinForced"); + + public static

void sendPlayerData(NetHandler handler, P target, P to) { + PlayerData dt = handler.getSNetH(target).cpm$getEncodedModelData(); + if(dt == null)return; + handler.sendPacketTo(handler.getSNetH(to), writeSkinData(handler, dt, target)); + if(dt.gestureData.length > 0) { + NBTTagCompound evt = new NBTTagCompound(); + evt.setByteArray(NetworkUtil.GESTURE, dt.gestureData); + handler.sendPacketTo(handler.getSNetH(to), new ReceiveEventS2C(handler.getPlayerId(target), evt)); + } + } + + public static

IPacket writeSkinData(NetHandler handler, PlayerData dt, P target) { + NBTTagCompound data = new NBTTagCompound(); + if(dt.data != null) { + data.setBoolean(FORCED_TAG, dt.forced); + data.setByteArray(DATA_TAG, dt.data); + } + return new SetSkinS2C(handler.getPlayerId(target), data); + } + + public static void sendSafetySettings(NetHandler handler, ServerNetH net) { + BuiltInSafetyProfiles profile = BuiltInSafetyProfiles.get(ModConfig.getWorldConfig().getString(ConfigKeys.SAFETY_PROFILE, BuiltInSafetyProfiles.MEDIUM.name().toLowerCase())); + if(profile != null) { + NBTTagCompound tag = new NBTTagCompound(); + tag.setString(PROFILE_TAG, profile.name().toLowerCase()); + if(profile == BuiltInSafetyProfiles.CUSTOM) { + Map map = new HashMap<>(); + ConfigEntry main = ModConfig.getWorldConfig().getEntry(ConfigKeys.SAFETY_SETTINGS); + ConfigEntry ce = new ConfigEntry(map, () -> {}); + for(PlayerSpecificConfigKey key : ConfigKeys.SAFETY_KEYS) { + Object v = key.getValue(main, KeyGroup.GLOBAL); + sendSafetySettings$setValue(ce, key, v); + } + tag.setString(PROFILE_DATA, MinecraftObjectHolder.gson.toJson(map)); + } + handler.sendPacketTo(net, new RecommendSafetyS2C(tag)); + } + } + + @SuppressWarnings("unchecked") + private static void sendSafetySettings$setValue(ConfigEntry ce, PlayerSpecificConfigKey key, Object value) { + key.setValue(ce, (T) value); + } + + public static Pair getScalingLimits(ScalingOptions o, String id) { + ConfigEntry e = ModConfig.getWorldConfig(); + ConfigEntry pl = e.getEntry(ConfigKeys.PLAYER_SCALING_SETTINGS); + ConfigEntry g = e.getEntry(ConfigKeys.SCALING_SETTINGS); + if(!getValue(pl, g, id, o.name().toLowerCase(), ConfigKeys.ENABLED, ConfigEntry::getBoolean, o.getDefualtEnabled())) + return null; + float min = getValue(pl, g, id, o.name().toLowerCase(), ConfigKeys.MIN, ConfigEntry::getFloat, o.getMin()); + float max = getValue(pl, g, id, o.name().toLowerCase(), ConfigKeys.MAX, ConfigEntry::getFloat, o.getMax()); + return Pair.of(min, max); + } + + private static T getValue(ConfigEntry pl, ConfigEntry g, String id, String opt, String key, TriFunction getter, T def) { + if(pl.hasEntry(id)) { + pl = pl.getEntry(id); + if(pl.hasEntry(opt)) { + pl = pl.getEntry(opt); + if(pl.hasEntry(key)) + return getter.apply(pl, key, def); + } + } + g = g.getEntry(opt); + return getter.apply(g, key, def); + } + + public static void sendSkinDataToServer(NetHandler handler) { + String model = ModConfig.getCommonConfig().getString(ConfigKeys.SELECTED_MODEL, null); + if(model != null) { + File modelsDir = new File(MinecraftClientAccess.get().getGameDir(), "player_models"); + try { + ModelFile file = ModelFile.load(new File(modelsDir, model)); + NBTTagCompound data = new NBTTagCompound(); + data.setByteArray(DATA_TAG, file.getDataBlock()); + file.registerLocalCache(MinecraftClientAccess.get().getDefinitionLoader()); + handler.sendPacketToServer(new SetSkinC2S(data)); + } catch (IOException e) { + handler.sendPacketToServer(new SetSkinC2S(new NBTTagCompound())); + //warn + } + } else { + handler.sendPacketToServer(new SetSkinC2S(new NBTTagCompound())); + } + } +} diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/ServerCaps.java b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/ServerCaps.java index 910c0cf5..5911d6ef 100644 --- a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/ServerCaps.java +++ b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/ServerCaps.java @@ -7,6 +7,7 @@ public enum ServerCaps { MODEL_EVENT_SUBS, THIRD_PERSON, ATTRIBUTE_SCALE, + GESTURES, ; public static final ServerCaps[] VALUES = values(); } diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/packet/GestureC2S.java b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/packet/GestureC2S.java new file mode 100644 index 00000000..50a380f8 --- /dev/null +++ b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/packet/GestureC2S.java @@ -0,0 +1,42 @@ +package com.tom.cpm.shared.network.packet; + +import java.io.IOException; + +import com.tom.cpl.nbt.NBTTagCompound; +import com.tom.cpm.shared.config.PlayerData; +import com.tom.cpm.shared.io.IOHelper; +import com.tom.cpm.shared.network.IC2SPacket; +import com.tom.cpm.shared.network.NetH.ServerNetH; +import com.tom.cpm.shared.network.NetHandler; +import com.tom.cpm.shared.network.NetworkUtil; + +public class GestureC2S implements IC2SPacket { + private byte[] gestureData; + + public GestureC2S() { + } + + public GestureC2S(byte[] gestureData) { + this.gestureData = gestureData; + } + + @Override + public void read(IOHelper pb) throws IOException { + gestureData = pb.readByteArray(); + } + + @Override + public void write(IOHelper pb) throws IOException { + pb.writeByteArray(gestureData); + } + + @Override + public

void handle(NetHandler handler, ServerNetH net, P player) { + if(gestureData.length > 128)return; + PlayerData pd = net.cpm$getEncodedModelData(); + pd.gestureData = gestureData; + NBTTagCompound evt = new NBTTagCompound(); + evt.setByteArray(NetworkUtil.GESTURE, gestureData); + handler.sendPacketToTracking(player, new ReceiveEventS2C(handler.getPlayerId(player), evt)); + } +} diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/packet/GetSkinS2C.java b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/packet/GetSkinS2C.java new file mode 100644 index 00000000..ebbc1244 --- /dev/null +++ b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/packet/GetSkinS2C.java @@ -0,0 +1,27 @@ +package com.tom.cpm.shared.network.packet; + +import java.io.IOException; + +import com.tom.cpm.shared.io.IOHelper; +import com.tom.cpm.shared.network.IS2CPacket; +import com.tom.cpm.shared.network.NetH; +import com.tom.cpm.shared.network.NetHandler; +import com.tom.cpm.shared.network.NetworkUtil; + +public class GetSkinS2C implements IS2CPacket { + + @Override + public void read(IOHelper pb) throws IOException { + pb.readByte(); + } + + @Override + public void write(IOHelper pb) throws IOException { + pb.writeByte(0); + } + + @Override + public void handle(NetHandler handler, NetH from) { + NetworkUtil.sendSkinDataToServer(handler); + } +} diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/packet/HelloC2S.java b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/packet/HelloC2S.java new file mode 100644 index 00000000..1cd4722f --- /dev/null +++ b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/packet/HelloC2S.java @@ -0,0 +1,48 @@ +package com.tom.cpm.shared.network.packet; + +import java.io.IOException; + +import com.tom.cpm.shared.config.ConfigKeys; +import com.tom.cpm.shared.config.ModConfig; +import com.tom.cpm.shared.config.PlayerData; +import com.tom.cpm.shared.io.IOHelper; +import com.tom.cpm.shared.network.IC2SPacket; +import com.tom.cpm.shared.network.NetH.ServerNetH; +import com.tom.cpm.shared.network.NetHandler; +import com.tom.cpm.shared.network.NetworkUtil; + +public class HelloC2S implements IC2SPacket { + private byte status; + + public HelloC2S() { + } + + public HelloC2S(int status) { + this.status = (byte) status; + } + + @Override + public void read(IOHelper pb) throws IOException { + status = pb.readByte(); + } + + @Override + public void write(IOHelper pb) throws IOException { + pb.writeByte(status); + } + + @Override + public

void handle(NetHandler handler, ServerNetH net, P pl) { + net.cpm$setHasMod(true); + handler.forEachTracking(pl, p -> NetworkUtil.sendPlayerData(handler, p, pl)); + PlayerData pd = net.cpm$getEncodedModelData(); + if(pd.canChangeModel()) { + handler.sendPacketTo(net, new GetSkinS2C()); + } else { + handler.sendPacketTo(net, NetworkUtil.writeSkinData(handler, pd, pl)); + } + if(ModConfig.getWorldConfig().getBoolean(ConfigKeys.RECOMMEND_SAFETY_SETTINGS, false)) { + NetworkUtil.sendSafetySettings(handler, net); + } + } +} diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/packet/HelloS2C.java b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/packet/HelloS2C.java new file mode 100644 index 00000000..77d2dbfa --- /dev/null +++ b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/packet/HelloS2C.java @@ -0,0 +1,56 @@ +package com.tom.cpm.shared.network.packet; + +import java.util.EnumMap; +import java.util.Map; + +import com.tom.cpl.config.ConfigEntry; +import com.tom.cpl.nbt.NBTTagCompound; +import com.tom.cpl.text.FormatText; +import com.tom.cpl.text.KeybindText; +import com.tom.cpm.shared.MinecraftClientAccess; +import com.tom.cpm.shared.config.ConfigChangeRequest; +import com.tom.cpm.shared.config.ConfigKeys; +import com.tom.cpm.shared.config.ModConfig; +import com.tom.cpm.shared.network.NetH; +import com.tom.cpm.shared.network.NetHandler; +import com.tom.cpm.shared.network.NetworkUtil; +import com.tom.cpm.shared.util.ScalingOptions; + +public class HelloS2C extends NBTS2C { + + public HelloS2C(NBTTagCompound data) { + super(data); + } + + public HelloS2C() { + } + + @Override + public void handle(NetHandler handler, NetH net) { + NBTTagCompound scaling = tag.getCompoundTag(NetworkUtil.SCALING); + Map scalingMap = new EnumMap<>(ScalingOptions.class); + for(ScalingOptions o : ScalingOptions.VALUES) { + float v = scaling.getFloat(o.getNetKey()); + scalingMap.put(o, v); + } + handler.handleServerCaps(tag.getCompoundTag(NetworkUtil.SERVER_CAPS)); + String server = MinecraftClientAccess.get().getConnectedServer(); + ConfigEntry cc = ModConfig.getCommonConfig(); + ConfigEntry ss = cc.getEntry(ConfigKeys.SERVER_SETTINGS); + if(server != null && ss.hasEntry(server)) { + if(ss.getEntry(server).getBoolean(ConfigKeys.DISABLE_NETWORK, false)) { + int kickTime = tag.getInteger(NetworkUtil.KICK_TIME); + if(kickTime > 0) { + handler.getRecommendedSettingChanges().clear(); + handler.getRecommendedSettingChanges().add(new ConfigChangeRequest<>(ConfigKeys.DISABLE_NETWORK, true, false)); + handler.displayText(new FormatText("chat.cpm.serverRequiresCPM", new KeybindText("key.cpm.gestureMenu", "gestureMenu"))); + } + return; + } + } + net.cpm$setHasMod(true); + MinecraftClientAccess.get().getDefinitionLoader().clearServerData(); + handler.sendPacketToServer(new HelloC2S(0)); + MinecraftClientAccess.get().getPlayerRenderManager().getAnimationEngine().setServerScaling(scalingMap); + } +} diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/packet/NBTC2S.java b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/packet/NBTC2S.java new file mode 100644 index 00000000..5f45bde9 --- /dev/null +++ b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/packet/NBTC2S.java @@ -0,0 +1,28 @@ +package com.tom.cpm.shared.network.packet; + +import java.io.IOException; + +import com.tom.cpl.nbt.NBTTagCompound; +import com.tom.cpm.shared.io.IOHelper; +import com.tom.cpm.shared.network.IC2SPacket; + +public abstract class NBTC2S implements IC2SPacket { + protected NBTTagCompound tag; + + public NBTC2S(NBTTagCompound data) { + this.tag = data; + } + + public NBTC2S() { + } + + @Override + public void read(IOHelper pb) throws IOException { + tag = pb.readNBT(); + } + + @Override + public void write(IOHelper pb) throws IOException { + pb.writeNBT(tag); + } +} diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/packet/NBTEntityS2C.java b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/packet/NBTEntityS2C.java new file mode 100644 index 00000000..2aa929cb --- /dev/null +++ b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/packet/NBTEntityS2C.java @@ -0,0 +1,46 @@ +package com.tom.cpm.shared.network.packet; + +import java.io.IOException; + +import com.tom.cpl.nbt.NBTTagCompound; +import com.tom.cpm.shared.io.IOHelper; +import com.tom.cpm.shared.network.IS2CPacket; +import com.tom.cpm.shared.network.NetH; +import com.tom.cpm.shared.network.NetHandler; + +public abstract class NBTEntityS2C implements IS2CPacket { + private int entityId; + protected NBTTagCompound tag; + + public NBTEntityS2C() { + } + + public NBTEntityS2C(int entityId, NBTTagCompound data) { + this.entityId = entityId; + this.tag = data; + } + + @Override + public void read(IOHelper pb) throws IOException { + entityId = pb.readVarInt(); + tag = pb.readNBT(); + } + + @Override + public void write(IOHelper pb) throws IOException { + pb.writeVarInt(entityId); + pb.writeNBT(tag); + } + + @Override + public void handle(NetHandler handler, NetH from) { + handle0(handler, from); + } + + private

void handle0(NetHandler handler, NetH from) { + P player = handler.getPlayerById(entityId); + if(player != null)handle(handler, from, player); + } + + protected abstract

void handle(NetHandler handler, NetH from, P player); +} diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/packet/NBTS2C.java b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/packet/NBTS2C.java new file mode 100644 index 00000000..30c96c61 --- /dev/null +++ b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/packet/NBTS2C.java @@ -0,0 +1,28 @@ +package com.tom.cpm.shared.network.packet; + +import java.io.IOException; + +import com.tom.cpl.nbt.NBTTagCompound; +import com.tom.cpm.shared.io.IOHelper; +import com.tom.cpm.shared.network.IS2CPacket; + +public abstract class NBTS2C implements IS2CPacket { + protected NBTTagCompound tag; + + public NBTS2C(NBTTagCompound data) { + this.tag = data; + } + + public NBTS2C() { + } + + @Override + public void read(IOHelper pb) throws IOException { + tag = pb.readNBT(); + } + + @Override + public void write(IOHelper pb) throws IOException { + pb.writeNBT(tag); + } +} diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/packet/ReceiveEventS2C.java b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/packet/ReceiveEventS2C.java new file mode 100644 index 00000000..367f1c0f --- /dev/null +++ b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/packet/ReceiveEventS2C.java @@ -0,0 +1,26 @@ +package com.tom.cpm.shared.network.packet; + +import com.tom.cpl.nbt.NBTTagCompound; +import com.tom.cpm.shared.MinecraftClientAccess; +import com.tom.cpm.shared.config.Player; +import com.tom.cpm.shared.definition.ModelDefinitionLoader; +import com.tom.cpm.shared.network.NetH; +import com.tom.cpm.shared.network.NetHandler; + +public class ReceiveEventS2C extends NBTEntityS2C { + + public ReceiveEventS2C() { + super(); + } + + public ReceiveEventS2C(int entityId, NBTTagCompound data) { + super(entityId, data); + } + + @SuppressWarnings("unchecked") + @Override + protected

void handle(NetHandler handler, NetH from, P player) { + Player pl = MinecraftClientAccess.get().getDefinitionLoader().loadPlayer(handler.getLoaderId(player), ModelDefinitionLoader.PLAYER_UNIQUE); + pl.animState.receiveEvent(tag, pl.isClientPlayer()); + } +} diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/packet/RecommendSafetyS2C.java b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/packet/RecommendSafetyS2C.java new file mode 100644 index 00000000..5e51dd53 --- /dev/null +++ b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/packet/RecommendSafetyS2C.java @@ -0,0 +1,90 @@ +package com.tom.cpm.shared.network.packet; + +import java.util.Map; + +import com.tom.cpl.config.ConfigEntry; +import com.tom.cpl.nbt.NBTTagCompound; +import com.tom.cpl.text.FormatText; +import com.tom.cpl.text.KeybindText; +import com.tom.cpm.shared.MinecraftClientAccess; +import com.tom.cpm.shared.MinecraftObjectHolder; +import com.tom.cpm.shared.config.BuiltInSafetyProfiles; +import com.tom.cpm.shared.config.ConfigChangeRequest; +import com.tom.cpm.shared.config.ConfigKeys; +import com.tom.cpm.shared.config.ModConfig; +import com.tom.cpm.shared.config.PlayerSpecificConfigKey; +import com.tom.cpm.shared.config.PlayerSpecificConfigKey.KeyGroup; +import com.tom.cpm.shared.config.SocialConfig; +import com.tom.cpm.shared.network.NetH; +import com.tom.cpm.shared.network.NetHandler; +import com.tom.cpm.shared.network.NetworkUtil; + +public class RecommendSafetyS2C extends NBTS2C { + + public RecommendSafetyS2C(NBTTagCompound data) { + super(data); + } + + public RecommendSafetyS2C() { + } + + @SuppressWarnings("unchecked") + @Override + public void handle(NetHandler handler, NetH from) { + String server = MinecraftClientAccess.get().getConnectedServer(); + ConfigEntry cc = ModConfig.getCommonConfig(); + ConfigEntry ss = cc.getEntry(ConfigKeys.SERVER_SETTINGS); + if(server != null && ss.hasEntry(server)) { + if(ss.getEntry(server).getBoolean(ConfigKeys.IGNORE_SAFETY_RECOMMENDATIONS, false))return; + } + + BuiltInSafetyProfiles netProfile = BuiltInSafetyProfiles.get(tag.getString(NetworkUtil.PROFILE_TAG)); + + ConfigEntry ce = null; + if(netProfile == BuiltInSafetyProfiles.CUSTOM) { + try { + Map map = (Map) MinecraftObjectHolder.gson.fromJson(tag.getString(NetworkUtil.PROFILE_DATA), Object.class); + ce = new ConfigEntry(map, () -> {}); + } catch (Exception e) { + return; + } + } + + handler.getRecommendedSettingChanges().clear(); + for(PlayerSpecificConfigKey k : ConfigKeys.SAFETY_KEYS) { + Object rv = ce != null ? k.getValue(ce, KeyGroup.GLOBAL) : k.getValue(netProfile); + Object sv = k.getValueFor(server, null, cc); + if(!rv.equals(sv)) { + handler.getRecommendedSettingChanges().add(new ConfigChangeRequest<>(k, sv, rv)); + } + } + if(!handler.getRecommendedSettingChanges().isEmpty()) { + ConfigEntry gs = cc.getEntry(ConfigKeys.GLOBAL_SETTINGS); + String[] spf = gs.getString(ConfigKeys.SAFETY_PROFILE, BuiltInSafetyProfiles.MEDIUM.name().toLowerCase()).split(":", 2); + BuiltInSafetyProfiles profile = SocialConfig.getProfile(spf); + + if(server != null && ss.hasEntry(server)) { + ConfigEntry e = ss.getEntry(server); + if(e.hasEntry(ConfigKeys.SAFETY_PROFILE)) { + spf = e.getString(ConfigKeys.SAFETY_PROFILE, BuiltInSafetyProfiles.MEDIUM.name().toLowerCase()).split(":", 2); + profile = SocialConfig.getProfile(spf); + } + } + + String old; + if(profile == BuiltInSafetyProfiles.CUSTOM) { + old = "custom:" + spf[1]; + } else { + old = profile.name().toLowerCase(); + } + + if(netProfile == BuiltInSafetyProfiles.CUSTOM) { + handler.getRecommendedSettingChanges().add(new ConfigChangeRequest<>(ConfigKeys.SAFETY_PROFILE, old, "custom:import-" + server)); + } else { + handler.getRecommendedSettingChanges().add(new ConfigChangeRequest<>(ConfigKeys.SAFETY_PROFILE, old, netProfile.name().toLowerCase())); + } + + handler.displayText(new FormatText("chat.cpm.serverSafetySettings", new KeybindText("key.cpm.gestureMenu", "gestureMenu"))); + } + } +} diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/packet/ScaleInfoS2C.java b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/packet/ScaleInfoS2C.java new file mode 100644 index 00000000..d7f39621 --- /dev/null +++ b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/packet/ScaleInfoS2C.java @@ -0,0 +1,26 @@ +package com.tom.cpm.shared.network.packet; + +import com.tom.cpl.nbt.NBTTagCompound; +import com.tom.cpl.text.FormatText; +import com.tom.cpm.shared.network.NetH; +import com.tom.cpm.shared.network.NetHandler; +import com.tom.cpm.shared.network.NetworkUtil; + +public class ScaleInfoS2C extends NBTS2C { + + public ScaleInfoS2C() { + super(); + } + + public ScaleInfoS2C(NBTTagCompound data) { + super(data); + } + + @Override + public void handle(NetHandler handler, NetH from) { + if(tag.hasKey(NetworkUtil.SCALING) && !handler.hasScalingWarning()) { + handler.displayText(new FormatText("chat.cpm.scalingBlocked")); + handler.setScalingWarning(); + } + } +} diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/packet/SetScaleC2S.java b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/packet/SetScaleC2S.java new file mode 100644 index 00000000..c24f443b --- /dev/null +++ b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/packet/SetScaleC2S.java @@ -0,0 +1,57 @@ +package com.tom.cpm.shared.network.packet; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map.Entry; +import java.util.function.BiConsumer; + +import com.tom.cpl.math.MathHelper; +import com.tom.cpl.nbt.NBTTagCompound; +import com.tom.cpl.nbt.NBTTagList; +import com.tom.cpl.nbt.NBTTagString; +import com.tom.cpl.util.Pair; +import com.tom.cpm.shared.config.PlayerData; +import com.tom.cpm.shared.network.NetH.ServerNetH; +import com.tom.cpm.shared.network.NetHandler; +import com.tom.cpm.shared.network.NetworkUtil; +import com.tom.cpm.shared.util.Log; +import com.tom.cpm.shared.util.ScalingOptions; + +public class SetScaleC2S extends NBTC2S { + + public SetScaleC2S(NBTTagCompound data) { + super(data); + } + + public SetScaleC2S() { + } + + @Override + public

void handle(NetHandler handler, ServerNetH net, P pl) { + PlayerData pd = net.cpm$getEncodedModelData(); + List blocked = new ArrayList<>(); + for(Entry> e : handler.getScaleSetters().entrySet()) { + float oldV = pd.scale.getOrDefault(e.getKey(), 1F); + float selNewV = tag.getFloat(e.getKey().getNetKey()); + float newV = selNewV; + Pair l = NetworkUtil.getScalingLimits(e.getKey(), handler.getID(pl)); + newV = newV == 0 || l == null ? 1F : MathHelper.clamp(newV, l.getKey(), l.getValue()); + Log.debug("Scaling " + e.getKey() + " " + oldV + " -> " + newV); + if(newV != oldV) { + e.getValue().accept(pl, newV); + pd.scale.put(e.getKey(), newV); + } + if(newV != selNewV && selNewV != 0) { + blocked.add(e.getKey()); + } + } + pd.save(handler.getID(pl)); + NBTTagCompound ret = new NBTTagCompound(); + if(!blocked.isEmpty()) { + NBTTagList list = new NBTTagList(); + blocked.forEach(sc -> list.appendTag(new NBTTagString(sc.getNetKey()))); + ret.setTag(NetworkUtil.SCALING, list); + } + handler.sendPacketTo(net, new ScaleInfoS2C(ret)); + } +} diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/packet/SetSkinC2S.java b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/packet/SetSkinC2S.java new file mode 100644 index 00000000..163dbd98 --- /dev/null +++ b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/packet/SetSkinC2S.java @@ -0,0 +1,29 @@ +package com.tom.cpm.shared.network.packet; + +import com.tom.cpl.nbt.NBTTagCompound; +import com.tom.cpm.shared.config.PlayerData; +import com.tom.cpm.shared.network.NetH.ServerNetH; +import com.tom.cpm.shared.network.NetHandler; +import com.tom.cpm.shared.network.NetworkUtil; + +public class SetSkinC2S extends NBTC2S { + + public SetSkinC2S(NBTTagCompound data) { + super(data); + } + + public SetSkinC2S() { + } + + @Override + public

void handle(NetHandler handler, ServerNetH net, P player) { + PlayerData pd = net.cpm$getEncodedModelData(); + if(pd.canChangeModel()) { + pd.setModel(tag.hasKey(NetworkUtil.DATA_TAG) ? tag.getByteArray(NetworkUtil.DATA_TAG) : null, false, false); + handler.sendPacketToTracking(player, NetworkUtil.writeSkinData(handler, pd, player)); + pd.save(handler.getID(player)); + } else { + handler.sendChat(player, NetworkUtil.FORCED_CHAT_MSG); + } + } +} diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/packet/SetSkinS2C.java b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/packet/SetSkinS2C.java new file mode 100644 index 00000000..4fbfb2ab --- /dev/null +++ b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/packet/SetSkinS2C.java @@ -0,0 +1,25 @@ +package com.tom.cpm.shared.network.packet; + +import com.tom.cpl.nbt.NBTTagCompound; +import com.tom.cpm.shared.MinecraftClientAccess; +import com.tom.cpm.shared.network.NetH; +import com.tom.cpm.shared.network.NetHandler; +import com.tom.cpm.shared.network.NetworkUtil; + +public class SetSkinS2C extends NBTEntityS2C { + + public SetSkinS2C() { + super(); + } + + public SetSkinS2C(int entityId, NBTTagCompound data) { + super(entityId, data); + } + + @SuppressWarnings("unchecked") + @Override + protected

void handle(NetHandler handler, NetH from, P player) { + MinecraftClientAccess.get().getDefinitionLoader().setModel(handler.getLoaderId(player), tag.hasKey(NetworkUtil.DATA_TAG) ? tag.getByteArray(NetworkUtil.DATA_TAG) : null, tag.getBoolean(NetworkUtil.FORCED_TAG)); + } + +} diff --git a/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/packet/SubEventC2S.java b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/packet/SubEventC2S.java new file mode 100644 index 00000000..d6550e24 --- /dev/null +++ b/CustomPlayerModels/src/shared/java/com/tom/cpm/shared/network/packet/SubEventC2S.java @@ -0,0 +1,31 @@ +package com.tom.cpm.shared.network.packet; + +import com.tom.cpl.nbt.NBTTag; +import com.tom.cpl.nbt.NBTTagCompound; +import com.tom.cpl.nbt.NBTTagList; +import com.tom.cpm.shared.config.PlayerData; +import com.tom.cpm.shared.network.ModelEventType; +import com.tom.cpm.shared.network.NetH.ServerNetH; +import com.tom.cpm.shared.network.NetHandler; +import com.tom.cpm.shared.network.NetworkUtil; + +public class SubEventC2S extends NBTC2S { + + public SubEventC2S(NBTTagCompound data) { + super(data); + } + + public SubEventC2S() { + } + + @Override + public

void handle(NetHandler handler, ServerNetH net, P player) { + PlayerData pd = net.cpm$getEncodedModelData(); + pd.eventSubs.clear(); + NBTTagList list = tag.getTagList(NetworkUtil.EVENT_LIST, NBTTag.TAG_STRING); + for (int i = 0;i button.cpm.openWikiExt=在浏览器中打开 +button.cpm.clearAnimDataAll=全部清除 button.cpm.root_group.cape=披风 button.cpm.root_group.elytra=鞘翅 button.cpm.root_group.armor=盔甲 @@ -160,7 +161,7 @@ tooltip.cpm.new.template=创建一个新的模板项目\阅读关于使用模板 tooltip.cpm.anim_priority=动画应用优先级\动画按从低到高的顺序应用。 tooltip.cpm.export_def=为链接到此皮肤的文件创建更新。 tooltip.cpm.config.titleScreenButton=在标题屏幕上显示打开编辑器按钮\打开编辑器按钮也可在选项/皮肤自定义 gui 中使用。 -tooltip.cpm.glow=早期发光。\将末影人和蜘蛛眼使用的原版发光眼睛效果应用到选定的部分。 +tooltip.cpm.glow=早期自发光。\将末影人和蜘蛛眼使用的原版自发光眼睛效果应用到选定的部分。 tooltip.cpm.display.onlyDrawOnSelected=只允许在选定的模型上绘画。 tooltip.cpm.effect.scaling=启用不同的模型缩放选项。\有关选项,请参阅模型列表。 tooltip.cpm.cloneable=任何人都可以克隆和使用此模型。\在玩家设置菜单中克隆模型。 @@ -273,6 +274,13 @@ tooltip.cpm.loading=正在加载项目... tooltip.cpm.loadSuccess=已加载项目:%s tooltip.cpm.failedToLoadImage=加载图像失败:%s tooltip.cpm.config.wikiOfflineMode=使用离线wiki,可能已经过时了! +tooltip.cpm.config.editorGizmoAlpha=工具透明度 +tooltip.cpm.config.editorUVAreaAlpha=选定的 UV 区域叠加透明度 +tooltip.cpm.config.editorUVAreaAllAlpha=未选择 UV 区域叠加透明度 +tooltip.cpm.config.editorGizmoScale=将工具缩放到当前缩放。 +tooltip.cpm.config.editorGizmoSize=工具宽度乘数 +tooltip.cpm.config.editorGizmoLength= 工具长度乘数 +tooltip.cpm.config.editorAutosaveTime=自动保存之间的时间间隔。\将其设置为 -1 以禁用。 tab.cpm.model=模型 tab.cpm.texture=纹理 tab.cpm.animation=动画 @@ -649,6 +657,7 @@ label.cpm.changelog.newVersion.desc=新版本可用!\查看编辑/更改日志 label.cpm.openURL.title=打开网址 label.cpm.openURL.text=您确定要打开以下网站吗?\%s\切勿打开您不信任的链接! label.cpm.config.wikiOfflineMode=维基离线模式 +label.cpm.config.editorAutosaveTime=自动保存间隔:%ss label.cpm.paste.connecting.title=连接... label.cpm.paste.connecting.message=正在连接到粘贴站点... label.cpm.paste.listing=正在刷新文件列表... @@ -788,8 +797,9 @@ commands.cpm.kickWOMod=在没有模组的情况下踢出玩家 commands.cpm.kickWOMod.msg=踢出消息 commands.cpm.numberOutOfBounds=输入的数字超出范围 chat.cpm.skinForced=换不了皮肤。 你的皮肤是服务器管理员强制设置的. -chat.cpm.serverSafetySettings=服务器有推荐的安全设置。 打开手势菜单 [%s] 以编辑安全设置。 +chat.cpm.serverSafetySettings=[CPM] 服务器有推荐的安全设置。 打开手势菜单 [%s] 以编辑安全设置。 chat.cpm.serverRequiresCPM=服务器需要安装 CPM 并开启通讯。 当前“禁用服务器通信”设置设置为“true”,您将被踢出服务器。 打开手势菜单 [%s] 以编辑设置。 +chat.cpm.scalingBlocked=[CPM] 某些缩放设置被阻止,请让管理员启用缩放。 action.cpm.switch=转换%s action.cpm.set=设置%s action.cpm.add=添加%s @@ -872,7 +882,7 @@ label.cpm.key.left.alt= 左Alt label.cpm.key.right.alt=右Alt label.cpm.key.left.shift=左Shift label.cpm.key.right.shift=右Shift -label.cpm.key.space=Space +label.cpm.key.space=空格 label.cpm.key.tab=Tab label.cpm.key.up=向上箭头 label.cpm.key.down=向下箭头 diff --git a/CustomPlayerModels/src/shared/resources/assets/cpm/wiki/pages/API-documentation.md b/CustomPlayerModels/src/shared/resources/assets/cpm/wiki/pages/API-documentation.md index b05531ef..3c653b20 100644 --- a/CustomPlayerModels/src/shared/resources/assets/cpm/wiki/pages/API-documentation.md +++ b/CustomPlayerModels/src/shared/resources/assets/cpm/wiki/pages/API-documentation.md @@ -137,18 +137,18 @@ else ### Voice animation Register a voice level supplier. `IClientAPI:registerVoice(Player.class, player -> voiceLevel);` -[Player.class](#client-player-class) +[Player.class](#client-playerclass) ### Rendering API Create a player renderer to render CPM models on any Humanoid Entity. `PlayerRenderer renderer = IClientAPI.createPlayerRenderer(Model.class, ResourceLocation.class, RenderType.class, MultiBufferSource.class, GameProfile.class)` For 1.12 and lower use: `RetroPlayerRenderer renderer = IClientAPI.createPlayerRenderer(Model.class, GameProfile.class);` -[Model.class](#client-model-class) -[ResourceLocation.class](#client-resourcelocation-class) -[RenderType.class](#client-rendertype-class) -[MultiBufferSource.class](#client-multibuffersource-class) -[GameProfile.class](#client-gameprofile-class) +[Model.class](#client-modelclass) +[ResourceLocation.class](#client-resourcelocationclass) +[RenderType.class](#client-rendertypeclass) +[MultiBufferSource.class](#client-multibuffersourceclass) +[GameProfile.class](#client-gameprofileclass) #### Rendering an Entity with CPM model 1. Using the renderer set the GameProfile or LocalModel before rendering. @@ -280,12 +280,12 @@ Create a ModelFile using `ModelFile.load(file);` or `ModelFile.load(inputstream) or `ICommonAPI.resetPlayerModel(Player.class, playerObj);` clear the server set model -[Player.class](#common-player-class) +[Player.class](#common-playerclass) ### Jump (0.4.1+) Play the jump animation on for a player. `ICommonAPI.playerJumped(Player.class, playerObj);` -[Player.class](#common-player-class) +[Player.class](#common-playerclass) ### Class Map Classes are dependent on your minecraft version and mod loader. diff --git a/CustomPlayerModels/src/shared/resources/assets/cpm/wiki/pages/Mod-Integrations.md b/CustomPlayerModels/src/shared/resources/assets/cpm/wiki/pages/Mod-Integrations.md new file mode 100644 index 00000000..7ae71f48 --- /dev/null +++ b/CustomPlayerModels/src/shared/resources/assets/cpm/wiki/pages/Mod-Integrations.md @@ -0,0 +1,12 @@ +Integration animations: +- [Speaking](#speaking) +- [First Person View](#first-person-view) + +## Speaking +- [Simple Voice Chat](https://www.curseforge.com/minecraft/mc-mods/simple-voice-chat) +Requires compat mod: [Customizable Player Models Simple Voice Chat compat](https://www.curseforge.com/minecraft/mc-mods/cpmsvcc) + +## First Person View +- [First-person Model (Forge/Fabric)](https://www.curseforge.com/minecraft/mc-mods/first-person-model) + + diff --git a/CustomPlayerModels/src/shared/resources/assets/cpm/wiki/pages/_Sidebar.md b/CustomPlayerModels/src/shared/resources/assets/cpm/wiki/pages/_Sidebar.md index 1009abfa..867af78b 100644 --- a/CustomPlayerModels/src/shared/resources/assets/cpm/wiki/pages/_Sidebar.md +++ b/CustomPlayerModels/src/shared/resources/assets/cpm/wiki/pages/_Sidebar.md @@ -7,6 +7,7 @@ Customizable Player Models Wiki * [Exporting Models](https://github.com/tom5454/CustomPlayerModels/wiki/Exporting) * [Creating Animations](https://github.com/tom5454/CustomPlayerModels/wiki/Animations) * [Animated Textures](https://github.com/tom5454/CustomPlayerModels/wiki/Animated-Textures) +* [Mod Integrations](https://github.com/tom5454/CustomPlayerModels/wiki/Mod-Integrations) * Controls * [Editor](https://github.com/tom5454/CustomPlayerModels/wiki/Controls#editor-controls) * [In-Game](https://github.com/tom5454/CustomPlayerModels/wiki/Controls#in-game-controls-keybindings) diff --git a/CustomPlayerModelsFabric-1.16/gradle.properties b/CustomPlayerModelsFabric-1.16/gradle.properties index efe62488..ee8b082f 100644 --- a/CustomPlayerModelsFabric-1.16/gradle.properties +++ b/CustomPlayerModelsFabric-1.16/gradle.properties @@ -11,6 +11,6 @@ loader_version=0.12.11 fabric_version=0.42.0+1.16 # Mod Properties -mod_version=0.4.8a +mod_version=0.5.0a maven_group = com.tom archives_base_name = CustomPlayerModels-Fabric-1.16 diff --git a/CustomPlayerModelsFabric-1.16/src/main/java/com/tom/cpm/client/CustomPlayerModelsClient.java b/CustomPlayerModelsFabric-1.16/src/main/java/com/tom/cpm/client/CustomPlayerModelsClient.java index 3ddd1b4b..6257eef4 100644 --- a/CustomPlayerModelsFabric-1.16/src/main/java/com/tom/cpm/client/CustomPlayerModelsClient.java +++ b/CustomPlayerModelsFabric-1.16/src/main/java/com/tom/cpm/client/CustomPlayerModelsClient.java @@ -1,23 +1,18 @@ package com.tom.cpm.client; -import java.util.List; -import java.util.Map.Entry; - import net.fabricmc.api.ClientModInitializer; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents; +import net.fabricmc.fabric.api.client.screen.v1.Screens; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.Element; -import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.TitleScreen; import net.minecraft.client.gui.screen.option.SkinOptionsScreen; import net.minecraft.client.gui.widget.ButtonWidget; -import net.minecraft.client.gui.widget.ClickableWidget; import net.minecraft.client.model.Model; import net.minecraft.client.network.AbstractClientPlayerEntity; import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.client.option.KeyBinding; import net.minecraft.client.render.OverlayTexture; import net.minecraft.client.render.RenderLayer; import net.minecraft.client.render.VertexConsumer; @@ -91,10 +86,14 @@ public void onInitializeClient() { Player.setEnableRendering(!Player.isEnableRendering()); } - for (Entry e : KeyBindings.quickAccess.entrySet()) { - if(e.getValue().wasPressed()) { - mc.getPlayerRenderManager().getAnimationEngine().onKeybind(e.getKey()); - } + mc.getPlayerRenderManager().getAnimationEngine().updateKeys(KeyBindings.quickAccess); + }); + ScreenEvents.AFTER_INIT.register((mc, screen, sw, sh) -> { + ScreenEvents.beforeRender(screen).register((_1, _2, _3, _4, _5) -> PlayerProfile.inGui = true); + ScreenEvents.afterRender(screen).register((_1, _2, _3, _4, _5) -> PlayerProfile.inGui = false); + if((screen instanceof TitleScreen && ModConfig.getCommonConfig().getSetBoolean(ConfigKeys.TITLE_SCREEN_BUTTON, true)) || + screen instanceof SkinOptionsScreen) { + Screens.getButtons(screen).add(new Button(0, 0, () -> MinecraftClient.getInstance().openScreen(new GuiImpl(EditorGui::new, screen)))); } }); manager = new RenderManager<>(mc.getPlayerRenderManager(), mc.getDefinitionLoader(), PlayerEntity::getGameProfile); @@ -127,15 +126,6 @@ public void playerRenderPost(VertexConsumerProvider buffer, PlayerEntityModel mo manager.unbindClear(model); } - public void initGui(Screen screen, List children, List buttons) { - if((screen instanceof TitleScreen && ModConfig.getCommonConfig().getSetBoolean(ConfigKeys.TITLE_SCREEN_BUTTON, true)) || - screen instanceof SkinOptionsScreen) { - Button btn = new Button(0, 0, () -> MinecraftClient.getInstance().openScreen(new GuiImpl(EditorGui::new, screen))); - buttons.add(btn); - children.add(btn); - } - } - public void renderHand(VertexConsumerProvider buffer, PlayerEntityModel model) { manager.bindHand(MinecraftClient.getInstance().player, buffer, model); } diff --git a/CustomPlayerModelsFabric-1.16/src/main/java/com/tom/cpm/client/KeyBindings.java b/CustomPlayerModelsFabric-1.16/src/main/java/com/tom/cpm/client/KeyBindings.java index 66778889..d441324a 100644 --- a/CustomPlayerModelsFabric-1.16/src/main/java/com/tom/cpm/client/KeyBindings.java +++ b/CustomPlayerModelsFabric-1.16/src/main/java/com/tom/cpm/client/KeyBindings.java @@ -1,9 +1,7 @@ package com.tom.cpm.client; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.lwjgl.glfw.GLFW; @@ -16,7 +14,8 @@ public class KeyBindings implements IKeybind { public static KeyBinding gestureMenuBinding, renderToggleBinding; - public static Map quickAccess = new HashMap<>(); + public static IKeybind[] quickAccess = new IKeybind[IKeybind.QUICK_ACCESS_KEYBINDS_COUNT]; + public static void init() { gestureMenuBinding = new KeyBinding("key.cpm.gestureMenu", GLFW.GLFW_KEY_G, "key.cpm.category"); kbs.add(new KeyBindings(gestureMenuBinding, "gestureMenu")); @@ -24,14 +23,15 @@ public static void init() { renderToggleBinding = new KeyBinding("key.cpm.renderToggle", InputUtil.UNKNOWN_KEY.getCode(), "key.cpm.category"); kbs.add(new KeyBindings(renderToggleBinding, "renderToggle")); - for(int i = 1;i<=6;i++) + for(int i = 1;i<=IKeybind.QUICK_ACCESS_KEYBINDS_COUNT;i++) createQA(i); } private static void createQA(int id) { KeyBinding kb = new KeyBinding("key.cpm.qa_" + id, InputUtil.UNKNOWN_KEY.getCode(), "key.cpm.category"); - kbs.add(new KeyBindings(kb, "qa_" + id)); - quickAccess.put(id, kb); + KeyBindings kbs = new KeyBindings(kb, "qa_" + id); + KeyBindings.kbs.add(kbs); + quickAccess[id - 1] = kbs; } public static List kbs = new ArrayList<>(); @@ -58,4 +58,9 @@ public String getBoundKey() { public String getName() { return name; } + + @Override + public boolean isPressed() { + return kb.isPressed(); + } } diff --git a/CustomPlayerModelsFabric-1.16/src/main/java/com/tom/cpm/client/PlayerProfile.java b/CustomPlayerModelsFabric-1.16/src/main/java/com/tom/cpm/client/PlayerProfile.java index 02ee333f..69f89186 100644 --- a/CustomPlayerModelsFabric-1.16/src/main/java/com/tom/cpm/client/PlayerProfile.java +++ b/CustomPlayerModelsFabric-1.16/src/main/java/com/tom/cpm/client/PlayerProfile.java @@ -1,9 +1,13 @@ package com.tom.cpm.client; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; import java.util.Map; import java.util.UUID; import java.util.concurrent.CompletableFuture; +import java.util.function.BooleanSupplier; +import net.fabricmc.loader.api.FabricLoader; import net.minecraft.block.AbstractSkullBlock; import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.entity.PlayerModelPart; @@ -34,6 +38,27 @@ import com.tom.cpm.shared.skin.PlayerTextureLoader; public class PlayerProfile extends Player { + public static boolean inGui; + public static BooleanSupplier inFirstPerson; + static { + inFirstPerson = () -> false; + if(FabricLoader.getInstance().isModLoaded("firstperson")) { + try { + MethodHandle h = MethodHandles.lookup().unreflectGetter(Class.forName("dev.tr7zw.firstperson.FirstPersonModelCore").getDeclaredField("isRenderingPlayer")); + inFirstPerson = () -> { + try { + return (boolean) h.invoke(); + } catch (Throwable e) { + inFirstPerson = () -> false; + return false; + } + }; + inFirstPerson.getAsBoolean(); + } catch (Throwable e) { + } + } + } + private final GameProfile profile; private String skinType; @@ -180,6 +205,8 @@ public void updateFromPlayer(PlayerEntity player) { animState.hurtTime = player.hurtTime; animState.isOnLadder = player.isClimbing(); animState.isBurning = player.isOnFire(); + animState.inGui = inGui; + animState.firstPersonMod = inFirstPerson.getAsBoolean(); if(player.getActiveItem().getItem() instanceof CrossbowItem) { float f = CrossbowItem.getPullTime(player.getActiveItem()); diff --git a/CustomPlayerModelsFabric-1.16/src/main/java/com/tom/cpm/client/VBufferOut.java b/CustomPlayerModelsFabric-1.16/src/main/java/com/tom/cpm/client/VBufferOut.java index fcd670b0..85926417 100644 --- a/CustomPlayerModelsFabric-1.16/src/main/java/com/tom/cpm/client/VBufferOut.java +++ b/CustomPlayerModelsFabric-1.16/src/main/java/com/tom/cpm/client/VBufferOut.java @@ -15,8 +15,8 @@ public class VBufferOut implements BufferOutput { public VBufferOut(int light, int overlay, MatrixStack matrixStackIn) { this.light = light; this.overlay = overlay; - mat4 = matrixStackIn.peek().getModel(); - mat3 = matrixStackIn.peek().getNormal(); + mat4 = new Matrix4f(matrixStackIn.peek().getModel()); + mat3 = new Matrix3f(matrixStackIn.peek().getNormal()); } @Override diff --git a/CustomPlayerModelsFabric-1.16/src/main/java/com/tom/cpm/mixin/PlayerRendererMixin.java b/CustomPlayerModelsFabric-1.16/src/main/java/com/tom/cpm/mixin/PlayerRendererMixin.java index 9648edc6..f93b83cd 100644 --- a/CustomPlayerModelsFabric-1.16/src/main/java/com/tom/cpm/mixin/PlayerRendererMixin.java +++ b/CustomPlayerModelsFabric-1.16/src/main/java/com/tom/cpm/mixin/PlayerRendererMixin.java @@ -85,8 +85,15 @@ public Identifier getSkinTex(AbstractClientPlayerEntity player) { } @Inject(at = @At("HEAD"), method = "renderLabelIfPresent(Lnet/minecraft/client/network/AbstractClientPlayerEntity;Lnet/minecraft/text/Text;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;I)V", cancellable = true) - public void onRenderName(AbstractClientPlayerEntity entityIn, Text displayNameIn, MatrixStack matrixStackIn, VertexConsumerProvider bufferIn, int packedLightIn, CallbackInfo cbi) { + public void onRenderName1(AbstractClientPlayerEntity entityIn, Text displayNameIn, MatrixStack matrixStackIn, VertexConsumerProvider bufferIn, int packedLightIn, CallbackInfo cbi) { if(!Player.isEnableNames())cbi.cancel(); + } + + @Inject(at = @At(value = "INVOKE", + target = "Lnet/minecraft/client/render/entity/LivingEntityRenderer;renderLabelIfPresent(Lnet/minecraft/entity/Entity;Lnet/minecraft/text/Text;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;I)V", + ordinal = 1), + method = "renderLabelIfPresent(Lnet/minecraft/client/network/AbstractClientPlayerEntity;Lnet/minecraft/text/Text;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;I)V") + public void onRenderName2(AbstractClientPlayerEntity entityIn, Text displayNameIn, MatrixStack matrixStackIn, VertexConsumerProvider bufferIn, int packedLightIn, CallbackInfo cbi) { if(Player.isEnableLoadingInfo()) CustomPlayerModelsClient.renderNameTag(this, entityIn, entityIn.getGameProfile(), ModelDefinitionLoader.PLAYER_UNIQUE, matrixStackIn, bufferIn, packedLightIn); } diff --git a/CustomPlayerModelsFabric-1.16/src/main/java/com/tom/cpm/mixin/ScreenMixin.java b/CustomPlayerModelsFabric-1.16/src/main/java/com/tom/cpm/mixin/ScreenMixin.java deleted file mode 100644 index a2a34822..00000000 --- a/CustomPlayerModelsFabric-1.16/src/main/java/com/tom/cpm/mixin/ScreenMixin.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.tom.cpm.mixin; - -import java.util.List; - -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; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.Element; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.widget.ClickableWidget; - -import com.tom.cpm.client.CustomPlayerModelsClient; - -@Mixin(Screen.class) -public class ScreenMixin { - - @Shadow - protected List buttons; - - @Shadow - protected List children; - - @Inject(at = @At("RETURN"), method = "init(Lnet/minecraft/client/MinecraftClient;II)V") - public void onInit(MinecraftClient client, int width, int height, CallbackInfo cbi) { - CustomPlayerModelsClient.INSTANCE.initGui((Screen)(Object)this, children, buttons); - } -} diff --git a/CustomPlayerModelsFabric-1.16/src/main/resources/cpm.mixins.json b/CustomPlayerModelsFabric-1.16/src/main/resources/cpm.mixins.json index 688e917c..cc45f647 100644 --- a/CustomPlayerModelsFabric-1.16/src/main/resources/cpm.mixins.json +++ b/CustomPlayerModelsFabric-1.16/src/main/resources/cpm.mixins.json @@ -10,7 +10,6 @@ ], "client": [ "PlayerRendererMixin", - "ScreenMixin", "MinecraftClientMixin", "SkullBlockEntityRendererMixin", "ClientPlayNetHandlerMixin", diff --git a/CustomPlayerModelsFabric-1.17/gradle.properties b/CustomPlayerModelsFabric-1.17/gradle.properties index ec1263ea..42bc22ab 100644 --- a/CustomPlayerModelsFabric-1.17/gradle.properties +++ b/CustomPlayerModelsFabric-1.17/gradle.properties @@ -11,6 +11,6 @@ loader_version=0.12.11 fabric_version=0.44.0+1.17 # Mod Properties -mod_version=0.4.8a +mod_version=0.5.0a maven_group = com.tom archives_base_name = CustomPlayerModels-Fabric-1.17 diff --git a/CustomPlayerModelsFabric-1.17/src/main/java/com/tom/cpm/client/CustomPlayerModelsClient.java b/CustomPlayerModelsFabric-1.17/src/main/java/com/tom/cpm/client/CustomPlayerModelsClient.java index 90755025..8eb758bf 100644 --- a/CustomPlayerModelsFabric-1.17/src/main/java/com/tom/cpm/client/CustomPlayerModelsClient.java +++ b/CustomPlayerModelsFabric-1.17/src/main/java/com/tom/cpm/client/CustomPlayerModelsClient.java @@ -1,14 +1,13 @@ package com.tom.cpm.client; -import java.util.Map.Entry; import java.util.function.Consumer; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents; +import net.fabricmc.fabric.api.client.screen.v1.Screens; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.Element; -import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.TitleScreen; import net.minecraft.client.gui.screen.option.SkinOptionsScreen; import net.minecraft.client.gui.widget.ButtonWidget; @@ -16,7 +15,6 @@ import net.minecraft.client.network.AbstractClientPlayerEntity; import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.client.option.KeyBinding; import net.minecraft.client.render.OverlayTexture; import net.minecraft.client.render.RenderLayer; import net.minecraft.client.render.Shader; @@ -94,10 +92,14 @@ public void onInitializeClient() { Player.setEnableRendering(!Player.isEnableRendering()); } - for (Entry e : KeyBindings.quickAccess.entrySet()) { - if(e.getValue().wasPressed()) { - mc.getPlayerRenderManager().getAnimationEngine().onKeybind(e.getKey()); - } + mc.getPlayerRenderManager().getAnimationEngine().updateKeys(KeyBindings.quickAccess); + }); + ScreenEvents.AFTER_INIT.register((mc, screen, sw, sh) -> { + ScreenEvents.beforeRender(screen).register((_1, _2, _3, _4, _5) -> PlayerProfile.inGui = true); + ScreenEvents.afterRender(screen).register((_1, _2, _3, _4, _5) -> PlayerProfile.inGui = false); + if((screen instanceof TitleScreen && ModConfig.getCommonConfig().getSetBoolean(ConfigKeys.TITLE_SCREEN_BUTTON, true)) || + screen instanceof SkinOptionsScreen) { + Screens.getButtons(screen).add(new Button(0, 0, () -> MinecraftClient.getInstance().setScreen(new GuiImpl(EditorGui::new, screen)))); } }); manager = new RenderManager<>(mc.getPlayerRenderManager(), mc.getDefinitionLoader(), PlayerEntity::getGameProfile); @@ -134,18 +136,6 @@ public void playerRenderPost(VertexConsumerProvider buffer, PlayerEntityModel mo manager.unbindClear(model); } - public void initGui(Screen screen) { - if((screen instanceof TitleScreen && ModConfig.getCommonConfig().getSetBoolean(ConfigKeys.TITLE_SCREEN_BUTTON, true)) || - screen instanceof SkinOptionsScreen) { - Button btn = new Button(0, 0, () -> MinecraftClient.getInstance().setScreen(new GuiImpl(EditorGui::new, screen))); - ((IScreen)screen).cpm$addDrawableChild(btn); - } - } - - public static interface IScreen { - void cpm$addDrawableChild(Element drawableElement); - } - public void renderHand(VertexConsumerProvider buffer, PlayerEntityModel model) { manager.bindHand(MinecraftClient.getInstance().player, buffer, model); } diff --git a/CustomPlayerModelsFabric-1.17/src/main/java/com/tom/cpm/client/KeyBindings.java b/CustomPlayerModelsFabric-1.17/src/main/java/com/tom/cpm/client/KeyBindings.java index 66778889..d441324a 100644 --- a/CustomPlayerModelsFabric-1.17/src/main/java/com/tom/cpm/client/KeyBindings.java +++ b/CustomPlayerModelsFabric-1.17/src/main/java/com/tom/cpm/client/KeyBindings.java @@ -1,9 +1,7 @@ package com.tom.cpm.client; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.lwjgl.glfw.GLFW; @@ -16,7 +14,8 @@ public class KeyBindings implements IKeybind { public static KeyBinding gestureMenuBinding, renderToggleBinding; - public static Map quickAccess = new HashMap<>(); + public static IKeybind[] quickAccess = new IKeybind[IKeybind.QUICK_ACCESS_KEYBINDS_COUNT]; + public static void init() { gestureMenuBinding = new KeyBinding("key.cpm.gestureMenu", GLFW.GLFW_KEY_G, "key.cpm.category"); kbs.add(new KeyBindings(gestureMenuBinding, "gestureMenu")); @@ -24,14 +23,15 @@ public static void init() { renderToggleBinding = new KeyBinding("key.cpm.renderToggle", InputUtil.UNKNOWN_KEY.getCode(), "key.cpm.category"); kbs.add(new KeyBindings(renderToggleBinding, "renderToggle")); - for(int i = 1;i<=6;i++) + for(int i = 1;i<=IKeybind.QUICK_ACCESS_KEYBINDS_COUNT;i++) createQA(i); } private static void createQA(int id) { KeyBinding kb = new KeyBinding("key.cpm.qa_" + id, InputUtil.UNKNOWN_KEY.getCode(), "key.cpm.category"); - kbs.add(new KeyBindings(kb, "qa_" + id)); - quickAccess.put(id, kb); + KeyBindings kbs = new KeyBindings(kb, "qa_" + id); + KeyBindings.kbs.add(kbs); + quickAccess[id - 1] = kbs; } public static List kbs = new ArrayList<>(); @@ -58,4 +58,9 @@ public String getBoundKey() { public String getName() { return name; } + + @Override + public boolean isPressed() { + return kb.isPressed(); + } } diff --git a/CustomPlayerModelsFabric-1.17/src/main/java/com/tom/cpm/client/PlayerProfile.java b/CustomPlayerModelsFabric-1.17/src/main/java/com/tom/cpm/client/PlayerProfile.java index 9a5c0d5b..aacd0793 100644 --- a/CustomPlayerModelsFabric-1.17/src/main/java/com/tom/cpm/client/PlayerProfile.java +++ b/CustomPlayerModelsFabric-1.17/src/main/java/com/tom/cpm/client/PlayerProfile.java @@ -1,9 +1,13 @@ package com.tom.cpm.client; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; import java.util.Map; import java.util.UUID; import java.util.concurrent.CompletableFuture; +import java.util.function.BooleanSupplier; +import net.fabricmc.loader.api.FabricLoader; import net.minecraft.block.AbstractSkullBlock; import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.entity.PlayerModelPart; @@ -34,6 +38,27 @@ import com.tom.cpm.shared.skin.PlayerTextureLoader; public class PlayerProfile extends Player { + public static boolean inGui; + public static BooleanSupplier inFirstPerson; + static { + inFirstPerson = () -> false; + if(FabricLoader.getInstance().isModLoaded("firstperson")) { + try { + MethodHandle h = MethodHandles.lookup().unreflectGetter(Class.forName("dev.tr7zw.firstperson.FirstPersonModelCore").getDeclaredField("isRenderingPlayer")); + inFirstPerson = () -> { + try { + return (boolean) h.invoke(); + } catch (Throwable e) { + inFirstPerson = () -> false; + return false; + } + }; + inFirstPerson.getAsBoolean(); + } catch (Throwable e) { + } + } + } + private final GameProfile profile; private String skinType; @@ -179,6 +204,8 @@ public void updateFromPlayer(PlayerEntity player) { animState.isOnLadder = player.isClimbing(); animState.isBurning = player.isOnFire(); animState.isFreezing = player.getFrozenTicks() > 0; + animState.inGui = inGui; + animState.firstPersonMod = inFirstPerson.getAsBoolean(); if(player.getActiveItem().getItem() instanceof CrossbowItem) { float f = CrossbowItem.getPullTime(player.getActiveItem()); diff --git a/CustomPlayerModelsFabric-1.17/src/main/java/com/tom/cpm/client/VBufferOut.java b/CustomPlayerModelsFabric-1.17/src/main/java/com/tom/cpm/client/VBufferOut.java index fcd670b0..85926417 100644 --- a/CustomPlayerModelsFabric-1.17/src/main/java/com/tom/cpm/client/VBufferOut.java +++ b/CustomPlayerModelsFabric-1.17/src/main/java/com/tom/cpm/client/VBufferOut.java @@ -15,8 +15,8 @@ public class VBufferOut implements BufferOutput { public VBufferOut(int light, int overlay, MatrixStack matrixStackIn) { this.light = light; this.overlay = overlay; - mat4 = matrixStackIn.peek().getModel(); - mat3 = matrixStackIn.peek().getNormal(); + mat4 = new Matrix4f(matrixStackIn.peek().getModel()); + mat3 = new Matrix3f(matrixStackIn.peek().getNormal()); } @Override diff --git a/CustomPlayerModelsFabric-1.17/src/main/java/com/tom/cpm/mixin/PlayerRendererMixin.java b/CustomPlayerModelsFabric-1.17/src/main/java/com/tom/cpm/mixin/PlayerRendererMixin.java index fc6db57c..0883f367 100644 --- a/CustomPlayerModelsFabric-1.17/src/main/java/com/tom/cpm/mixin/PlayerRendererMixin.java +++ b/CustomPlayerModelsFabric-1.17/src/main/java/com/tom/cpm/mixin/PlayerRendererMixin.java @@ -101,8 +101,15 @@ public RenderLayer getArmLayer(Identifier loc, MatrixStack matrices, VertexConsu } @Inject(at = @At("HEAD"), method = "renderLabelIfPresent(Lnet/minecraft/client/network/AbstractClientPlayerEntity;Lnet/minecraft/text/Text;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;I)V", cancellable = true) - public void onRenderName(AbstractClientPlayerEntity entityIn, Text displayNameIn, MatrixStack matrixStackIn, VertexConsumerProvider bufferIn, int packedLightIn, CallbackInfo cbi) { + public void onRenderName1(AbstractClientPlayerEntity entityIn, Text displayNameIn, MatrixStack matrixStackIn, VertexConsumerProvider bufferIn, int packedLightIn, CallbackInfo cbi) { if(!Player.isEnableNames())cbi.cancel(); + } + + @Inject(at = @At(value = "INVOKE", + target = "Lnet/minecraft/client/render/entity/LivingEntityRenderer;renderLabelIfPresent(Lnet/minecraft/entity/Entity;Lnet/minecraft/text/Text;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;I)V", + ordinal = 1), + method = "renderLabelIfPresent(Lnet/minecraft/client/network/AbstractClientPlayerEntity;Lnet/minecraft/text/Text;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;I)V") + public void onRenderName2(AbstractClientPlayerEntity entityIn, Text displayNameIn, MatrixStack matrixStackIn, VertexConsumerProvider bufferIn, int packedLightIn, CallbackInfo cbi) { if(Player.isEnableLoadingInfo()) CustomPlayerModelsClient.renderNameTag(this, entityIn, entityIn.getGameProfile(), ModelDefinitionLoader.PLAYER_UNIQUE, matrixStackIn, bufferIn, packedLightIn); } diff --git a/CustomPlayerModelsFabric-1.17/src/main/java/com/tom/cpm/mixin/ScreenMixin.java b/CustomPlayerModelsFabric-1.17/src/main/java/com/tom/cpm/mixin/ScreenMixin.java deleted file mode 100644 index d5038a53..00000000 --- a/CustomPlayerModelsFabric-1.17/src/main/java/com/tom/cpm/mixin/ScreenMixin.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.tom.cpm.mixin; - -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; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.Element; -import net.minecraft.client.gui.screen.Screen; - -import com.tom.cpm.client.CustomPlayerModelsClient; -import com.tom.cpm.client.CustomPlayerModelsClient.IScreen; - -@Mixin(Screen.class) -public abstract class ScreenMixin implements IScreen { - - protected @Shadow abstract Element addDrawableChild(Element drawableElement); - - @Inject(at = @At("RETURN"), method = "init(Lnet/minecraft/client/MinecraftClient;II)V") - public void onInit(MinecraftClient client, int width, int height, CallbackInfo cbi) { - CustomPlayerModelsClient.INSTANCE.initGui((Screen)(Object)this); - } - - @Override - public void cpm$addDrawableChild(Element drawableElement) { - addDrawableChild(drawableElement); - } -} diff --git a/CustomPlayerModelsFabric-1.17/src/main/resources/cpm.mixins.json b/CustomPlayerModelsFabric-1.17/src/main/resources/cpm.mixins.json index c2619736..b55b35c2 100644 --- a/CustomPlayerModelsFabric-1.17/src/main/resources/cpm.mixins.json +++ b/CustomPlayerModelsFabric-1.17/src/main/resources/cpm.mixins.json @@ -9,7 +9,6 @@ ], "client": [ "PlayerRendererMixin", - "ScreenMixin", "MinecraftClientMixin", "SkullBlockEntityRendererMixin", "BuiltinModelItemRendererMixin", diff --git a/CustomPlayerModelsFabric-1.18/gradle.properties b/CustomPlayerModelsFabric-1.18/gradle.properties index 6927e225..662caf69 100644 --- a/CustomPlayerModelsFabric-1.18/gradle.properties +++ b/CustomPlayerModelsFabric-1.18/gradle.properties @@ -11,6 +11,6 @@ loader_version=0.14.6 fabric_version=0.53.4+1.18.2 # Mod Properties -mod_version=0.4.8a +mod_version=0.5.0a maven_group = com.tom archives_base_name = CustomPlayerModels-Fabric-1.18 diff --git a/CustomPlayerModelsFabric-1.18/src/main/java/com/tom/cpm/client/CustomPlayerModelsClient.java b/CustomPlayerModelsFabric-1.18/src/main/java/com/tom/cpm/client/CustomPlayerModelsClient.java index ea68d353..e0ecde78 100644 --- a/CustomPlayerModelsFabric-1.18/src/main/java/com/tom/cpm/client/CustomPlayerModelsClient.java +++ b/CustomPlayerModelsFabric-1.18/src/main/java/com/tom/cpm/client/CustomPlayerModelsClient.java @@ -1,14 +1,13 @@ package com.tom.cpm.client; -import java.util.Map.Entry; import java.util.function.Consumer; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents; +import net.fabricmc.fabric.api.client.screen.v1.Screens; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.Element; -import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.TitleScreen; import net.minecraft.client.gui.screen.option.SkinOptionsScreen; import net.minecraft.client.gui.widget.ButtonWidget; @@ -16,7 +15,6 @@ import net.minecraft.client.network.AbstractClientPlayerEntity; import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.client.option.KeyBinding; import net.minecraft.client.render.OverlayTexture; import net.minecraft.client.render.RenderLayer; import net.minecraft.client.render.Shader; @@ -92,10 +90,14 @@ public void onInitializeClient() { Player.setEnableRendering(!Player.isEnableRendering()); } - for (Entry e : KeyBindings.quickAccess.entrySet()) { - if(e.getValue().wasPressed()) { - mc.getPlayerRenderManager().getAnimationEngine().onKeybind(e.getKey()); - } + mc.getPlayerRenderManager().getAnimationEngine().updateKeys(KeyBindings.quickAccess); + }); + ScreenEvents.AFTER_INIT.register((mc, screen, sw, sh) -> { + ScreenEvents.beforeRender(screen).register((_1, _2, _3, _4, _5) -> PlayerProfile.inGui = true); + ScreenEvents.afterRender(screen).register((_1, _2, _3, _4, _5) -> PlayerProfile.inGui = false); + if((screen instanceof TitleScreen && ModConfig.getCommonConfig().getSetBoolean(ConfigKeys.TITLE_SCREEN_BUTTON, true)) || + screen instanceof SkinOptionsScreen) { + Screens.getButtons(screen).add(new Button(0, 0, () -> MinecraftClient.getInstance().setScreen(new Gui(EditorGui::new, screen)))); } }); manager = new RenderManager<>(mc.getPlayerRenderManager(), mc.getDefinitionLoader(), PlayerEntity::getGameProfile); @@ -128,18 +130,6 @@ public void playerRenderPost(VertexConsumerProvider buffer, PlayerEntityModel mo manager.unbindClear(model); } - public void initGui(Screen screen) { - if((screen instanceof TitleScreen && ModConfig.getCommonConfig().getSetBoolean(ConfigKeys.TITLE_SCREEN_BUTTON, true)) || - screen instanceof SkinOptionsScreen) { - Button btn = new Button(0, 0, () -> MinecraftClient.getInstance().setScreen(new Gui(EditorGui::new, screen))); - ((IScreen)screen).cpm$addDrawableChild(btn); - } - } - - public static interface IScreen { - void cpm$addDrawableChild(Element drawableElement); - } - public void renderHand(VertexConsumerProvider buffer, PlayerEntityModel model) { manager.bindHand(MinecraftClient.getInstance().player, buffer, model); } diff --git a/CustomPlayerModelsFabric-1.18/src/main/java/com/tom/cpm/client/KeyBindings.java b/CustomPlayerModelsFabric-1.18/src/main/java/com/tom/cpm/client/KeyBindings.java index 66778889..d441324a 100644 --- a/CustomPlayerModelsFabric-1.18/src/main/java/com/tom/cpm/client/KeyBindings.java +++ b/CustomPlayerModelsFabric-1.18/src/main/java/com/tom/cpm/client/KeyBindings.java @@ -1,9 +1,7 @@ package com.tom.cpm.client; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.lwjgl.glfw.GLFW; @@ -16,7 +14,8 @@ public class KeyBindings implements IKeybind { public static KeyBinding gestureMenuBinding, renderToggleBinding; - public static Map quickAccess = new HashMap<>(); + public static IKeybind[] quickAccess = new IKeybind[IKeybind.QUICK_ACCESS_KEYBINDS_COUNT]; + public static void init() { gestureMenuBinding = new KeyBinding("key.cpm.gestureMenu", GLFW.GLFW_KEY_G, "key.cpm.category"); kbs.add(new KeyBindings(gestureMenuBinding, "gestureMenu")); @@ -24,14 +23,15 @@ public static void init() { renderToggleBinding = new KeyBinding("key.cpm.renderToggle", InputUtil.UNKNOWN_KEY.getCode(), "key.cpm.category"); kbs.add(new KeyBindings(renderToggleBinding, "renderToggle")); - for(int i = 1;i<=6;i++) + for(int i = 1;i<=IKeybind.QUICK_ACCESS_KEYBINDS_COUNT;i++) createQA(i); } private static void createQA(int id) { KeyBinding kb = new KeyBinding("key.cpm.qa_" + id, InputUtil.UNKNOWN_KEY.getCode(), "key.cpm.category"); - kbs.add(new KeyBindings(kb, "qa_" + id)); - quickAccess.put(id, kb); + KeyBindings kbs = new KeyBindings(kb, "qa_" + id); + KeyBindings.kbs.add(kbs); + quickAccess[id - 1] = kbs; } public static List kbs = new ArrayList<>(); @@ -58,4 +58,9 @@ public String getBoundKey() { public String getName() { return name; } + + @Override + public boolean isPressed() { + return kb.isPressed(); + } } diff --git a/CustomPlayerModelsFabric-1.18/src/main/java/com/tom/cpm/client/PlayerProfile.java b/CustomPlayerModelsFabric-1.18/src/main/java/com/tom/cpm/client/PlayerProfile.java index a4e93f93..93213caa 100644 --- a/CustomPlayerModelsFabric-1.18/src/main/java/com/tom/cpm/client/PlayerProfile.java +++ b/CustomPlayerModelsFabric-1.18/src/main/java/com/tom/cpm/client/PlayerProfile.java @@ -1,9 +1,13 @@ package com.tom.cpm.client; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; import java.util.Map; import java.util.UUID; import java.util.concurrent.CompletableFuture; +import java.util.function.BooleanSupplier; +import net.fabricmc.loader.api.FabricLoader; import net.minecraft.block.AbstractSkullBlock; import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.entity.PlayerModelPart; @@ -34,6 +38,27 @@ import com.tom.cpm.shared.skin.PlayerTextureLoader; public class PlayerProfile extends Player { + public static boolean inGui; + public static BooleanSupplier inFirstPerson; + static { + inFirstPerson = () -> false; + if(FabricLoader.getInstance().isModLoaded("firstperson")) { + try { + MethodHandle h = MethodHandles.lookup().unreflectGetter(Class.forName("dev.tr7zw.firstperson.FirstPersonModelCore").getDeclaredField("isRenderingPlayer")); + inFirstPerson = () -> { + try { + return (boolean) h.invoke(); + } catch (Throwable e) { + inFirstPerson = () -> false; + return false; + } + }; + inFirstPerson.getAsBoolean(); + } catch (Throwable e) { + } + } + } + private final GameProfile profile; private String skinType; @@ -181,6 +206,8 @@ public void updateFromPlayer(PlayerEntity player) { animState.isOnLadder = player.isClimbing(); animState.isBurning = player.isOnFire(); animState.isFreezing = player.getFrozenTicks() > 0; + animState.inGui = inGui; + animState.firstPersonMod = inFirstPerson.getAsBoolean(); if(player.getActiveItem().getItem() instanceof CrossbowItem) { float f = CrossbowItem.getPullTime(player.getActiveItem()); diff --git a/CustomPlayerModelsFabric-1.18/src/main/java/com/tom/cpm/client/VBufferOut.java b/CustomPlayerModelsFabric-1.18/src/main/java/com/tom/cpm/client/VBufferOut.java index f994ce56..23cba8cb 100644 --- a/CustomPlayerModelsFabric-1.18/src/main/java/com/tom/cpm/client/VBufferOut.java +++ b/CustomPlayerModelsFabric-1.18/src/main/java/com/tom/cpm/client/VBufferOut.java @@ -15,8 +15,8 @@ public class VBufferOut implements BufferOutput { public VBufferOut(int light, int overlay, MatrixStack matrixStackIn) { this.light = light; this.overlay = overlay; - mat4 = matrixStackIn.peek().getPositionMatrix(); - mat3 = matrixStackIn.peek().getNormalMatrix(); + mat4 = new Matrix4f(matrixStackIn.peek().getPositionMatrix()); + mat3 = new Matrix3f(matrixStackIn.peek().getNormalMatrix()); } @Override diff --git a/CustomPlayerModelsFabric-1.18/src/main/java/com/tom/cpm/mixin/PlayerRendererMixin.java b/CustomPlayerModelsFabric-1.18/src/main/java/com/tom/cpm/mixin/PlayerRendererMixin.java index fc6db57c..0883f367 100644 --- a/CustomPlayerModelsFabric-1.18/src/main/java/com/tom/cpm/mixin/PlayerRendererMixin.java +++ b/CustomPlayerModelsFabric-1.18/src/main/java/com/tom/cpm/mixin/PlayerRendererMixin.java @@ -101,8 +101,15 @@ public RenderLayer getArmLayer(Identifier loc, MatrixStack matrices, VertexConsu } @Inject(at = @At("HEAD"), method = "renderLabelIfPresent(Lnet/minecraft/client/network/AbstractClientPlayerEntity;Lnet/minecraft/text/Text;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;I)V", cancellable = true) - public void onRenderName(AbstractClientPlayerEntity entityIn, Text displayNameIn, MatrixStack matrixStackIn, VertexConsumerProvider bufferIn, int packedLightIn, CallbackInfo cbi) { + public void onRenderName1(AbstractClientPlayerEntity entityIn, Text displayNameIn, MatrixStack matrixStackIn, VertexConsumerProvider bufferIn, int packedLightIn, CallbackInfo cbi) { if(!Player.isEnableNames())cbi.cancel(); + } + + @Inject(at = @At(value = "INVOKE", + target = "Lnet/minecraft/client/render/entity/LivingEntityRenderer;renderLabelIfPresent(Lnet/minecraft/entity/Entity;Lnet/minecraft/text/Text;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;I)V", + ordinal = 1), + method = "renderLabelIfPresent(Lnet/minecraft/client/network/AbstractClientPlayerEntity;Lnet/minecraft/text/Text;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;I)V") + public void onRenderName2(AbstractClientPlayerEntity entityIn, Text displayNameIn, MatrixStack matrixStackIn, VertexConsumerProvider bufferIn, int packedLightIn, CallbackInfo cbi) { if(Player.isEnableLoadingInfo()) CustomPlayerModelsClient.renderNameTag(this, entityIn, entityIn.getGameProfile(), ModelDefinitionLoader.PLAYER_UNIQUE, matrixStackIn, bufferIn, packedLightIn); } diff --git a/CustomPlayerModelsFabric-1.18/src/main/java/com/tom/cpm/mixin/ScreenMixin.java b/CustomPlayerModelsFabric-1.18/src/main/java/com/tom/cpm/mixin/ScreenMixin.java deleted file mode 100644 index d5038a53..00000000 --- a/CustomPlayerModelsFabric-1.18/src/main/java/com/tom/cpm/mixin/ScreenMixin.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.tom.cpm.mixin; - -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; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.Element; -import net.minecraft.client.gui.screen.Screen; - -import com.tom.cpm.client.CustomPlayerModelsClient; -import com.tom.cpm.client.CustomPlayerModelsClient.IScreen; - -@Mixin(Screen.class) -public abstract class ScreenMixin implements IScreen { - - protected @Shadow abstract Element addDrawableChild(Element drawableElement); - - @Inject(at = @At("RETURN"), method = "init(Lnet/minecraft/client/MinecraftClient;II)V") - public void onInit(MinecraftClient client, int width, int height, CallbackInfo cbi) { - CustomPlayerModelsClient.INSTANCE.initGui((Screen)(Object)this); - } - - @Override - public void cpm$addDrawableChild(Element drawableElement) { - addDrawableChild(drawableElement); - } -} diff --git a/CustomPlayerModelsFabric-1.18/src/main/resources/cpm.mixins.json b/CustomPlayerModelsFabric-1.18/src/main/resources/cpm.mixins.json index cf1d08a1..b89950a4 100644 --- a/CustomPlayerModelsFabric-1.18/src/main/resources/cpm.mixins.json +++ b/CustomPlayerModelsFabric-1.18/src/main/resources/cpm.mixins.json @@ -9,7 +9,6 @@ ], "client": [ "PlayerRendererMixin", - "ScreenMixin", "MinecraftClientMixin", "SkullBlockEntityRendererMixin", "BuiltinModelItemRendererMixin", diff --git a/CustomPlayerModelsFabric-1.19/gradle.properties b/CustomPlayerModelsFabric-1.19/gradle.properties index 9aba0e7b..af2bda4a 100644 --- a/CustomPlayerModelsFabric-1.19/gradle.properties +++ b/CustomPlayerModelsFabric-1.19/gradle.properties @@ -4,13 +4,13 @@ org.gradle.jvmargs=-Xmx1G # Fabric Properties # check these on https://fabricmc.net/use minecraft_version=1.19.2 -yarn_mappings=1.19.2+build.4 +yarn_mappings=1.19.2+build.8 loader_version=0.14.9 #Fabric api -fabric_version=0.59.0+1.19.2 +fabric_version=0.60.0+1.19.2 # Mod Properties -mod_version=0.4.8a +mod_version=0.5.0a maven_group = com.tom archives_base_name = CustomPlayerModels-Fabric-1.19 diff --git a/CustomPlayerModelsFabric-1.19/src/main/java/com/tom/cpm/client/CustomPlayerModelsClient.java b/CustomPlayerModelsFabric-1.19/src/main/java/com/tom/cpm/client/CustomPlayerModelsClient.java index 8ce04578..f3b1d1ed 100644 --- a/CustomPlayerModelsFabric-1.19/src/main/java/com/tom/cpm/client/CustomPlayerModelsClient.java +++ b/CustomPlayerModelsFabric-1.19/src/main/java/com/tom/cpm/client/CustomPlayerModelsClient.java @@ -1,14 +1,13 @@ package com.tom.cpm.client; -import java.util.Map.Entry; import java.util.function.Consumer; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents; +import net.fabricmc.fabric.api.client.screen.v1.Screens; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.Element; -import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.TitleScreen; import net.minecraft.client.gui.screen.option.SkinOptionsScreen; import net.minecraft.client.gui.widget.ButtonWidget; @@ -16,7 +15,6 @@ import net.minecraft.client.network.AbstractClientPlayerEntity; import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.client.option.KeyBinding; import net.minecraft.client.render.OverlayTexture; import net.minecraft.client.render.RenderLayer; import net.minecraft.client.render.Shader; @@ -91,10 +89,14 @@ public void onInitializeClient() { Player.setEnableRendering(!Player.isEnableRendering()); } - for (Entry e : KeyBindings.quickAccess.entrySet()) { - if(e.getValue().wasPressed()) { - mc.getPlayerRenderManager().getAnimationEngine().onKeybind(e.getKey()); - } + mc.getPlayerRenderManager().getAnimationEngine().updateKeys(KeyBindings.quickAccess); + }); + ScreenEvents.AFTER_INIT.register((mc, screen, sw, sh) -> { + ScreenEvents.beforeRender(screen).register((_1, _2, _3, _4, _5) -> PlayerProfile.inGui = true); + ScreenEvents.afterRender(screen).register((_1, _2, _3, _4, _5) -> PlayerProfile.inGui = false); + if((screen instanceof TitleScreen && ModConfig.getCommonConfig().getSetBoolean(ConfigKeys.TITLE_SCREEN_BUTTON, true)) || + screen instanceof SkinOptionsScreen) { + Screens.getButtons(screen).add(new Button(0, 0, () -> MinecraftClient.getInstance().setScreen(new Gui(EditorGui::new, screen)))); } }); manager = new RenderManager<>(mc.getPlayerRenderManager(), mc.getDefinitionLoader(), PlayerEntity::getGameProfile); @@ -127,18 +129,6 @@ public void playerRenderPost(VertexConsumerProvider buffer, PlayerEntityModel mo manager.unbindClear(model); } - public void initGui(Screen screen) { - if((screen instanceof TitleScreen && ModConfig.getCommonConfig().getSetBoolean(ConfigKeys.TITLE_SCREEN_BUTTON, true)) || - screen instanceof SkinOptionsScreen) { - Button btn = new Button(0, 0, () -> MinecraftClient.getInstance().setScreen(new Gui(EditorGui::new, screen))); - ((IScreen)screen).cpm$addDrawableChild(btn); - } - } - - public static interface IScreen { - void cpm$addDrawableChild(Element drawableElement); - } - public void renderHand(VertexConsumerProvider buffer, PlayerEntityModel model) { manager.bindHand(MinecraftClient.getInstance().player, buffer, model); } diff --git a/CustomPlayerModelsFabric-1.19/src/main/java/com/tom/cpm/client/KeyBindings.java b/CustomPlayerModelsFabric-1.19/src/main/java/com/tom/cpm/client/KeyBindings.java index 66778889..d441324a 100644 --- a/CustomPlayerModelsFabric-1.19/src/main/java/com/tom/cpm/client/KeyBindings.java +++ b/CustomPlayerModelsFabric-1.19/src/main/java/com/tom/cpm/client/KeyBindings.java @@ -1,9 +1,7 @@ package com.tom.cpm.client; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.lwjgl.glfw.GLFW; @@ -16,7 +14,8 @@ public class KeyBindings implements IKeybind { public static KeyBinding gestureMenuBinding, renderToggleBinding; - public static Map quickAccess = new HashMap<>(); + public static IKeybind[] quickAccess = new IKeybind[IKeybind.QUICK_ACCESS_KEYBINDS_COUNT]; + public static void init() { gestureMenuBinding = new KeyBinding("key.cpm.gestureMenu", GLFW.GLFW_KEY_G, "key.cpm.category"); kbs.add(new KeyBindings(gestureMenuBinding, "gestureMenu")); @@ -24,14 +23,15 @@ public static void init() { renderToggleBinding = new KeyBinding("key.cpm.renderToggle", InputUtil.UNKNOWN_KEY.getCode(), "key.cpm.category"); kbs.add(new KeyBindings(renderToggleBinding, "renderToggle")); - for(int i = 1;i<=6;i++) + for(int i = 1;i<=IKeybind.QUICK_ACCESS_KEYBINDS_COUNT;i++) createQA(i); } private static void createQA(int id) { KeyBinding kb = new KeyBinding("key.cpm.qa_" + id, InputUtil.UNKNOWN_KEY.getCode(), "key.cpm.category"); - kbs.add(new KeyBindings(kb, "qa_" + id)); - quickAccess.put(id, kb); + KeyBindings kbs = new KeyBindings(kb, "qa_" + id); + KeyBindings.kbs.add(kbs); + quickAccess[id - 1] = kbs; } public static List kbs = new ArrayList<>(); @@ -58,4 +58,9 @@ public String getBoundKey() { public String getName() { return name; } + + @Override + public boolean isPressed() { + return kb.isPressed(); + } } diff --git a/CustomPlayerModelsFabric-1.19/src/main/java/com/tom/cpm/client/PlayerProfile.java b/CustomPlayerModelsFabric-1.19/src/main/java/com/tom/cpm/client/PlayerProfile.java index a4e93f93..93213caa 100644 --- a/CustomPlayerModelsFabric-1.19/src/main/java/com/tom/cpm/client/PlayerProfile.java +++ b/CustomPlayerModelsFabric-1.19/src/main/java/com/tom/cpm/client/PlayerProfile.java @@ -1,9 +1,13 @@ package com.tom.cpm.client; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; import java.util.Map; import java.util.UUID; import java.util.concurrent.CompletableFuture; +import java.util.function.BooleanSupplier; +import net.fabricmc.loader.api.FabricLoader; import net.minecraft.block.AbstractSkullBlock; import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.entity.PlayerModelPart; @@ -34,6 +38,27 @@ import com.tom.cpm.shared.skin.PlayerTextureLoader; public class PlayerProfile extends Player { + public static boolean inGui; + public static BooleanSupplier inFirstPerson; + static { + inFirstPerson = () -> false; + if(FabricLoader.getInstance().isModLoaded("firstperson")) { + try { + MethodHandle h = MethodHandles.lookup().unreflectGetter(Class.forName("dev.tr7zw.firstperson.FirstPersonModelCore").getDeclaredField("isRenderingPlayer")); + inFirstPerson = () -> { + try { + return (boolean) h.invoke(); + } catch (Throwable e) { + inFirstPerson = () -> false; + return false; + } + }; + inFirstPerson.getAsBoolean(); + } catch (Throwable e) { + } + } + } + private final GameProfile profile; private String skinType; @@ -181,6 +206,8 @@ public void updateFromPlayer(PlayerEntity player) { animState.isOnLadder = player.isClimbing(); animState.isBurning = player.isOnFire(); animState.isFreezing = player.getFrozenTicks() > 0; + animState.inGui = inGui; + animState.firstPersonMod = inFirstPerson.getAsBoolean(); if(player.getActiveItem().getItem() instanceof CrossbowItem) { float f = CrossbowItem.getPullTime(player.getActiveItem()); diff --git a/CustomPlayerModelsFabric-1.19/src/main/java/com/tom/cpm/client/VBufferOut.java b/CustomPlayerModelsFabric-1.19/src/main/java/com/tom/cpm/client/VBufferOut.java index f994ce56..23cba8cb 100644 --- a/CustomPlayerModelsFabric-1.19/src/main/java/com/tom/cpm/client/VBufferOut.java +++ b/CustomPlayerModelsFabric-1.19/src/main/java/com/tom/cpm/client/VBufferOut.java @@ -15,8 +15,8 @@ public class VBufferOut implements BufferOutput { public VBufferOut(int light, int overlay, MatrixStack matrixStackIn) { this.light = light; this.overlay = overlay; - mat4 = matrixStackIn.peek().getPositionMatrix(); - mat3 = matrixStackIn.peek().getNormalMatrix(); + mat4 = new Matrix4f(matrixStackIn.peek().getPositionMatrix()); + mat3 = new Matrix3f(matrixStackIn.peek().getNormalMatrix()); } @Override diff --git a/CustomPlayerModelsFabric-1.19/src/main/java/com/tom/cpm/mixin/ArmorFeatureRendererMixin.java b/CustomPlayerModelsFabric-1.19/src/main/java/com/tom/cpm/mixin/ArmorFeatureRendererMixin.java index 6399672c..5510e4a0 100644 --- a/CustomPlayerModelsFabric-1.19/src/main/java/com/tom/cpm/mixin/ArmorFeatureRendererMixin.java +++ b/CustomPlayerModelsFabric-1.19/src/main/java/com/tom/cpm/mixin/ArmorFeatureRendererMixin.java @@ -29,8 +29,8 @@ public ArmorFeatureRendererMixin(FeatureRendererContext leggingsModel; - private @Final @Shadow BipedEntityModel bodyModel; + private @Final @Shadow BipedEntityModel innerModel; + private @Final @Shadow BipedEntityModel outerModel; @Shadow abstract Identifier getArmorTexture(ArmorItem armorItem, boolean bl, String string); @@ -38,15 +38,15 @@ public ArmorFeatureRendererMixin(FeatureRendererContext model, boolean bl2, float f, float g, float h, String string, CallbackInfo cbi) { - CustomPlayerModelsClient.mc.getPlayerRenderManager().bindSkin(model, new ModelTexture(this.getArmorTexture(armorItem, bl2, string), PlayerRenderManager.armor), model == leggingsModel ? TextureSheetType.ARMOR2 : TextureSheetType.ARMOR1); + CustomPlayerModelsClient.mc.getPlayerRenderManager().bindSkin(model, new ModelTexture(this.getArmorTexture(armorItem, bl2, string), PlayerRenderManager.armor), model == innerModel ? TextureSheetType.ARMOR2 : TextureSheetType.ARMOR1); } @Inject(at = @At("HEAD"), @@ -65,7 +65,7 @@ private void preRenderTexture(MatrixStack matrixStack, VertexConsumerProvider ve + "ZLnet/minecraft/class_572;FFFLnet/minecraft/class_2960;)V"}, remap = false, require = 0)//Optifine private void preRenderTexture(MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int p_241738_3_, boolean p_241738_5_, BipedEntityModel model, float p_241738_8_, float p_241738_9_, float p_241738_10_, Identifier resLoc, CallbackInfo cbi) { - CustomPlayerModelsClient.mc.getPlayerRenderManager().bindSkin(model, new ModelTexture(resLoc, PlayerRenderManager.armor), model == leggingsModel ? TextureSheetType.ARMOR2 : TextureSheetType.ARMOR1); + CustomPlayerModelsClient.mc.getPlayerRenderManager().bindSkin(model, new ModelTexture(resLoc, PlayerRenderManager.armor), model == innerModel ? TextureSheetType.ARMOR2 : TextureSheetType.ARMOR1); } @Inject(at = @At("HEAD"), @@ -75,6 +75,6 @@ private void preRenderTexture(MatrixStack matrixStack, VertexConsumerProvider ve + "ZLnet/minecraft/class_3879;FFFLnet/minecraft/class_2960;)V"}, remap = false, require = 0)//Optifine private void preRenderTexture(MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int p_241738_3_, boolean p_241738_5_, net.minecraft.client.model.Model model, float p_241738_8_, float p_241738_9_, float p_241738_10_, Identifier resLoc, CallbackInfo cbi) { - CustomPlayerModelsClient.mc.getPlayerRenderManager().bindSkin(model, new ModelTexture(resLoc, PlayerRenderManager.armor), model == leggingsModel ? TextureSheetType.ARMOR2 : TextureSheetType.ARMOR1); + CustomPlayerModelsClient.mc.getPlayerRenderManager().bindSkin(model, new ModelTexture(resLoc, PlayerRenderManager.armor), model == innerModel ? TextureSheetType.ARMOR2 : TextureSheetType.ARMOR1); } } diff --git a/CustomPlayerModelsFabric-1.19/src/main/java/com/tom/cpm/mixin/PlayerRendererMixin.java b/CustomPlayerModelsFabric-1.19/src/main/java/com/tom/cpm/mixin/PlayerRendererMixin.java index fc6db57c..0883f367 100644 --- a/CustomPlayerModelsFabric-1.19/src/main/java/com/tom/cpm/mixin/PlayerRendererMixin.java +++ b/CustomPlayerModelsFabric-1.19/src/main/java/com/tom/cpm/mixin/PlayerRendererMixin.java @@ -101,8 +101,15 @@ public RenderLayer getArmLayer(Identifier loc, MatrixStack matrices, VertexConsu } @Inject(at = @At("HEAD"), method = "renderLabelIfPresent(Lnet/minecraft/client/network/AbstractClientPlayerEntity;Lnet/minecraft/text/Text;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;I)V", cancellable = true) - public void onRenderName(AbstractClientPlayerEntity entityIn, Text displayNameIn, MatrixStack matrixStackIn, VertexConsumerProvider bufferIn, int packedLightIn, CallbackInfo cbi) { + public void onRenderName1(AbstractClientPlayerEntity entityIn, Text displayNameIn, MatrixStack matrixStackIn, VertexConsumerProvider bufferIn, int packedLightIn, CallbackInfo cbi) { if(!Player.isEnableNames())cbi.cancel(); + } + + @Inject(at = @At(value = "INVOKE", + target = "Lnet/minecraft/client/render/entity/LivingEntityRenderer;renderLabelIfPresent(Lnet/minecraft/entity/Entity;Lnet/minecraft/text/Text;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;I)V", + ordinal = 1), + method = "renderLabelIfPresent(Lnet/minecraft/client/network/AbstractClientPlayerEntity;Lnet/minecraft/text/Text;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;I)V") + public void onRenderName2(AbstractClientPlayerEntity entityIn, Text displayNameIn, MatrixStack matrixStackIn, VertexConsumerProvider bufferIn, int packedLightIn, CallbackInfo cbi) { if(Player.isEnableLoadingInfo()) CustomPlayerModelsClient.renderNameTag(this, entityIn, entityIn.getGameProfile(), ModelDefinitionLoader.PLAYER_UNIQUE, matrixStackIn, bufferIn, packedLightIn); } diff --git a/CustomPlayerModelsFabric-1.19/src/main/java/com/tom/cpm/mixin/ScreenMixin.java b/CustomPlayerModelsFabric-1.19/src/main/java/com/tom/cpm/mixin/ScreenMixin.java deleted file mode 100644 index d5038a53..00000000 --- a/CustomPlayerModelsFabric-1.19/src/main/java/com/tom/cpm/mixin/ScreenMixin.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.tom.cpm.mixin; - -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; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.Element; -import net.minecraft.client.gui.screen.Screen; - -import com.tom.cpm.client.CustomPlayerModelsClient; -import com.tom.cpm.client.CustomPlayerModelsClient.IScreen; - -@Mixin(Screen.class) -public abstract class ScreenMixin implements IScreen { - - protected @Shadow abstract Element addDrawableChild(Element drawableElement); - - @Inject(at = @At("RETURN"), method = "init(Lnet/minecraft/client/MinecraftClient;II)V") - public void onInit(MinecraftClient client, int width, int height, CallbackInfo cbi) { - CustomPlayerModelsClient.INSTANCE.initGui((Screen)(Object)this); - } - - @Override - public void cpm$addDrawableChild(Element drawableElement) { - addDrawableChild(drawableElement); - } -} diff --git a/CustomPlayerModelsFabric-1.19/src/main/resources/cpm.mixins.json b/CustomPlayerModelsFabric-1.19/src/main/resources/cpm.mixins.json index cf1d08a1..b89950a4 100644 --- a/CustomPlayerModelsFabric-1.19/src/main/resources/cpm.mixins.json +++ b/CustomPlayerModelsFabric-1.19/src/main/resources/cpm.mixins.json @@ -9,7 +9,6 @@ ], "client": [ "PlayerRendererMixin", - "ScreenMixin", "MinecraftClientMixin", "SkullBlockEntityRendererMixin", "BuiltinModelItemRendererMixin", diff --git a/Localization/en_us.lang b/Localization/en_us.lang index cb4c53a0..b10ae385 100644 --- a/Localization/en_us.lang +++ b/Localization/en_us.lang @@ -261,7 +261,7 @@ tooltip.cpm.tree.scaling.mob_visibility=Mob Detection Distance Scale\Customizabl tooltip.cpm.animType.pose.freezing=Freezing in powdered snow (1.17+) tooltip.cpm.animType.pose.speaking=Requires compatible voice chat mod\Animation frame depends on sound loudness tooltip.cpm.pluginGenerator=%s\Added by: %s -tooltip.cpm.gestureQuickAccess=Bind Quick Access keys in the Options/Controls menu\hover over the gesture/pose and press the button to bind. +tooltip.cpm.gestureQuickAccess=Bind Quick Access keys in the Options/Controls menu\hover over the gesture/pose and press the button to bind.\Hold Ctrl to enable hold to play mode.\This mode will play the selected pose/looping gesture while you hold the button. tooltip.cpm.config.showLoadingInfo=Show model loading status above the players' heads. tooltip.cpm.copyTransform=Copy element position, rotation, and scale\Right click on the part to edit the effect later. tooltip.cpm.config.advScalingSettings=Always enable advanced scaling settings. @@ -280,6 +280,13 @@ tooltip.cpm.config.editorGizmoScale=Scale the Gizmo to your current zoom. tooltip.cpm.config.editorGizmoSize=Gizmo width multiplier tooltip.cpm.config.editorGizmoLength=Gizmo length multiplier tooltip.cpm.config.editorAutosaveTime=Time interval between auto-saves.\Set it to -1 to disable. +tooltip.cpm.gestureButton=%s\Keybind: %s +tooltip.cpm.gestureButton.mode=%s\Keybind: %s\Mode: %s +tooltip.cpm.animType.pose.opt_layer=Custom Layer\Can be toggled using the Gestures menu\Requires server-side mod +tooltip.cpm.animType.pose.opt_value=Custom Value Layer\Value can be changed using the Gestures menu\Value defines the progress through the frames\Requires server-side mod +tooltip.cpm.animType.pose.in_gui=When your model is rendered inside a Menu (Inventory Menu) +tooltip.cpm.animType.pose.first_person_mod=When your model is rendered in first person\with the First Person Model mod installed. +tooltip.cpm.config.gestureAutoReset=Deactivate gestures after the animation finishes tab.cpm.model=Model tab.cpm.texture=Texture @@ -659,6 +666,16 @@ label.cpm.openURL.title=Open URL label.cpm.openURL.text=Are you sure you want to open the following website?\%s\Never open links that you don't trust! label.cpm.config.wikiOfflineMode=Wiki Offline Mode label.cpm.config.editorAutosaveTime=Auto-save interval: %ss +label.cpm.gestureMode.press=Activate on Press +label.cpm.gestureMode.hold=Play While holding +label.cpm.quick_key_info=Hold Ctrl to change play mode +label.cpm.quick_key_short=Bindings +label.cpm.new_anim_layer=New Toggle Layer +label.cpm.customLayers=Custom Layers +label.cpm.anim_layer=Layer: %s +label.cpm.new_anim_value=New Value Layer +label.cpm.anim_value=Value Layer: %s +label.cpm.config.gestureAutoReset=Gesture Auto-Reset label.cpm.paste.connecting.title=Connecting... label.cpm.paste.connecting.message=Connecting to paste site... @@ -745,6 +762,8 @@ label.cpm.pose.climbing_on_ladder=Climbing on Ladder label.cpm.pose.speaking=Speaking label.cpm.pose.toot_horn_left=Tooting Goat Horn Left label.cpm.pose.toot_horn_right=Tooting Goat Horn Right +label.cpm.pose.in_gui=Display In Menu +label.cpm.pose.first_person_mod=First Person Model View label.cpm.dir.up=Up label.cpm.dir.down=Down diff --git a/Localization/start.json b/Localization/start.json index d435c180..1c571fbb 100644 --- a/Localization/start.json +++ b/Localization/start.json @@ -259,7 +259,7 @@ "tooltip.cpm.animType.pose.freezing": "Freezing in powdered snow (1.17+)", "tooltip.cpm.animType.pose.speaking": "Requires compatible voice chat mod\\Animation frame depends on sound loudness", "tooltip.cpm.pluginGenerator": "%s\\Added by: %s", - "tooltip.cpm.gestureQuickAccess": "Bind Quick Access keys in the Options/Controls menu\\hover over the gesture/pose and press the button to bind.", + "tooltip.cpm.gestureQuickAccess": "Bind Quick Access keys in the Options/Controls menu\\hover over the gesture/pose and press the button to bind.\\Hold Ctrl to enable hold to play mode.\\This mode will play the selected pose/looping gesture while you hold the button.", "tooltip.cpm.config.showLoadingInfo": "Show model loading status above the players\u0027 heads.", "tooltip.cpm.copyTransform": "Copy element position, rotation, and scale\\Right click on the part to edit the effect later.", "tooltip.cpm.config.advScalingSettings": "Always enable advanced scaling settings.", @@ -278,6 +278,13 @@ "tooltip.cpm.config.editorGizmoSize": "Gizmo width multiplier", "tooltip.cpm.config.editorGizmoLength": "Gizmo length multiplier", "tooltip.cpm.config.editorAutosaveTime": "Time interval between auto-saves.\\Set it to -1 to disable.", + "tooltip.cpm.gestureButton": "%s\\Keybind: %s", + "tooltip.cpm.gestureButton.mode": "%s\\Keybind: %s\\Mode: %s", + "tooltip.cpm.animType.pose.opt_layer": "Custom Layer\\Can be toggled using the Gestures menu\\Requires server-side mod", + "tooltip.cpm.animType.pose.opt_value": "Custom Value Layer\\Value can be changed using the Gestures menu\\Value defines the progress through the frames\\Requires server-side mod", + "tooltip.cpm.animType.pose.in_gui": "When your model is rendered inside a Menu (Inventory Menu)", + "tooltip.cpm.animType.pose.first_person_mod": "When your model is rendered in first person\\with the First Person Model mod installed.", + "tooltip.cpm.config.gestureAutoReset": "Deactivate gestures after the animation finishes", "tab.cpm.model": "Model", "tab.cpm.texture": "Texture", "tab.cpm.animation": "Animations", @@ -655,6 +662,16 @@ "label.cpm.openURL.text": "Are you sure you want to open the following website?\\%s\\Never open links that you don\u0027t trust!", "label.cpm.config.wikiOfflineMode": "Wiki Offline Mode", "label.cpm.config.editorAutosaveTime": "Auto-save interval: %ss", + "label.cpm.gestureMode.press": "Activate on Press", + "label.cpm.gestureMode.hold": "Play While holding", + "label.cpm.quick_key_info": "Hold Ctrl to change play mode", + "label.cpm.quick_key_short": "Bindings", + "label.cpm.new_anim_layer": "New Toggle Layer", + "label.cpm.customLayers": "Custom Layers", + "label.cpm.anim_layer": "Layer: %s", + "label.cpm.new_anim_value": "New Value Layer", + "label.cpm.anim_value": "Value Layer: %s", + "label.cpm.config.gestureAutoReset": "Gesture Auto-Reset", "label.cpm.paste.connecting.title": "Connecting...", "label.cpm.paste.connecting.message": "Connecting to paste site...", "label.cpm.paste.listing": "Refreshing files list...", @@ -738,6 +755,8 @@ "label.cpm.pose.speaking": "Speaking", "label.cpm.pose.toot_horn_left": "Tooting Goat Horn Left", "label.cpm.pose.toot_horn_right": "Tooting Goat Horn Right", + "label.cpm.pose.in_gui": "Display In Menu", + "label.cpm.pose.first_person_mod": "First Person Model View", "label.cpm.dir.up": "Up", "label.cpm.dir.down": "Down", "label.cpm.dir.north": "North", diff --git a/Localization/zh_cn.json b/Localization/zh_cn.json index 21dd5d7d..47e2ecaf 100644 --- a/Localization/zh_cn.json +++ b/Localization/zh_cn.json @@ -259,7 +259,7 @@ "tooltip.cpm.animType.pose.freezing": "在细雪中结冰(1.17+)", "tooltip.cpm.animType.pose.speaking": "需要兼容的语音聊天模块\\动画帧取决于声音响度", "tooltip.cpm.pluginGenerator": "%s\\添加者:%s", - "tooltip.cpm.gestureQuickAccess": "在选项/控件菜单中绑定快速访问键\\将鼠标悬停在手势/姿势上,然后按下按钮进行绑定。", + "tooltip.cpm.gestureQuickAccess": "MODIFIED: 在选项/控件菜单中绑定快速访问键\\将鼠标悬停在手势/姿势上,然后按下按钮进行绑定。", "tooltip.cpm.config.showLoadingInfo": "在玩家头顶显示模型加载状态。", "tooltip.cpm.copyTransform": "复制元素位置、旋转和缩放\\在模型上单击鼠标右键,稍后编辑效果。", "tooltip.cpm.config.advScalingSettings": "始终启用高级缩放设置。", @@ -278,6 +278,13 @@ "tooltip.cpm.config.editorGizmoSize": "工具宽度乘数", "tooltip.cpm.config.editorGizmoLength": " 工具长度乘数", "tooltip.cpm.config.editorAutosaveTime": "自动保存之间的时间间隔。\\将其设置为 -1 以禁用。", + "tooltip.cpm.gestureButton": "UNLOCALIZED: %s\\Keybind: %s", + "tooltip.cpm.gestureButton.mode": "UNLOCALIZED: %s\\Keybind: %s\\Mode: %s", + "tooltip.cpm.animType.pose.opt_layer": "UNLOCALIZED: Custom Layer\\Can be toggled using the Gestures menu\\Requires server-side mod", + "tooltip.cpm.animType.pose.opt_value": "UNLOCALIZED: Custom Value Layer\\Value can be changed using the Gestures menu\\Value defines the progress through the frames\\Requires server-side mod", + "tooltip.cpm.animType.pose.in_gui": "UNLOCALIZED: When your model is rendered inside a Menu (Inventory Menu)", + "tooltip.cpm.animType.pose.first_person_mod": "UNLOCALIZED: When your model is rendered in first person\\with the First Person Model mod installed.", + "tooltip.cpm.config.gestureAutoReset": "UNLOCALIZED: Deactivate gestures after the animation finishes", "tab.cpm.model": "模型", "tab.cpm.texture": "纹理", "tab.cpm.animation": "动画", @@ -655,6 +662,16 @@ "label.cpm.openURL.text": "您确定要打开以下网站吗?\\%s\\切勿打开您不信任的链接!", "label.cpm.config.wikiOfflineMode": "维基离线模式", "label.cpm.config.editorAutosaveTime": "自动保存间隔:%ss", + "label.cpm.gestureMode.press": "UNLOCALIZED: Activate on Press", + "label.cpm.gestureMode.hold": "UNLOCALIZED: Play While holding", + "label.cpm.quick_key_info": "UNLOCALIZED: Hold Ctrl to change play mode", + "label.cpm.quick_key_short": "UNLOCALIZED: Bindings", + "label.cpm.new_anim_layer": "UNLOCALIZED: New Toggle Layer", + "label.cpm.customLayers": "UNLOCALIZED: Custom Layers", + "label.cpm.anim_layer": "UNLOCALIZED: Layer: %s", + "label.cpm.new_anim_value": "UNLOCALIZED: New Value Layer", + "label.cpm.anim_value": "UNLOCALIZED: Value Layer: %s", + "label.cpm.config.gestureAutoReset": "UNLOCALIZED: Gesture Auto-Reset", "label.cpm.paste.connecting.title": "连接...", "label.cpm.paste.connecting.message": "正在连接到粘贴站点...", "label.cpm.paste.listing": "正在刷新文件列表...", @@ -738,6 +755,8 @@ "label.cpm.pose.speaking": "潜行", "label.cpm.pose.toot_horn_left": "左手山羊角", "label.cpm.pose.toot_horn_right": "右手山羊角t", + "label.cpm.pose.in_gui": "UNLOCALIZED: Display In Menu", + "label.cpm.pose.first_person_mod": "UNLOCALIZED: First Person Model View", "label.cpm.dir.up": "上", "label.cpm.dir.down": "下", "label.cpm.dir.north": "北", @@ -794,7 +813,7 @@ "commands.cpm.kickWOMod.msg": "踢出消息", "commands.cpm.numberOutOfBounds": "输入的数字超出范围", "chat.cpm.skinForced": "换不了皮肤。 你的皮肤是服务器管理员强制设置的.", - "chat.cpm.serverSafetySettings": "MODIFIED: 服务器有推荐的安全设置。 打开手势菜单 [%s] 以编辑安全设置。", + "chat.cpm.serverSafetySettings": "[CPM] 服务器有推荐的安全设置。 打开手势菜单 [%s] 以编辑安全设置。", "chat.cpm.serverRequiresCPM": "服务器需要安装 CPM 并开启通讯。 当前“禁用服务器通信”设置设置为“true”,您将被踢出服务器。 打开手势菜单 [%s] 以编辑设置。 ", "chat.cpm.scalingBlocked": "[CPM] 某些缩放设置被阻止,请让管理员启用缩放。", "action.cpm.switch": "转换%s", diff --git a/Localization/zh_cn.version b/Localization/zh_cn.version index ed6ed3de..1350775a 100644 --- a/Localization/zh_cn.version +++ b/Localization/zh_cn.version @@ -791,7 +791,6 @@ "commands.cpm.kickWOMod.msg": "Kick message", "commands.cpm.numberOutOfBounds": "Entered numbers out of bounds", "chat.cpm.skinForced": "Can\u0027t change skin. Your skin was force set by the operators of the server.", - "chat.cpm.serverSafetySettings": "The server has recommended safety settings. Open the Gestures menu [%s] to edit the safety settings.", "chat.cpm.serverRequiresCPM": "The server requires CPM to be installed and communication enabled. Currently the \u0027Disable server communication\u0027 setting is set to \u0027true\u0027, and you will be kicked from the server. Open the Gestures menu [%s] to edit the settings. ", "action.cpm.switch": "Switch %s", "action.cpm.set": "Set %s", @@ -886,5 +885,25 @@ "tooltip.cpm.config.editorAutosaveTime": "Time interval between auto-saves.\\Set it to -1 to disable.", "label.cpm.config.editorAutosaveTime": "Auto-save interval: %ss", "chat.cpm.scalingBlocked": "[CPM] Some scaling settings were blocked, ask an admin to enable scaling.", - "button.cpm.clearAnimDataAll": "Clear All" + "button.cpm.clearAnimDataAll": "Clear All", + "tooltip.cpm.gestureButton": "%s\\Keybind: %s", + "label.cpm.gestureMode.press": "Activate on Press", + "label.cpm.gestureMode.hold": "Play While holding", + "label.cpm.quick_key_info": "Hold Ctrl to change play mode", + "tooltip.cpm.animType.pose.opt_layer": "Custom Layer\\Can be toggled using the Gestures menu\\Requires server-side mod", + "label.cpm.quick_key_short": "Bindings", + "label.cpm.new_anim_layer": "New Toggle Layer", + "label.cpm.customLayers": "Custom Layers", + "label.cpm.anim_layer": "Layer: %s", + "tooltip.cpm.animType.pose.opt_value": "Custom Value Layer\\Value can be changed using the Gestures menu\\Value defines the progress through the frames\\Requires server-side mod", + "label.cpm.anim_value": "Value Layer: %s", + "tooltip.cpm.gestureButton.mode": "%s\\Keybind: %s\\Mode: %s", + "label.cpm.new_anim_value": "New Value Layer", + "tooltip.cpm.animType.pose.in_gui": "When your model is rendered inside a Menu (Inventory Menu)", + "label.cpm.pose.in_gui": "Display In Menu", + "tooltip.cpm.config.gestureAutoReset": "Deactivate gestures after the animation finishes", + "label.cpm.config.gestureAutoReset": "Gesture Auto-Reset", + "tooltip.cpm.animType.pose.first_person_mod": "When your model is rendered in first person\\with the First Person Model mod installed.", + "label.cpm.pose.first_person_mod": "First Person Model View", + "chat.cpm.serverSafetySettings": "[CPM] The server has recommended safety settings. Open the Gestures menu [%s] to edit the safety settings." } \ No newline at end of file diff --git a/version-check.json b/version-check.json index b144d552..27864bbe 100644 --- a/version-check.json +++ b/version-check.json @@ -2,31 +2,31 @@ "homepage": "https://www.curseforge.com/minecraft/mc-mods/custom-player-models", "homepage-fabric": "https://www.curseforge.com/minecraft/mc-mods/custom-player-models-fabric", "promos": { - "1.12.2-latest": "0.4.8a", + "1.12.2-latest": "0.5.0a", "1.16.4-latest": "0.4.3a", - "1.16.5-latest": "0.4.8a", - "1.8.9-latest": "0.4.8a", - "1.7.10-latest": "0.4.8a", + "1.16.5-latest": "0.5.0a", + "1.8.9-latest": "0.5.0a", + "1.7.10-latest": "0.5.0a", "1.15.2-latest": "0.0.17d", "1.16.4-fabric-latest": "0.4.3a", - "1.16.5-fabric-latest": "0.4.8a", + "1.16.5-fabric-latest": "0.5.0a", "1.17-fabric-latest": "0.4.3a", - "bukkit-latest": "0.4.8a", - "1.17.1-fabric-latest": "0.4.8a", - "1.17.1-latest": "0.4.8a", + "bukkit-latest": "0.5.0a", + "1.17.1-fabric-latest": "0.5.0a", + "1.17.1-latest": "0.5.0a", "1.18-latest": "0.4.0a", "1.18.1-latest": "0.4.0a", "1.18-fabric-latest": "0.4.1a", "1.18.1-fabric-latest": "0.4.1a", - "1.10.2-latest": "0.4.8a", - "1.18.2-latest": "0.4.8a", - "1.18.2-fabric-latest": "0.4.8a", - "1.19-latest": "0.4.8a", - "1.19-fabric-latest": "0.4.8a", - "1.19.1-latest": "0.4.8a", - "1.19.1-fabric-latest": "0.4.8a", - "1.19.2-latest": "0.4.8a", - "1.19.2-fabric-latest": "0.4.8a" + "1.10.2-latest": "0.5.0a", + "1.18.2-latest": "0.5.0a", + "1.18.2-fabric-latest": "0.5.0a", + "1.19-latest": "0.5.0a", + "1.19-fabric-latest": "0.5.0a", + "1.19.1-latest": "0.5.0a", + "1.19.1-fabric-latest": "0.5.0a", + "1.19.2-latest": "0.5.0a", + "1.19.2-fabric-latest": "0.5.0a" }, "1.12.2": { "0.0.5a": "First release", @@ -72,7 +72,8 @@ "0.4.5a": "Updated translations (#252)\nAdded: auto-save interval setting\n\nFixed links opening the Wiki Viewer on the First Start Guide\nFixed missing translations on some config tooltips\nFixed crash with 1.19 forge servers\nFixed screenshot not working in fabric (Closes #253)\nFixed some changes not updating the editor (Closes #250)\nFixed crash with animated textures\nFixed scaling not working in some cases (Closes #257, #202)", "0.4.6a": "Added moving per-face UVs and Animated Textures with Move UV tool\nAdded clear all function to the Clear button under Animations\n\nFixed cloning not working in some cases\nFixed non-additive animations not displaying correctly in the Editor in rare cases\nFixed some changes not updating the editor (Closes #263)\nFixed multi-selection not working with Move UV tool\nFixed LAN not working on some versions (Closes #260)\nDisabled vanilla helmet 2nd layers (Closes #189)\nFixed rendering issue with Quark on 1.12.2 (Closes #244)", "0.4.7a": "Fixed models failing to load with SSL error on 1.12.2\nFixed editor crash when nothing is selected with Display All UVs", - "0.4.8a": "Fixed Glowing Eyes not working with Iris (Closes #245, ? #210, Closes #195)\nFixed server crash on 1.17+ (Closes #266, ? #270, ? #272)\nFixed duplicated root parts not saving correctly and breaking animations" + "0.4.8a": "Fixed Glowing Eyes not working with Iris (Closes #245, ? #210, Closes #195)\nFixed server crash on 1.17+ (Closes #266, ? #270, ? #272)\nFixed duplicated root parts not saving correctly and breaking animations", + "0.5.0a": "Added hold to play gesture/pose mode\nAdded non looping gestures reset after playing\nImproved Gesture gui on big gui scales\nAdded new poses:\n- In Menu\n- First Person Model View\nAdded new type of animation: Layers (Closes #64)\nAdded an updated gesture system when mod is installed on the server (Closes #66)\nUpdated Simplified Chinese translations (#276)\n\nFixed settings popup/gui always asking to discard changes\nFixed some popups opening way too big with some gui scales\nFixed Optifine breaking Glowing parts (Closes #278)\nFixed skull rendering when the First Person Model mod is installed\nFixed model loading status rendering in the wrong place in some cases" }, "1.16.4": { "0.0.5a": "First release", @@ -167,7 +168,8 @@ "0.4.5a": "Updated translations (#252)\nAdded: auto-save interval setting\n\nFixed links opening the Wiki Viewer on the First Start Guide\nFixed missing translations on some config tooltips\nFixed crash with 1.19 forge servers\nFixed screenshot not working in fabric (Closes #253)\nFixed some changes not updating the editor (Closes #250)\nFixed crash with animated textures\nFixed scaling not working in some cases (Closes #257, #202)", "0.4.6a": "Added moving per-face UVs and Animated Textures with Move UV tool\nAdded clear all function to the Clear button under Animations\n\nFixed cloning not working in some cases\nFixed non-additive animations not displaying correctly in the Editor in rare cases\nFixed some changes not updating the editor (Closes #263)\nFixed multi-selection not working with Move UV tool\nFixed LAN not working on some versions (Closes #260)\nDisabled vanilla helmet 2nd layers (Closes #189)\nFixed rendering issue with Quark on 1.12.2 (Closes #244)", "0.4.7a": "Fixed models failing to load with SSL error on 1.12.2\nFixed editor crash when nothing is selected with Display All UVs", - "0.4.8a": "Fixed Glowing Eyes not working with Iris (Closes #245, ? #210, Closes #195)\nFixed server crash on 1.17+ (Closes #266, ? #270, ? #272)\nFixed duplicated root parts not saving correctly and breaking animations" + "0.4.8a": "Fixed Glowing Eyes not working with Iris (Closes #245, ? #210, Closes #195)\nFixed server crash on 1.17+ (Closes #266, ? #270, ? #272)\nFixed duplicated root parts not saving correctly and breaking animations", + "0.5.0a": "Added hold to play gesture/pose mode\nAdded non looping gestures reset after playing\nImproved Gesture gui on big gui scales\nAdded new poses:\n- In Menu\n- First Person Model View\nAdded new type of animation: Layers (Closes #64)\nAdded an updated gesture system when mod is installed on the server (Closes #66)\nUpdated Simplified Chinese translations (#276)\n\nFixed settings popup/gui always asking to discard changes\nFixed some popups opening way too big with some gui scales\nFixed Optifine breaking Glowing parts (Closes #278)\nFixed skull rendering when the First Person Model mod is installed\nFixed model loading status rendering in the wrong place in some cases" }, "1.16.4-fabric": { "0.0.5a": "First release", @@ -258,7 +260,8 @@ "0.4.5a": "Updated translations (#252)\nAdded: auto-save interval setting\n\nFixed links opening the Wiki Viewer on the First Start Guide\nFixed missing translations on some config tooltips\nFixed crash with 1.19 forge servers\nFixed screenshot not working in fabric (Closes #253)\nFixed some changes not updating the editor (Closes #250)\nFixed crash with animated textures\nFixed scaling not working in some cases (Closes #257, #202)", "0.4.6a": "Added moving per-face UVs and Animated Textures with Move UV tool\nAdded clear all function to the Clear button under Animations\n\nFixed cloning not working in some cases\nFixed non-additive animations not displaying correctly in the Editor in rare cases\nFixed some changes not updating the editor (Closes #263)\nFixed multi-selection not working with Move UV tool\nFixed LAN not working on some versions (Closes #260)\nDisabled vanilla helmet 2nd layers (Closes #189)\nFixed rendering issue with Quark on 1.12.2 (Closes #244)", "0.4.7a": "Fixed models failing to load with SSL error on 1.12.2\nFixed editor crash when nothing is selected with Display All UVs", - "0.4.8a": "Fixed Glowing Eyes not working with Iris (Closes #245, ? #210, Closes #195)\nFixed server crash on 1.17+ (Closes #266, ? #270, ? #272)\nFixed duplicated root parts not saving correctly and breaking animations" + "0.4.8a": "Fixed Glowing Eyes not working with Iris (Closes #245, ? #210, Closes #195)\nFixed server crash on 1.17+ (Closes #266, ? #270, ? #272)\nFixed duplicated root parts not saving correctly and breaking animations", + "0.5.0a": "Added hold to play gesture/pose mode\nAdded non looping gestures reset after playing\nImproved Gesture gui on big gui scales\nAdded new poses:\n- In Menu\n- First Person Model View\nAdded new type of animation: Layers (Closes #64)\nAdded an updated gesture system when mod is installed on the server (Closes #66)\nUpdated Simplified Chinese translations (#276)\n\nFixed settings popup/gui always asking to discard changes\nFixed some popups opening way too big with some gui scales\nFixed Optifine breaking Glowing parts (Closes #278)\nFixed skull rendering when the First Person Model mod is installed\nFixed model loading status rendering in the wrong place in some cases" }, "1.17-fabric": { "0.0.5a": "First release", @@ -348,7 +351,8 @@ "0.4.5a": "Updated translations (#252)\nAdded: auto-save interval setting\n\nFixed links opening the Wiki Viewer on the First Start Guide\nFixed missing translations on some config tooltips\nFixed crash with 1.19 forge servers\nFixed screenshot not working in fabric (Closes #253)\nFixed some changes not updating the editor (Closes #250)\nFixed crash with animated textures\nFixed scaling not working in some cases (Closes #257, #202)", "0.4.6a": "Added moving per-face UVs and Animated Textures with Move UV tool\nAdded clear all function to the Clear button under Animations\n\nFixed cloning not working in some cases\nFixed non-additive animations not displaying correctly in the Editor in rare cases\nFixed some changes not updating the editor (Closes #263)\nFixed multi-selection not working with Move UV tool\nFixed LAN not working on some versions (Closes #260)\nDisabled vanilla helmet 2nd layers (Closes #189)\nFixed rendering issue with Quark on 1.12.2 (Closes #244)", "0.4.7a": "Fixed models failing to load with SSL error on 1.12.2\nFixed editor crash when nothing is selected with Display All UVs", - "0.4.8a": "Fixed Glowing Eyes not working with Iris (Closes #245, ? #210, Closes #195)\nFixed server crash on 1.17+ (Closes #266, ? #270, ? #272)\nFixed duplicated root parts not saving correctly and breaking animations" + "0.4.8a": "Fixed Glowing Eyes not working with Iris (Closes #245, ? #210, Closes #195)\nFixed server crash on 1.17+ (Closes #266, ? #270, ? #272)\nFixed duplicated root parts not saving correctly and breaking animations", + "0.5.0a": "Added hold to play gesture/pose mode\nAdded non looping gestures reset after playing\nImproved Gesture gui on big gui scales\nAdded new poses:\n- In Menu\n- First Person Model View\nAdded new type of animation: Layers (Closes #64)\nAdded an updated gesture system when mod is installed on the server (Closes #66)\nUpdated Simplified Chinese translations (#276)\n\nFixed settings popup/gui always asking to discard changes\nFixed some popups opening way too big with some gui scales\nFixed Optifine breaking Glowing parts (Closes #278)\nFixed skull rendering when the First Person Model mod is installed\nFixed model loading status rendering in the wrong place in some cases" }, "1.7.10": { "0.0.5a": "First release", @@ -393,7 +397,8 @@ "0.4.5a": "Updated translations (#252)\nAdded: auto-save interval setting\n\nFixed links opening the Wiki Viewer on the First Start Guide\nFixed missing translations on some config tooltips\nFixed crash with 1.19 forge servers\nFixed screenshot not working in fabric (Closes #253)\nFixed some changes not updating the editor (Closes #250)\nFixed crash with animated textures\nFixed scaling not working in some cases (Closes #257, #202)", "0.4.6a": "Added moving per-face UVs and Animated Textures with Move UV tool\nAdded clear all function to the Clear button under Animations\n\nFixed cloning not working in some cases\nFixed non-additive animations not displaying correctly in the Editor in rare cases\nFixed some changes not updating the editor (Closes #263)\nFixed multi-selection not working with Move UV tool\nFixed LAN not working on some versions (Closes #260)\nDisabled vanilla helmet 2nd layers (Closes #189)\nFixed rendering issue with Quark on 1.12.2 (Closes #244)", "0.4.7a": "Fixed models failing to load with SSL error on 1.12.2\nFixed editor crash when nothing is selected with Display All UVs", - "0.4.8a": "Fixed Glowing Eyes not working with Iris (Closes #245, ? #210, Closes #195)\nFixed server crash on 1.17+ (Closes #266, ? #270, ? #272)\nFixed duplicated root parts not saving correctly and breaking animations" + "0.4.8a": "Fixed Glowing Eyes not working with Iris (Closes #245, ? #210, Closes #195)\nFixed server crash on 1.17+ (Closes #266, ? #270, ? #272)\nFixed duplicated root parts not saving correctly and breaking animations", + "0.5.0a": "Added hold to play gesture/pose mode\nAdded non looping gestures reset after playing\nImproved Gesture gui on big gui scales\nAdded new poses:\n- In Menu\n- First Person Model View\nAdded new type of animation: Layers (Closes #64)\nAdded an updated gesture system when mod is installed on the server (Closes #66)\nUpdated Simplified Chinese translations (#276)\n\nFixed settings popup/gui always asking to discard changes\nFixed some popups opening way too big with some gui scales\nFixed Optifine breaking Glowing parts (Closes #278)\nFixed skull rendering when the First Person Model mod is installed\nFixed model loading status rendering in the wrong place in some cases" }, "1.15.2": { "0.0.6a": "Editor gui cleanup\nAdded custom Animations tab in editor\nVariuos rendering fixes with the editor", @@ -451,7 +456,8 @@ "0.4.5a": "Updated translations (#252)\nAdded: auto-save interval setting\n\nFixed links opening the Wiki Viewer on the First Start Guide\nFixed missing translations on some config tooltips\nFixed crash with 1.19 forge servers\nFixed screenshot not working in fabric (Closes #253)\nFixed some changes not updating the editor (Closes #250)\nFixed crash with animated textures\nFixed scaling not working in some cases (Closes #257, #202)", "0.4.6a": "Added moving per-face UVs and Animated Textures with Move UV tool\nAdded clear all function to the Clear button under Animations\n\nFixed cloning not working in some cases\nFixed non-additive animations not displaying correctly in the Editor in rare cases\nFixed some changes not updating the editor (Closes #263)\nFixed multi-selection not working with Move UV tool\nFixed LAN not working on some versions (Closes #260)\nDisabled vanilla helmet 2nd layers (Closes #189)\nFixed rendering issue with Quark on 1.12.2 (Closes #244)", "0.4.7a": "Fixed models failing to load with SSL error on 1.12.2\nFixed editor crash when nothing is selected with Display All UVs", - "0.4.8a": "Fixed Glowing Eyes not working with Iris (Closes #245, ? #210, Closes #195)\nFixed server crash on 1.17+ (Closes #266, ? #270, ? #272)\nFixed duplicated root parts not saving correctly and breaking animations" + "0.4.8a": "Fixed Glowing Eyes not working with Iris (Closes #245, ? #210, Closes #195)\nFixed server crash on 1.17+ (Closes #266, ? #270, ? #272)\nFixed duplicated root parts not saving correctly and breaking animations", + "0.5.0a": "Added hold to play gesture/pose mode\nAdded non looping gestures reset after playing\nImproved Gesture gui on big gui scales\nAdded new poses:\n- In Menu\n- First Person Model View\nAdded new type of animation: Layers (Closes #64)\nAdded an updated gesture system when mod is installed on the server (Closes #66)\nUpdated Simplified Chinese translations (#276)\n\nFixed settings popup/gui always asking to discard changes\nFixed some popups opening way too big with some gui scales\nFixed Optifine breaking Glowing parts (Closes #278)\nFixed skull rendering when the First Person Model mod is installed\nFixed model loading status rendering in the wrong place in some cases" }, "1.17.1-fabric": { "0.0.0": "1.17-fabric", @@ -474,7 +480,8 @@ "0.4.5a": "Updated translations (#252)\nAdded: auto-save interval setting\n\nFixed links opening the Wiki Viewer on the First Start Guide\nFixed missing translations on some config tooltips\nFixed crash with 1.19 forge servers\nFixed screenshot not working in fabric (Closes #253)\nFixed some changes not updating the editor (Closes #250)\nFixed crash with animated textures\nFixed scaling not working in some cases (Closes #257, #202)", "0.4.6a": "Added moving per-face UVs and Animated Textures with Move UV tool\nAdded clear all function to the Clear button under Animations\n\nFixed cloning not working in some cases\nFixed non-additive animations not displaying correctly in the Editor in rare cases\nFixed some changes not updating the editor (Closes #263)\nFixed multi-selection not working with Move UV tool\nFixed LAN not working on some versions (Closes #260)\nDisabled vanilla helmet 2nd layers (Closes #189)\nFixed rendering issue with Quark on 1.12.2 (Closes #244)", "0.4.7a": "Fixed models failing to load with SSL error on 1.12.2\nFixed editor crash when nothing is selected with Display All UVs", - "0.4.8a": "Fixed Glowing Eyes not working with Iris (Closes #245, ? #210, Closes #195)\nFixed server crash on 1.17+ (Closes #266, ? #270, ? #272)\nFixed duplicated root parts not saving correctly and breaking animations" + "0.4.8a": "Fixed Glowing Eyes not working with Iris (Closes #245, ? #210, Closes #195)\nFixed server crash on 1.17+ (Closes #266, ? #270, ? #272)\nFixed duplicated root parts not saving correctly and breaking animations", + "0.5.0a": "Added hold to play gesture/pose mode\nAdded non looping gestures reset after playing\nImproved Gesture gui on big gui scales\nAdded new poses:\n- In Menu\n- First Person Model View\nAdded new type of animation: Layers (Closes #64)\nAdded an updated gesture system when mod is installed on the server (Closes #66)\nUpdated Simplified Chinese translations (#276)\n\nFixed settings popup/gui always asking to discard changes\nFixed some popups opening way too big with some gui scales\nFixed Optifine breaking Glowing parts (Closes #278)\nFixed skull rendering when the First Person Model mod is installed\nFixed model loading status rendering in the wrong place in some cases" }, "1.17.1": { "0.0.0": "1.16.5", @@ -492,7 +499,8 @@ "0.4.5a": "Updated translations (#252)\nAdded: auto-save interval setting\n\nFixed links opening the Wiki Viewer on the First Start Guide\nFixed missing translations on some config tooltips\nFixed crash with 1.19 forge servers\nFixed screenshot not working in fabric (Closes #253)\nFixed some changes not updating the editor (Closes #250)\nFixed crash with animated textures\nFixed scaling not working in some cases (Closes #257, #202)", "0.4.6a": "Added moving per-face UVs and Animated Textures with Move UV tool\nAdded clear all function to the Clear button under Animations\n\nFixed cloning not working in some cases\nFixed non-additive animations not displaying correctly in the Editor in rare cases\nFixed some changes not updating the editor (Closes #263)\nFixed multi-selection not working with Move UV tool\nFixed LAN not working on some versions (Closes #260)\nDisabled vanilla helmet 2nd layers (Closes #189)\nFixed rendering issue with Quark on 1.12.2 (Closes #244)", "0.4.7a": "Fixed models failing to load with SSL error on 1.12.2\nFixed editor crash when nothing is selected with Display All UVs", - "0.4.8a": "Fixed Glowing Eyes not working with Iris (Closes #245, ? #210, Closes #195)\nFixed server crash on 1.17+ (Closes #266, ? #270, ? #272)\nFixed duplicated root parts not saving correctly and breaking animations" + "0.4.8a": "Fixed Glowing Eyes not working with Iris (Closes #245, ? #210, Closes #195)\nFixed server crash on 1.17+ (Closes #266, ? #270, ? #272)\nFixed duplicated root parts not saving correctly and breaking animations", + "0.5.0a": "Added hold to play gesture/pose mode\nAdded non looping gestures reset after playing\nImproved Gesture gui on big gui scales\nAdded new poses:\n- In Menu\n- First Person Model View\nAdded new type of animation: Layers (Closes #64)\nAdded an updated gesture system when mod is installed on the server (Closes #66)\nUpdated Simplified Chinese translations (#276)\n\nFixed settings popup/gui always asking to discard changes\nFixed some popups opening way too big with some gui scales\nFixed Optifine breaking Glowing parts (Closes #278)\nFixed skull rendering when the First Person Model mod is installed\nFixed model loading status rendering in the wrong place in some cases" }, "1.18": { "0.0.0": "1.17.1", @@ -534,7 +542,8 @@ "0.4.5a": "Updated translations (#252)\nAdded: auto-save interval setting\n\nFixed links opening the Wiki Viewer on the First Start Guide\nFixed missing translations on some config tooltips\nFixed crash with 1.19 forge servers\nFixed screenshot not working in fabric (Closes #253)\nFixed some changes not updating the editor (Closes #250)\nFixed crash with animated textures\nFixed scaling not working in some cases (Closes #257, #202)", "0.4.6a": "Added moving per-face UVs and Animated Textures with Move UV tool\nAdded clear all function to the Clear button under Animations\n\nFixed cloning not working in some cases\nFixed non-additive animations not displaying correctly in the Editor in rare cases\nFixed some changes not updating the editor (Closes #263)\nFixed multi-selection not working with Move UV tool\nFixed LAN not working on some versions (Closes #260)\nDisabled vanilla helmet 2nd layers (Closes #189)\nFixed rendering issue with Quark on 1.12.2 (Closes #244)", "0.4.7a": "Fixed models failing to load with SSL error on 1.12.2\nFixed editor crash when nothing is selected with Display All UVs", - "0.4.8a": "Fixed Glowing Eyes not working with Iris (Closes #245, ? #210, Closes #195)\nFixed server crash on 1.17+ (Closes #266, ? #270, ? #272)\nFixed duplicated root parts not saving correctly and breaking animations" + "0.4.8a": "Fixed Glowing Eyes not working with Iris (Closes #245, ? #210, Closes #195)\nFixed server crash on 1.17+ (Closes #266, ? #270, ? #272)\nFixed duplicated root parts not saving correctly and breaking animations", + "0.5.0a": "Added hold to play gesture/pose mode\nAdded non looping gestures reset after playing\nImproved Gesture gui on big gui scales\nAdded new poses:\n- In Menu\n- First Person Model View\nAdded new type of animation: Layers (Closes #64)\nAdded an updated gesture system when mod is installed on the server (Closes #66)\nUpdated Simplified Chinese translations (#276)\n\nFixed settings popup/gui always asking to discard changes\nFixed some popups opening way too big with some gui scales\nFixed Optifine breaking Glowing parts (Closes #278)\nFixed skull rendering when the First Person Model mod is installed\nFixed model loading status rendering in the wrong place in some cases" }, "1.18.2": { "0.0.0": "1.18.1", @@ -546,7 +555,8 @@ "0.4.5a": "Updated translations (#252)\nAdded: auto-save interval setting\n\nFixed links opening the Wiki Viewer on the First Start Guide\nFixed missing translations on some config tooltips\nFixed crash with 1.19 forge servers\nFixed screenshot not working in fabric (Closes #253)\nFixed some changes not updating the editor (Closes #250)\nFixed crash with animated textures\nFixed scaling not working in some cases (Closes #257, #202)", "0.4.6a": "Added moving per-face UVs and Animated Textures with Move UV tool\nAdded clear all function to the Clear button under Animations\n\nFixed cloning not working in some cases\nFixed non-additive animations not displaying correctly in the Editor in rare cases\nFixed some changes not updating the editor (Closes #263)\nFixed multi-selection not working with Move UV tool\nFixed LAN not working on some versions (Closes #260)\nDisabled vanilla helmet 2nd layers (Closes #189)\nFixed rendering issue with Quark on 1.12.2 (Closes #244)", "0.4.7a": "Fixed models failing to load with SSL error on 1.12.2\nFixed editor crash when nothing is selected with Display All UVs", - "0.4.8a": "Fixed Glowing Eyes not working with Iris (Closes #245, ? #210, Closes #195)\nFixed server crash on 1.17+ (Closes #266, ? #270, ? #272)\nFixed duplicated root parts not saving correctly and breaking animations" + "0.4.8a": "Fixed Glowing Eyes not working with Iris (Closes #245, ? #210, Closes #195)\nFixed server crash on 1.17+ (Closes #266, ? #270, ? #272)\nFixed duplicated root parts not saving correctly and breaking animations", + "0.5.0a": "Added hold to play gesture/pose mode\nAdded non looping gestures reset after playing\nImproved Gesture gui on big gui scales\nAdded new poses:\n- In Menu\n- First Person Model View\nAdded new type of animation: Layers (Closes #64)\nAdded an updated gesture system when mod is installed on the server (Closes #66)\nUpdated Simplified Chinese translations (#276)\n\nFixed settings popup/gui always asking to discard changes\nFixed some popups opening way too big with some gui scales\nFixed Optifine breaking Glowing parts (Closes #278)\nFixed skull rendering when the First Person Model mod is installed\nFixed model loading status rendering in the wrong place in some cases" }, "1.18.2-fabric": { "0.0.0": "1.18.1-fabric", @@ -558,44 +568,51 @@ "0.4.5a": "Updated translations (#252)\nAdded: auto-save interval setting\n\nFixed links opening the Wiki Viewer on the First Start Guide\nFixed missing translations on some config tooltips\nFixed crash with 1.19 forge servers\nFixed screenshot not working in fabric (Closes #253)\nFixed some changes not updating the editor (Closes #250)\nFixed crash with animated textures\nFixed scaling not working in some cases (Closes #257, #202)", "0.4.6a": "Added moving per-face UVs and Animated Textures with Move UV tool\nAdded clear all function to the Clear button under Animations\n\nFixed cloning not working in some cases\nFixed non-additive animations not displaying correctly in the Editor in rare cases\nFixed some changes not updating the editor (Closes #263)\nFixed multi-selection not working with Move UV tool\nFixed LAN not working on some versions (Closes #260)\nDisabled vanilla helmet 2nd layers (Closes #189)\nFixed rendering issue with Quark on 1.12.2 (Closes #244)", "0.4.7a": "Fixed models failing to load with SSL error on 1.12.2\nFixed editor crash when nothing is selected with Display All UVs", - "0.4.8a": "Fixed Glowing Eyes not working with Iris (Closes #245, ? #210, Closes #195)\nFixed server crash on 1.17+ (Closes #266, ? #270, ? #272)\nFixed duplicated root parts not saving correctly and breaking animations" + "0.4.8a": "Fixed Glowing Eyes not working with Iris (Closes #245, ? #210, Closes #195)\nFixed server crash on 1.17+ (Closes #266, ? #270, ? #272)\nFixed duplicated root parts not saving correctly and breaking animations", + "0.5.0a": "Added hold to play gesture/pose mode\nAdded non looping gestures reset after playing\nImproved Gesture gui on big gui scales\nAdded new poses:\n- In Menu\n- First Person Model View\nAdded new type of animation: Layers (Closes #64)\nAdded an updated gesture system when mod is installed on the server (Closes #66)\nUpdated Simplified Chinese translations (#276)\n\nFixed settings popup/gui always asking to discard changes\nFixed some popups opening way too big with some gui scales\nFixed Optifine breaking Glowing parts (Closes #278)\nFixed skull rendering when the First Person Model mod is installed\nFixed model loading status rendering in the wrong place in some cases" }, "1.19": { "0.0.0": "1.18.2", "0.4.3a": "Added Disable Vanilla Animations Effect\nPorted to 1.19\nAdded animations for using Goat Horns\n\nFixed some root part animations still not saving correctly (#235)\nFixed copy transform not copying vanilla transforms (head movement)\nFixed undo not working after using the gizmo (#237)\nFixed gizmo not being in the correct place while editing some animations", "0.4.4a": "Added vivecraft support for 1.18 (tested with 3-r1)\nAdded wiki reader into the editor\nAdded a first start guide and wiki reader\nUpdated forge 1.19 to 41.0.94 (Closes #247)\nAdded: hold shift to skip confirm popups\n\nFixed duplicated root parts can\u0027t be deleted\nSmall performance optimizations in the editor\nFixed models not loading/log-spam in LAN worlds (Closes #246)\nFixed model loading errors showing for invisible players\nFixed mouse not working in the texture editor with some settings", "0.4.5a": "Updated translations (#252)\nAdded: auto-save interval setting\n\nFixed links opening the Wiki Viewer on the First Start Guide\nFixed missing translations on some config tooltips\nFixed crash with 1.19 forge servers\nFixed screenshot not working in fabric (Closes #253)\nFixed some changes not updating the editor (Closes #250)\nFixed crash with animated textures\nFixed scaling not working in some cases (Closes #257, #202)", - "0.4.8a": "Fixed Glowing Eyes not working with Iris (Closes #245, ? #210, Closes #195)\nFixed server crash on 1.17+ (Closes #266, ? #270, ? #272)\nFixed duplicated root parts not saving correctly and breaking animations" + "0.4.8a": "Fixed Glowing Eyes not working with Iris (Closes #245, ? #210, Closes #195)\nFixed server crash on 1.17+ (Closes #266, ? #270, ? #272)\nFixed duplicated root parts not saving correctly and breaking animations", + "0.5.0a": "Added hold to play gesture/pose mode\nAdded non looping gestures reset after playing\nImproved Gesture gui on big gui scales\nAdded new poses:\n- In Menu\n- First Person Model View\nAdded new type of animation: Layers (Closes #64)\nAdded an updated gesture system when mod is installed on the server (Closes #66)\nUpdated Simplified Chinese translations (#276)\n\nFixed settings popup/gui always asking to discard changes\nFixed some popups opening way too big with some gui scales\nFixed Optifine breaking Glowing parts (Closes #278)\nFixed skull rendering when the First Person Model mod is installed\nFixed model loading status rendering in the wrong place in some cases" }, "1.19-fabric": { "0.0.0": "1.18.2-fabric", "0.4.3a": "Added Disable Vanilla Animations Effect\nPorted to 1.19\nAdded animations for using Goat Horns\n\nFixed some root part animations still not saving correctly (#235)\nFixed copy transform not copying vanilla transforms (head movement)\nFixed undo not working after using the gizmo (#237)\nFixed gizmo not being in the correct place while editing some animations", "0.4.4a": "Added vivecraft support for 1.18 (tested with 3-r1)\nAdded wiki reader into the editor\nAdded a first start guide and wiki reader\nUpdated forge 1.19 to 41.0.94 (Closes #247)\nAdded: hold shift to skip confirm popups\n\nFixed duplicated root parts can\u0027t be deleted\nSmall performance optimizations in the editor\nFixed models not loading/log-spam in LAN worlds (Closes #246)\nFixed model loading errors showing for invisible players\nFixed mouse not working in the texture editor with some settings", "0.4.5a": "Updated translations (#252)\nAdded: auto-save interval setting\n\nFixed links opening the Wiki Viewer on the First Start Guide\nFixed missing translations on some config tooltips\nFixed crash with 1.19 forge servers\nFixed screenshot not working in fabric (Closes #253)\nFixed some changes not updating the editor (Closes #250)\nFixed crash with animated textures\nFixed scaling not working in some cases (Closes #257, #202)", - "0.4.8a": "Fixed Glowing Eyes not working with Iris (Closes #245, ? #210, Closes #195)\nFixed server crash on 1.17+ (Closes #266, ? #270, ? #272)\nFixed duplicated root parts not saving correctly and breaking animations" + "0.4.8a": "Fixed Glowing Eyes not working with Iris (Closes #245, ? #210, Closes #195)\nFixed server crash on 1.17+ (Closes #266, ? #270, ? #272)\nFixed duplicated root parts not saving correctly and breaking animations", + "0.5.0a": "Added hold to play gesture/pose mode\nAdded non looping gestures reset after playing\nImproved Gesture gui on big gui scales\nAdded new poses:\n- In Menu\n- First Person Model View\nAdded new type of animation: Layers (Closes #64)\nAdded an updated gesture system when mod is installed on the server (Closes #66)\nUpdated Simplified Chinese translations (#276)\n\nFixed settings popup/gui always asking to discard changes\nFixed some popups opening way too big with some gui scales\nFixed Optifine breaking Glowing parts (Closes #278)\nFixed skull rendering when the First Person Model mod is installed\nFixed model loading status rendering in the wrong place in some cases" }, "1.19.1": { "0.0.0": "1.19", "0.4.5b": "Updated to 1.19.1 (Closes #256, Closes #258)", "0.4.6a": "Added moving per-face UVs and Animated Textures with Move UV tool\nAdded clear all function to the Clear button under Animations\n\nFixed cloning not working in some cases\nFixed non-additive animations not displaying correctly in the Editor in rare cases\nFixed some changes not updating the editor (Closes #263)\nFixed multi-selection not working with Move UV tool\nFixed LAN not working on some versions (Closes #260)\nDisabled vanilla helmet 2nd layers (Closes #189)\nFixed rendering issue with Quark on 1.12.2 (Closes #244)", "0.4.7a": "Fixed models failing to load with SSL error on 1.12.2\nFixed editor crash when nothing is selected with Display All UVs", - "0.4.8a": "Fixed Glowing Eyes not working with Iris (Closes #245, ? #210, Closes #195)\nFixed server crash on 1.17+ (Closes #266, ? #270, ? #272)\nFixed duplicated root parts not saving correctly and breaking animations" + "0.4.8a": "Fixed Glowing Eyes not working with Iris (Closes #245, ? #210, Closes #195)\nFixed server crash on 1.17+ (Closes #266, ? #270, ? #272)\nFixed duplicated root parts not saving correctly and breaking animations", + "0.5.0a": "Added hold to play gesture/pose mode\nAdded non looping gestures reset after playing\nImproved Gesture gui on big gui scales\nAdded new poses:\n- In Menu\n- First Person Model View\nAdded new type of animation: Layers (Closes #64)\nAdded an updated gesture system when mod is installed on the server (Closes #66)\nUpdated Simplified Chinese translations (#276)\n\nFixed settings popup/gui always asking to discard changes\nFixed some popups opening way too big with some gui scales\nFixed Optifine breaking Glowing parts (Closes #278)\nFixed skull rendering when the First Person Model mod is installed\nFixed model loading status rendering in the wrong place in some cases" }, "1.19.1-fabric": { "0.0.0": "1.19-fabric", "0.4.5b": "Updated to 1.19.1 (Closes #256, Closes #258)", "0.4.6a": "Added moving per-face UVs and Animated Textures with Move UV tool\nAdded clear all function to the Clear button under Animations\n\nFixed cloning not working in some cases\nFixed non-additive animations not displaying correctly in the Editor in rare cases\nFixed some changes not updating the editor (Closes #263)\nFixed multi-selection not working with Move UV tool\nFixed LAN not working on some versions (Closes #260)\nDisabled vanilla helmet 2nd layers (Closes #189)\nFixed rendering issue with Quark on 1.12.2 (Closes #244)", "0.4.7a": "Fixed models failing to load with SSL error on 1.12.2\nFixed editor crash when nothing is selected with Display All UVs", - "0.4.8a": "Fixed Glowing Eyes not working with Iris (Closes #245, ? #210, Closes #195)\nFixed server crash on 1.17+ (Closes #266, ? #270, ? #272)\nFixed duplicated root parts not saving correctly and breaking animations" + "0.4.8a": "Fixed Glowing Eyes not working with Iris (Closes #245, ? #210, Closes #195)\nFixed server crash on 1.17+ (Closes #266, ? #270, ? #272)\nFixed duplicated root parts not saving correctly and breaking animations", + "0.5.0a": "Added hold to play gesture/pose mode\nAdded non looping gestures reset after playing\nImproved Gesture gui on big gui scales\nAdded new poses:\n- In Menu\n- First Person Model View\nAdded new type of animation: Layers (Closes #64)\nAdded an updated gesture system when mod is installed on the server (Closes #66)\nUpdated Simplified Chinese translations (#276)\n\nFixed settings popup/gui always asking to discard changes\nFixed some popups opening way too big with some gui scales\nFixed Optifine breaking Glowing parts (Closes #278)\nFixed skull rendering when the First Person Model mod is installed\nFixed model loading status rendering in the wrong place in some cases" }, "1.19.2": { "0.4.6a": "Added moving per-face UVs and Animated Textures with Move UV tool\nAdded clear all function to the Clear button under Animations\n\nFixed cloning not working in some cases\nFixed non-additive animations not displaying correctly in the Editor in rare cases\nFixed some changes not updating the editor (Closes #263)\nFixed multi-selection not working with Move UV tool\nFixed LAN not working on some versions (Closes #260)\nDisabled vanilla helmet 2nd layers (Closes #189)\nFixed rendering issue with Quark on 1.12.2 (Closes #244)", "0.4.7a": "Fixed models failing to load with SSL error on 1.12.2\nFixed editor crash when nothing is selected with Display All UVs", - "0.4.8a": "Fixed Glowing Eyes not working with Iris (Closes #245, ? #210, Closes #195)\nFixed server crash on 1.17+ (Closes #266, ? #270, ? #272)\nFixed duplicated root parts not saving correctly and breaking animations" + "0.4.8a": "Fixed Glowing Eyes not working with Iris (Closes #245, ? #210, Closes #195)\nFixed server crash on 1.17+ (Closes #266, ? #270, ? #272)\nFixed duplicated root parts not saving correctly and breaking animations", + "0.5.0a": "Added hold to play gesture/pose mode\nAdded non looping gestures reset after playing\nImproved Gesture gui on big gui scales\nAdded new poses:\n- In Menu\n- First Person Model View\nAdded new type of animation: Layers (Closes #64)\nAdded an updated gesture system when mod is installed on the server (Closes #66)\nUpdated Simplified Chinese translations (#276)\n\nFixed settings popup/gui always asking to discard changes\nFixed some popups opening way too big with some gui scales\nFixed Optifine breaking Glowing parts (Closes #278)\nFixed skull rendering when the First Person Model mod is installed\nFixed model loading status rendering in the wrong place in some cases" }, "1.19.2-fabric": { "0.4.6a": "Added moving per-face UVs and Animated Textures with Move UV tool\nAdded clear all function to the Clear button under Animations\n\nFixed cloning not working in some cases\nFixed non-additive animations not displaying correctly in the Editor in rare cases\nFixed some changes not updating the editor (Closes #263)\nFixed multi-selection not working with Move UV tool\nFixed LAN not working on some versions (Closes #260)\nDisabled vanilla helmet 2nd layers (Closes #189)\nFixed rendering issue with Quark on 1.12.2 (Closes #244)", "0.4.7a": "Fixed models failing to load with SSL error on 1.12.2\nFixed editor crash when nothing is selected with Display All UVs", - "0.4.8a": "Fixed Glowing Eyes not working with Iris (Closes #245, ? #210, Closes #195)\nFixed server crash on 1.17+ (Closes #266, ? #270, ? #272)\nFixed duplicated root parts not saving correctly and breaking animations" + "0.4.8a": "Fixed Glowing Eyes not working with Iris (Closes #245, ? #210, Closes #195)\nFixed server crash on 1.17+ (Closes #266, ? #270, ? #272)\nFixed duplicated root parts not saving correctly and breaking animations", + "0.5.0a": "Added hold to play gesture/pose mode\nAdded non looping gestures reset after playing\nImproved Gesture gui on big gui scales\nAdded new poses:\n- In Menu\n- First Person Model View\nAdded new type of animation: Layers (Closes #64)\nAdded an updated gesture system when mod is installed on the server (Closes #66)\nUpdated Simplified Chinese translations (#276)\n\nFixed settings popup/gui always asking to discard changes\nFixed some popups opening way too big with some gui scales\nFixed Optifine breaking Glowing parts (Closes #278)\nFixed skull rendering when the First Person Model mod is installed\nFixed model loading status rendering in the wrong place in some cases" } } \ No newline at end of file