diff --git a/gradle.properties b/gradle.properties index e3bdce5..d49fd5c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -13,7 +13,7 @@ mapping_version=2023.09.03-1.20.1 mod_id=simple_animator mod_name=SimpleAnimator mod_license=MIT -mod_version=1.0-SNAPSHOT +mod_version=1.0.1 mod_group_id=net.quepierts mod_authors= mod_description= diff --git a/src/main/java/net/quepierts/simple_animator/core/animation/AnimationState.java b/src/main/java/net/quepierts/simple_animator/core/animation/AnimationState.java deleted file mode 100644 index 49b2457..0000000 --- a/src/main/java/net/quepierts/simple_animator/core/animation/AnimationState.java +++ /dev/null @@ -1,10 +0,0 @@ -package net.quepierts.simple_animator.core.animation; - -public enum AnimationState { - IDLE, - REQUEST, - WAITING, - ENTER, - LOOP, - EXIT; -} diff --git a/src/main/java/net/quepierts/simple_animator/core/animation/Interaction.java b/src/main/java/net/quepierts/simple_animator/core/animation/Interaction.java deleted file mode 100644 index 7ea3fe8..0000000 --- a/src/main/java/net/quepierts/simple_animator/core/animation/Interaction.java +++ /dev/null @@ -1,31 +0,0 @@ -package net.quepierts.simple_animator.core.animation; - -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.resources.ResourceLocation; - -import java.util.Optional; - -public record Interaction( - ResourceLocation invite, - ResourceLocation requester, - ResourceLocation receiver -) { - public static void toNetwork(FriendlyByteBuf byteBuf, Interaction interaction) { - byteBuf.writeOptional(Optional.ofNullable(interaction.invite), FriendlyByteBuf::writeResourceLocation); - byteBuf.writeOptional(Optional.ofNullable(interaction.requester), FriendlyByteBuf::writeResourceLocation); - byteBuf.writeOptional(Optional.ofNullable(interaction.receiver), FriendlyByteBuf::writeResourceLocation); - - } - - public static Interaction fromNetwork(FriendlyByteBuf byteBuf) { - final Optional invite = byteBuf.readOptional(FriendlyByteBuf::readResourceLocation); - final Optional requester = byteBuf.readOptional(FriendlyByteBuf::readResourceLocation); - final Optional receiver = byteBuf.readOptional(FriendlyByteBuf::readResourceLocation); - - return new Interaction( - invite.orElse(null), - requester.orElse(null), - receiver.orElse(null) - ); - } -} diff --git a/src/main/java/net/quepierts/simple_animator/core/animation/InteractionHandler.java b/src/main/java/net/quepierts/simple_animator/core/animation/InteractionHandler.java deleted file mode 100644 index a8f2cba..0000000 --- a/src/main/java/net/quepierts/simple_animator/core/animation/InteractionHandler.java +++ /dev/null @@ -1,20 +0,0 @@ -package net.quepierts.simple_animator.core.animation; - -import com.ibm.icu.impl.Pair; -import net.minecraft.resources.ResourceLocation; - -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -public class InteractionHandler { - private final Map> requests; - - public InteractionHandler() { - requests = new HashMap<>(); - } - - public void request(UUID requester, UUID receiver, ResourceLocation location) { - - } -} diff --git a/src/main/java/net/quepierts/simple_animator/core/animation/LerpMode.java b/src/main/java/net/quepierts/simple_animator/core/animation/LerpMode.java deleted file mode 100644 index fa32da1..0000000 --- a/src/main/java/net/quepierts/simple_animator/core/animation/LerpMode.java +++ /dev/null @@ -1,7 +0,0 @@ -package net.quepierts.simple_animator.core.animation; - -public enum LerpMode { - LINEAR, - CATMULLROM, - STEP; -} diff --git a/src/main/java/net/quepierts/simple_animator/core/client/ClientAnimator.java b/src/main/java/net/quepierts/simple_animator/core/client/ClientAnimator.java index 93d7e4f..d9d3734 100644 --- a/src/main/java/net/quepierts/simple_animator/core/client/ClientAnimator.java +++ b/src/main/java/net/quepierts/simple_animator/core/client/ClientAnimator.java @@ -9,25 +9,25 @@ import net.minecraft.client.player.LocalPlayer; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Player; -import net.quepierts.simple_animator.core.animation.ModelBone; -import net.quepierts.simple_animator.core.animation.Animation; -import net.quepierts.simple_animator.core.animation.Animator; import net.quepierts.simple_animator.core.client.state.IAnimationState; import net.quepierts.simple_animator.core.common.PlayerUtils; -import net.quepierts.simple_animator.core.SimpleAnimator; -import net.quepierts.simple_animator.core.animation.AnimationState; +import net.quepierts.simple_animator.core.common.animation.AnimationState; +import net.quepierts.simple_animator.core.common.animation.Animator; +import net.quepierts.simple_animator.core.common.animation.ModelBone; import net.quepierts.simple_animator.core.network.ModNetwork; -import net.quepierts.simple_animator.core.network.packet.AnimatorPacket; +import net.quepierts.simple_animator.core.network.packet.AnimatorDataPacket; import org.joml.Matrix4f; import org.joml.Quaternionf; import org.joml.Vector3f; -import java.util.*; +import java.util.Collections; +import java.util.EnumMap; +import java.util.UUID; public class ClientAnimator extends Animator { private static final ModelPart ROOT = new ModelPart(Collections.EMPTY_LIST, Collections.EMPTY_MAP); public Player player; - private Animation animation; + //private Animation animation; private final EnumMap cache; private boolean processed = false; private boolean shouldUpdate = false; @@ -44,13 +44,7 @@ public ClientAnimator(UUID uuid) { } } - @Override - public void sync(AnimatorPacket packet) { - super.sync(packet); - this.animation = SimpleAnimator.getInstance().getProxy().getAnimationManager().getAnimation(animationLocation); - } - - public void update(AnimatorPacket packet) { + public void update(AnimatorDataPacket packet) { if (!isLocalPlayer()) return; @@ -58,15 +52,15 @@ public void update(AnimatorPacket packet) { } @Override - public void play(ResourceLocation location) { - super.play(location); + public boolean play(ResourceLocation location) { if (this.animation == null) processed = false; - this.animation = SimpleAnimator.getInstance().getProxy().getAnimationManager().getAnimation(location); + if (!super.play(location)) + return false; if (this.animation == null) - return; + return false; this.nextState = this.animation.hasEnterAnimation() ? AnimationState.ENTER : AnimationState.LOOP; this.procState = ProcessState.TRANSFER; @@ -77,19 +71,18 @@ public void play(ResourceLocation location) { assert localPlayer != null; this.player = localPlayer.level().getPlayerByUUID(uuid); } - } - @Override - public boolean isRunning() { - return this.animation != null && super.isRunning(); + return true; } - public void stop() { - super.stop(); + public boolean stop() { + if (!super.stop()) + return false; this.timer = 0; this.nextState = this.animation.hasExitAnimation() ? AnimationState.EXIT : AnimationState.IDLE; this.procState = ProcessState.TRANSFER; this.processed = false; + return true; } public void tick(float time) { @@ -116,7 +109,7 @@ public void tick(float time) { impl.exit(this); this.procState = ProcessState.TRANSFER; this.shouldUpdate = false; - this.update(new AnimatorPacket(this, false)); + this.update(new AnimatorDataPacket(this, false)); } } break; @@ -174,10 +167,6 @@ private void process(ModelBone bone, ModelPart part) { part.zRot = pose.zRot + rotation.z; } - public Animation getAnimation() { - return animation; - } - public boolean canStop() { return curState == AnimationState.LOOP && nextState == AnimationState.LOOP; } @@ -198,7 +187,6 @@ public boolean isLocalPlayer() { public void reset() { super.reset(); - this.animation = null; this.processed = false; this.cache.forEach((bone, cache) -> { @@ -206,7 +194,7 @@ public void reset() { cache.rotation.set(0); }); - this.update(new AnimatorPacket(this, false)); + this.update(new AnimatorDataPacket(this, false)); } public void processRoot(PoseStack poseStack) { diff --git a/src/main/java/net/quepierts/simple_animator/core/client/ClientAnimatorManager.java b/src/main/java/net/quepierts/simple_animator/core/client/ClientAnimatorManager.java index 681d76c..a4b2a47 100644 --- a/src/main/java/net/quepierts/simple_animator/core/client/ClientAnimatorManager.java +++ b/src/main/java/net/quepierts/simple_animator/core/client/ClientAnimatorManager.java @@ -3,9 +3,12 @@ import net.minecraft.client.Minecraft; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -import net.quepierts.simple_animator.core.common.AnimatorManager; +import net.quepierts.simple_animator.core.common.animation.AnimatorManager; +import net.quepierts.simple_animator.core.network.packet.AnimatorDataPacket; +import net.quepierts.simple_animator.core.network.packet.batch.ClientUpdateAnimatorPacket; import javax.annotation.Nonnull; +import java.util.List; import java.util.UUID; public class ClientAnimatorManager extends AnimatorManager { @@ -20,8 +23,20 @@ public ClientAnimator get(UUID player) { } public void tick(float renderTickTime) { + float time = renderTickTime / Minecraft.getInstance().getFps(); for (ClientAnimator animator : animators.values()) { - animator.tick(renderTickTime / Minecraft.getInstance().getFps()); + animator.tick(time); } } + + public void handleUpdateAnimator(ClientUpdateAnimatorPacket packet) { + this.clear(); + + List list = packet.getAnimators(); + for (AnimatorDataPacket data : list) { + this.get(data.getOwner()).sync(data); + } + + this.getLocalAnimator(); + } } diff --git a/src/main/java/net/quepierts/simple_animator/core/client/ClientInteractionHandler.java b/src/main/java/net/quepierts/simple_animator/core/client/ClientInteractionHandler.java deleted file mode 100644 index 53f18ca..0000000 --- a/src/main/java/net/quepierts/simple_animator/core/client/ClientInteractionHandler.java +++ /dev/null @@ -1,80 +0,0 @@ -package net.quepierts.simple_animator.core.client; - -import net.minecraft.client.Minecraft; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.phys.Vec3; -import net.quepierts.simple_animator.core.animation.Interaction; -import net.quepierts.simple_animator.core.common.PlayerUtils; -import net.quepierts.simple_animator.core.network.ModNetwork; -import net.quepierts.simple_animator.core.network.packet.InteractAcceptPacket; -import net.quepierts.simple_animator.core.proxy.ClientProxy; -import org.jetbrains.annotations.Nullable; - -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -public class ClientInteractionHandler { - private final ClientProxy client; - private final Map received; - - @Nullable private UUID target; - @Nullable private Interaction requested; - - public ClientInteractionHandler(ClientProxy clientProxy) { - this.client = clientProxy; - received = new HashMap<>(); - } - - public void receive(UUID uuid, ResourceLocation location) { - assert Minecraft.getInstance().level != null; - Player player = Minecraft.getInstance().level.getPlayerByUUID(uuid); - - if (player == null) - return; - - Interaction interaction = client.getAnimationManager().getInteraction(location); - if (interaction == null) { - received.remove(uuid); - } else { - received.put(uuid, interaction); - } - } - - public void travel(Player player) { - Vec3 position = PlayerUtils.getRelativePosition(player, 1, 0); - client.getNavigator().navigateTo(position); - } - - public void tryAccept(UUID uuid) { - Player player = Minecraft.getInstance().level.getPlayerByUUID(uuid); - - if (player == null) { - received.remove(uuid); - return; - } - - Vec3 position = PlayerUtils.getRelativePosition(player, 1, 0); - if (player.distanceToSqr(position) > 0.01) { - client.getNavigator().navigateTo(position); - return; - } - - accept(uuid); - } - - public void accept(UUID uuid) { - if (!received.containsKey(uuid)) - return; - - ClientAnimator localAnimator = client.getAnimatorManager().getLocalAnimator(); - if (localAnimator.isRunning()) - return; - - Interaction interaction = received.get(uuid); - - localAnimator.play(interaction.receiver()); - ModNetwork.update(new InteractAcceptPacket(uuid)); - } -} diff --git a/src/main/java/net/quepierts/simple_animator/core/client/ClientInteractionManager.java b/src/main/java/net/quepierts/simple_animator/core/client/ClientInteractionManager.java new file mode 100644 index 0000000..860f6bb --- /dev/null +++ b/src/main/java/net/quepierts/simple_animator/core/client/ClientInteractionManager.java @@ -0,0 +1,69 @@ +package net.quepierts.simple_animator.core.client; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.phys.Vec3; +import net.quepierts.simple_animator.core.SimpleAnimator; +import net.quepierts.simple_animator.core.common.PlayerUtils; +import net.quepierts.simple_animator.core.common.animation.InteractionManager; +import net.quepierts.simple_animator.core.network.ModNetwork; +import net.quepierts.simple_animator.core.network.packet.InteractAcceptPacket; +import net.quepierts.simple_animator.core.proxy.ClientProxy; + +import java.util.UUID; + +public class ClientInteractionManager extends InteractionManager { + private final ClientProxy client; + + public ClientInteractionManager(ClientProxy clientProxy) { + this.client = clientProxy; + } + + /* + * Receive Invite From Other Player + * */ + @Override + public boolean invite(Player requester, Player receiver, ResourceLocation location) { + return super.invite(requester, receiver, location); + } + + @Override + public boolean accept(Player requester, Player receiver) { + if (receiver == Minecraft.getInstance().player) { + return tryAccept(requester); + } + return super.accept(requester, receiver); + } + + public boolean tryAccept(Player requester) { + SimpleAnimator.LOGGER.info("Try Accept"); + LocalPlayer player = Minecraft.getInstance().player; + assert player != null; + UUID uuid = requester.getUUID(); + + Request request = this.get(uuid); + if (request == null) + return false; + + Vec3 position = PlayerUtils.getRelativePosition(requester, 1, 0); + if (player.distanceToSqr(position) > 0.01) { + client.getNavigator().navigateTo( + requester, 1, 0, + () -> ModNetwork.sendToServer(new InteractAcceptPacket(uuid, Minecraft.getInstance().player.getUUID())) + ); + return false; + } + + return super.accept(requester, player); + } + + public boolean requesting() { + return this.exist(Minecraft.getInstance().player.getUUID()); + } + + protected Request getLocalRequest() { + return get(Minecraft.getInstance().player.getUUID()); + } +} diff --git a/src/main/java/net/quepierts/simple_animator/core/client/ClientPlayerNavigator.java b/src/main/java/net/quepierts/simple_animator/core/client/ClientPlayerNavigator.java index 6d02d34..b7e88e9 100644 --- a/src/main/java/net/quepierts/simple_animator/core/client/ClientPlayerNavigator.java +++ b/src/main/java/net/quepierts/simple_animator/core/client/ClientPlayerNavigator.java @@ -1,51 +1,81 @@ package net.quepierts.simple_animator.core.client; +import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; +import net.minecraft.commands.arguments.EntityAnchorArgument; +import net.minecraft.world.entity.player.Player; import net.minecraft.world.phys.Vec3; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -import net.quepierts.simple_animator.core.SimpleAnimator; import net.quepierts.simple_animator.core.common.PlayerUtils; @OnlyIn(Dist.CLIENT) public class ClientPlayerNavigator { + private Player target = null; + private float forward = 0.0f; + private float left = 0.0f; + private Vec3 targetPosition = null; + private Vec3 lastTargetPosition = Vec3.ZERO; + private long timer = 0; - private long duration = 0; private boolean navigating = false; + private Runnable post; + + + public void tick() { + if (!lastTargetPosition.equals(target.position())) { + lastTargetPosition = target.position(); + targetPosition = PlayerUtils.getRelativePosition(target, forward, left); + } + + LocalPlayer player = Minecraft.getInstance().player; + if (timer ++ > 1000) { + this.stop(); + return; + } - public void tick(LocalPlayer player) { - if (PlayerUtils.distanceSqr2D(player.position(), targetPosition) < 0.0001 || timer++ > duration) { - stopNavigating(player); + if (PlayerUtils.distanceSqr2D(player.position(), targetPosition) < 0.01) { + finish(player); return; } - Vec3 direction = targetPosition.subtract(player.position()).normalize(); - double speed = 0.1; // 控制移动速度 - player.setDeltaMovement(direction.scale(speed)); + Vec3 subtract = targetPosition.subtract(player.position()).multiply(1, 0, 1); + Vec3 direction = subtract.normalize().scale(player.getSpeed()); + player.addDeltaMovement(subtract.lengthSqr() < direction.lengthSqr() ? subtract : direction); - /*double dX = targetPosition.x - player.getX(); - double dZ = targetPosition.z - player.getZ(); - float targetYaw = (float) (Mth.atan2(dZ, dX) * (180 / Math.PI)) - 90; - player.setYRot(targetYaw);*/ + player.lookAt(EntityAnchorArgument.Anchor.EYES, lastTargetPosition.add(0, target.getEyeHeight(), 0)); } - public void navigateTo(Vec3 position) { - SimpleAnimator.LOGGER.info("Position: {}", position); - targetPosition = position; - navigating = true; - timer = 0; - duration = 1000; + public void navigateTo(Player player, float forward, float left, Runnable post) { + this.target = player; + this.forward = forward; + this.left = left; + this.post = post; + this.navigating = true; + this.timer = 0; } - private void stopNavigating(LocalPlayer player) { - navigating = false; + private void finish(LocalPlayer player) { player.setPos(targetPosition); player.setDeltaMovement(Vec3.ZERO); // 停止移动 - targetPosition = null; + + if (post != null) + post.run(); + + this.stop(); } public boolean isNavigating() { return navigating; } + + public void stop() { + this.navigating = false; + this.target = null; + this.targetPosition = null; + this.lastTargetPosition = Vec3.ZERO; + this.post = null; + this.timer = 0; + } } diff --git a/src/main/java/net/quepierts/simple_animator/core/client/state/IAnimationState.java b/src/main/java/net/quepierts/simple_animator/core/client/state/IAnimationState.java index cd041a4..95ae2b7 100644 --- a/src/main/java/net/quepierts/simple_animator/core/client/state/IAnimationState.java +++ b/src/main/java/net/quepierts/simple_animator/core/client/state/IAnimationState.java @@ -2,7 +2,7 @@ import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -import net.quepierts.simple_animator.core.animation.AnimationState; +import net.quepierts.simple_animator.core.common.animation.AnimationState; import net.quepierts.simple_animator.core.client.ClientAnimator; import org.jetbrains.annotations.NotNull; import org.joml.Vector3f; @@ -40,8 +40,6 @@ public static IAnimationState get(@NotNull AnimationState state) { static { IMPL = new IAnimationState[]{ new StateIdle(), - new StateRequest(), - new StateWait(), new StateEnter(), new StateLoop(), new StateExit() diff --git a/src/main/java/net/quepierts/simple_animator/core/client/state/StateEnter.java b/src/main/java/net/quepierts/simple_animator/core/client/state/StateEnter.java index 714a426..109ba7b 100644 --- a/src/main/java/net/quepierts/simple_animator/core/client/state/StateEnter.java +++ b/src/main/java/net/quepierts/simple_animator/core/client/state/StateEnter.java @@ -1,6 +1,6 @@ package net.quepierts.simple_animator.core.client.state; -import net.quepierts.simple_animator.core.animation.AnimationState; +import net.quepierts.simple_animator.core.common.animation.AnimationState; import net.quepierts.simple_animator.core.client.ClientAnimator; public class StateEnter implements IAnimationState { diff --git a/src/main/java/net/quepierts/simple_animator/core/client/state/StateExit.java b/src/main/java/net/quepierts/simple_animator/core/client/state/StateExit.java index 39bdcfc..f44fb95 100644 --- a/src/main/java/net/quepierts/simple_animator/core/client/state/StateExit.java +++ b/src/main/java/net/quepierts/simple_animator/core/client/state/StateExit.java @@ -1,6 +1,6 @@ package net.quepierts.simple_animator.core.client.state; -import net.quepierts.simple_animator.core.animation.AnimationState; +import net.quepierts.simple_animator.core.common.animation.AnimationState; import net.quepierts.simple_animator.core.client.ClientAnimator; public class StateExit implements IAnimationState { diff --git a/src/main/java/net/quepierts/simple_animator/core/client/state/StateIdle.java b/src/main/java/net/quepierts/simple_animator/core/client/state/StateIdle.java index c3630e8..464e612 100644 --- a/src/main/java/net/quepierts/simple_animator/core/client/state/StateIdle.java +++ b/src/main/java/net/quepierts/simple_animator/core/client/state/StateIdle.java @@ -1,6 +1,6 @@ package net.quepierts.simple_animator.core.client.state; -import net.quepierts.simple_animator.core.animation.AnimationState; +import net.quepierts.simple_animator.core.common.animation.AnimationState; import net.quepierts.simple_animator.core.client.ClientAnimator; import org.joml.Vector3f; diff --git a/src/main/java/net/quepierts/simple_animator/core/client/state/StateLoop.java b/src/main/java/net/quepierts/simple_animator/core/client/state/StateLoop.java index 2b79be7..526655b 100644 --- a/src/main/java/net/quepierts/simple_animator/core/client/state/StateLoop.java +++ b/src/main/java/net/quepierts/simple_animator/core/client/state/StateLoop.java @@ -1,6 +1,6 @@ package net.quepierts.simple_animator.core.client.state; -import net.quepierts.simple_animator.core.animation.AnimationState; +import net.quepierts.simple_animator.core.common.animation.AnimationState; import net.quepierts.simple_animator.core.client.ClientAnimator; public class StateLoop implements IAnimationState { diff --git a/src/main/java/net/quepierts/simple_animator/core/client/state/StateRequest.java b/src/main/java/net/quepierts/simple_animator/core/client/state/StateRequest.java deleted file mode 100644 index 5435f15..0000000 --- a/src/main/java/net/quepierts/simple_animator/core/client/state/StateRequest.java +++ /dev/null @@ -1,11 +0,0 @@ -package net.quepierts.simple_animator.core.client.state; - -import net.quepierts.simple_animator.core.animation.AnimationState; -import net.quepierts.simple_animator.core.client.ClientAnimator; - -public class StateRequest implements IAnimationState { - @Override - public AnimationState getNext(ClientAnimator animator) { - return AnimationState.WAITING; - } -} diff --git a/src/main/java/net/quepierts/simple_animator/core/client/state/StateWait.java b/src/main/java/net/quepierts/simple_animator/core/client/state/StateWait.java deleted file mode 100644 index 812b46e..0000000 --- a/src/main/java/net/quepierts/simple_animator/core/client/state/StateWait.java +++ /dev/null @@ -1,11 +0,0 @@ -package net.quepierts.simple_animator.core.client.state; - -import net.quepierts.simple_animator.core.animation.AnimationState; -import net.quepierts.simple_animator.core.client.ClientAnimator; - -public class StateWait implements IAnimationState { - @Override - public AnimationState getNext(ClientAnimator animator) { - return AnimationState.ENTER; - } -} diff --git a/src/main/java/net/quepierts/simple_animator/core/common/PlayerUtils.java b/src/main/java/net/quepierts/simple_animator/core/common/PlayerUtils.java index d75a671..0b16927 100644 --- a/src/main/java/net/quepierts/simple_animator/core/common/PlayerUtils.java +++ b/src/main/java/net/quepierts/simple_animator/core/common/PlayerUtils.java @@ -25,15 +25,15 @@ public static float normalizeRadians(double rad) { return (float) Math.toRadians(normalizeAngle((float) Math.toDegrees(rad))); } - public static Vec3 getRelativePosition(Player player, double forwards, double left) { - Vec2 vec2 = new Vec2(0, player.getYRot()); + public static Vec3 getRelativePosition(Player player, double forward, double left) { + Vec2 vec2 = new Vec2(0, player.yBodyRot); Vec3 vec3 = player.position(); float f = Mth.cos((vec2.y + 90.0F) * ((float)Math.PI / 180F)); float f1 = Mth.sin((vec2.y + 90.0F) * ((float)Math.PI / 180F)); Vec3 vec31 = new Vec3(f, 0, f1); Vec3 vec33 = new Vec3(-f1, 0, f); - double d0 = vec31.x * forwards + vec33.x * left; - double d2 = vec31.z * forwards + vec33.z * left; + double d0 = vec31.x * forward + vec33.x * left; + double d2 = vec31.z * forward + vec33.z * left; return new Vec3(vec3.x + d0, vec3.y, vec3.z + d2); } @@ -42,4 +42,8 @@ public static double distanceSqr2D(Vec3 src, Vec3 dest) { double z = dest.z - src.z; return x * x + z * z; } + + public static boolean inSameDimension(Player a, Player b) { + return a.level() == b.level(); + } } diff --git a/src/main/java/net/quepierts/simple_animator/core/animation/Animation.java b/src/main/java/net/quepierts/simple_animator/core/common/animation/Animation.java similarity index 72% rename from src/main/java/net/quepierts/simple_animator/core/animation/Animation.java rename to src/main/java/net/quepierts/simple_animator/core/common/animation/Animation.java index 793e826..a940c74 100644 --- a/src/main/java/net/quepierts/simple_animator/core/animation/Animation.java +++ b/src/main/java/net/quepierts/simple_animator/core/common/animation/Animation.java @@ -1,4 +1,4 @@ -package net.quepierts.simple_animator.core.animation; +package net.quepierts.simple_animator.core.common.animation; import com.google.gson.JsonObject; import com.google.gson.JsonParser; @@ -38,8 +38,7 @@ public static Animation[] fromStream(Reader reader) { public static Animation[] serialize(JsonObject json) { JsonObject object = json.getAsJsonObject("animations"); - JsonObject main = object.getAsJsonObject(KEY_LOOP); - if (main == null) + if (!object.has(KEY_LOOP)) throw new RuntimeException("Cannot accept animation without \"main\"!"); boolean override = getBoolean(json, "override", true); @@ -47,14 +46,14 @@ public static Animation[] serialize(JsonObject json) { boolean abortable = getBoolean(json, "abortable", true); Animation[] animations; - if (isInteractiveAnimation(main)) { + if (isInteractiveAnimation(object)) { animations = new Animation[3]; - final AnimationSection request = AnimationSection.fromJsonObject(object.getAsJsonObject(KEY_REQUEST), PREFIX_REQUESTER); + final AnimationSection request = AnimationSection.fromJsonObject(object.getAsJsonObject(KEY_REQUEST), Type.INVITE); if (request == null) throw new RuntimeException("Required animation: \"request\"!"); - final AnimationSection waiting = AnimationSection.fromJsonObject(object.getAsJsonObject(KEY_WAITING), PREFIX_REQUESTER); + final AnimationSection waiting = AnimationSection.fromJsonObject(object.getAsJsonObject(KEY_WAITING), Type.INVITE); if (waiting == null) throw new RuntimeException("Required animation: \"waiting\"!"); @@ -66,23 +65,23 @@ public static Animation[] serialize(JsonObject json) { override, movable, true, Type.INVITE ); animations[1] = new Animation( - AnimationSection.fromJsonObject(object.getAsJsonObject(KEY_ENTER), PREFIX_REQUESTER), - AnimationSection.fromJsonObject(object.getAsJsonObject(KEY_LOOP), PREFIX_REQUESTER), - AnimationSection.fromJsonObject(object.getAsJsonObject(KEY_EXIT), PREFIX_REQUESTER), - override, movable, abortable, Type.REQUESTER + AnimationSection.fromJsonObject(object.getAsJsonObject(KEY_ENTER), Type.REQUESTER), + AnimationSection.fromJsonObject(object.getAsJsonObject(KEY_LOOP), Type.REQUESTER), + AnimationSection.fromJsonObject(object.getAsJsonObject(KEY_EXIT), Type.REQUESTER), + override, movable, false, Type.REQUESTER ); animations[2] = new Animation( - AnimationSection.fromJsonObject(object.getAsJsonObject(KEY_ENTER), PREFIX_RECEIVER), - AnimationSection.fromJsonObject(object.getAsJsonObject(KEY_LOOP), PREFIX_RECEIVER), - AnimationSection.fromJsonObject(object.getAsJsonObject(KEY_EXIT), PREFIX_RECEIVER), - override, movable, abortable, Type.RECEIVER + AnimationSection.fromJsonObject(object.getAsJsonObject(KEY_ENTER), Type.RECEIVER), + AnimationSection.fromJsonObject(object.getAsJsonObject(KEY_LOOP), Type.RECEIVER), + AnimationSection.fromJsonObject(object.getAsJsonObject(KEY_EXIT), Type.RECEIVER), + override, movable, false, Type.RECEIVER ); } else { animations = new Animation[] { new Animation( AnimationSection.fromJsonObject(object.getAsJsonObject(KEY_ENTER)), - AnimationSection.fromJsonObject(main), + AnimationSection.fromJsonObject(object.getAsJsonObject(KEY_LOOP)), AnimationSection.fromJsonObject(object.getAsJsonObject(KEY_EXIT)), override, movable, abortable, Type.SIMPLE ) @@ -110,7 +109,7 @@ private Animation( } private static boolean isInteractiveAnimation(JsonObject json) { - return json.getAsJsonObject("bones").has("requester"); + return json.has("request"); } private static boolean getBoolean(JsonObject json, String key, boolean def) { @@ -196,47 +195,18 @@ public static Animation fromNetwork(FriendlyByteBuf byteBuf) { override, movable, abortable, type); } - record AnimationSet( - AnimationSection request, - AnimationSection waiting, - AnimationSection enter, - AnimationSection main, - AnimationSection exit - ) { - public static void toNetwork(FriendlyByteBuf byteBuf, AnimationSet set) { - byteBuf.writeOptional(Optional.ofNullable(set.request), AnimationSection::toNetwork); - byteBuf.writeOptional(Optional.ofNullable(set.waiting), AnimationSection::toNetwork); - byteBuf.writeOptional(Optional.ofNullable(set.enter), AnimationSection::toNetwork); - byteBuf.writeOptional(Optional.ofNullable(set.main), AnimationSection::toNetwork); - byteBuf.writeOptional(Optional.ofNullable(set.exit), AnimationSection::toNetwork); - } - - public static AnimationSet fromNetwork(FriendlyByteBuf byteBuf) { - final Optional request = byteBuf.readOptional(AnimationSection::fromNetwork); - final Optional waiting = byteBuf.readOptional(AnimationSection::fromNetwork); - final Optional enter = byteBuf.readOptional(AnimationSection::fromNetwork); - final Optional main = byteBuf.readOptional(AnimationSection::fromNetwork); - final Optional exit = byteBuf.readOptional(AnimationSection::fromNetwork); - return new AnimationSet( - request.orElse(null), - waiting.orElse(null), - enter.orElse(null), - main.orElse(null), - exit.orElse(null) - ); - } - } - public enum Type { - SIMPLE("simple/"), - INVITE("invite/"), - REQUESTER("requester/"), - RECEIVER("receiver/"); + SIMPLE("simple/", ""), + INVITE("invite/", "requester"), + REQUESTER("requester/", "requester"), + RECEIVER("receiver/", "receiver"); public final String path; + public final String prefix; - Type(String path) { + Type(String path, String prefix) { this.path = path; + this.prefix = prefix; } } } diff --git a/src/main/java/net/quepierts/simple_animator/core/animation/AnimationManager.java b/src/main/java/net/quepierts/simple_animator/core/common/animation/AnimationManager.java similarity index 97% rename from src/main/java/net/quepierts/simple_animator/core/animation/AnimationManager.java rename to src/main/java/net/quepierts/simple_animator/core/common/animation/AnimationManager.java index f416c71..6914d17 100644 --- a/src/main/java/net/quepierts/simple_animator/core/animation/AnimationManager.java +++ b/src/main/java/net/quepierts/simple_animator/core/common/animation/AnimationManager.java @@ -1,4 +1,4 @@ -package net.quepierts.simple_animator.core.animation; +package net.quepierts.simple_animator.core.common.animation; import com.google.common.collect.ImmutableMap; import com.google.gson.JsonObject; @@ -14,8 +14,8 @@ import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.util.profiling.ProfilerFiller; import net.quepierts.simple_animator.core.network.ModNetwork; -import net.quepierts.simple_animator.core.network.packet.data.ClientUpdateAnimationPacket; -import net.quepierts.simple_animator.core.network.packet.data.ClientUpdateInteractionPacket; +import net.quepierts.simple_animator.core.network.packet.batch.ClientUpdateAnimationPacket; +import net.quepierts.simple_animator.core.network.packet.batch.ClientUpdateInteractionPacket; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; diff --git a/src/main/java/net/quepierts/simple_animator/core/animation/AnimationSection.java b/src/main/java/net/quepierts/simple_animator/core/common/animation/AnimationSection.java similarity index 98% rename from src/main/java/net/quepierts/simple_animator/core/animation/AnimationSection.java rename to src/main/java/net/quepierts/simple_animator/core/common/animation/AnimationSection.java index 457d917..a69b42d 100644 --- a/src/main/java/net/quepierts/simple_animator/core/animation/AnimationSection.java +++ b/src/main/java/net/quepierts/simple_animator/core/common/animation/AnimationSection.java @@ -1,4 +1,4 @@ -package net.quepierts.simple_animator.core.animation; +package net.quepierts.simple_animator.core.common.animation; import com.google.common.collect.Maps; import com.google.gson.JsonArray; @@ -29,7 +29,7 @@ public class AnimationSection { private final EnumMap keyFrames; - public static AnimationSection fromJsonObject(JsonObject json, String prefix) { + public static AnimationSection fromJsonObject(JsonObject json, Animation.Type type) { if (json == null) return null; @@ -47,9 +47,9 @@ public static AnimationSection fromJsonObject(JsonObject json, String prefix) { for (Map.Entry entry : bones.entrySet()) { final String key = entry.getKey(); - if (!key.startsWith(prefix)) + if (!key.startsWith(type.prefix)) continue; - ModelBone bone = key.equals(prefix) ? ModelBone.ROOT : ModelBone.fromString(key.substring(prefix.length() + 1)); + ModelBone bone = ModelBone.fromString(key.substring(type.prefix.length() + 1)); if (bone != null) { KeyFrame[] rotation = getRotation(entry.getValue().getAsJsonObject().get("rotation"), bone, length); diff --git a/src/main/java/net/quepierts/simple_animator/core/common/animation/AnimationState.java b/src/main/java/net/quepierts/simple_animator/core/common/animation/AnimationState.java new file mode 100644 index 0000000..3a3162b --- /dev/null +++ b/src/main/java/net/quepierts/simple_animator/core/common/animation/AnimationState.java @@ -0,0 +1,8 @@ +package net.quepierts.simple_animator.core.common.animation; + +public enum AnimationState { + IDLE, + ENTER, + LOOP, + EXIT +} diff --git a/src/main/java/net/quepierts/simple_animator/core/animation/Animator.java b/src/main/java/net/quepierts/simple_animator/core/common/animation/Animator.java similarity index 68% rename from src/main/java/net/quepierts/simple_animator/core/animation/Animator.java rename to src/main/java/net/quepierts/simple_animator/core/common/animation/Animator.java index 9a2d629..bf63f4a 100644 --- a/src/main/java/net/quepierts/simple_animator/core/animation/Animator.java +++ b/src/main/java/net/quepierts/simple_animator/core/common/animation/Animator.java @@ -1,8 +1,8 @@ -package net.quepierts.simple_animator.core.animation; +package net.quepierts.simple_animator.core.common.animation; import net.minecraft.resources.ResourceLocation; import net.quepierts.simple_animator.core.SimpleAnimator; -import net.quepierts.simple_animator.core.network.packet.AnimatorPacket; +import net.quepierts.simple_animator.core.network.packet.AnimatorDataPacket; import java.util.UUID; @@ -11,6 +11,7 @@ public class Animator { protected final UUID uuid; protected ResourceLocation animationLocation; + protected Animation animation; protected AnimationState curState; protected AnimationState nextState; @@ -26,22 +27,31 @@ public Animator(UUID uuid) { this.timer = 0.0f; } - public void sync(AnimatorPacket packet) { + public void sync(AnimatorDataPacket packet) { SimpleAnimator.LOGGER.info("Update: {} {} ,", this.getClass().getSimpleName(), packet); this.animationLocation = packet.animationLocation; + this.animation = SimpleAnimator.getInstance().getProxy().getAnimationManager().getAnimation(packet.animationLocation); this.curState = packet.curState; this.nextState = packet.nextState; this.procState = packet.procState; this.timer = packet.timer; } - public void play(ResourceLocation location) { + public boolean play(ResourceLocation location) { + if (this.animation != null && !this.animation.isAbortable()) + return false; + this.animationLocation = location; + this.animation = SimpleAnimator.getInstance().getProxy().getAnimationManager().getAnimation(location); this.timer = 0; + return true; } - public void stop() { + public boolean stop() { + if (this.animation == null || !this.animation.isAbortable()) + return false; this.timer = 0; + return true; } public void terminate() { @@ -57,6 +67,10 @@ public ResourceLocation getAnimationLocation() { return animationLocation; } + public Animation getAnimation() { + return animation; + } + public AnimationState getCurState() { return curState; } @@ -75,11 +89,12 @@ public float getTimer() { public void reset() { this.timer = 0; + this.animation = null; this.animationLocation = EMPTY; } public boolean isRunning() { - return !animationLocation.equals(EMPTY); + return !animationLocation.equals(EMPTY) && this.animation != null; } public enum ProcessState { diff --git a/src/main/java/net/quepierts/simple_animator/core/common/AnimatorManager.java b/src/main/java/net/quepierts/simple_animator/core/common/animation/AnimatorManager.java similarity index 59% rename from src/main/java/net/quepierts/simple_animator/core/common/AnimatorManager.java rename to src/main/java/net/quepierts/simple_animator/core/common/animation/AnimatorManager.java index 84162bb..f505b9e 100644 --- a/src/main/java/net/quepierts/simple_animator/core/common/AnimatorManager.java +++ b/src/main/java/net/quepierts/simple_animator/core/common/animation/AnimatorManager.java @@ -1,14 +1,15 @@ -package net.quepierts.simple_animator.core.common; +package net.quepierts.simple_animator.core.common.animation; import net.minecraft.server.level.ServerPlayer; -import net.quepierts.simple_animator.core.SimpleAnimator; -import net.quepierts.simple_animator.core.animation.Animator; import net.quepierts.simple_animator.core.network.ModNetwork; -import net.quepierts.simple_animator.core.network.packet.AnimatorPacket; +import net.quepierts.simple_animator.core.network.packet.AnimatorDataPacket; +import net.quepierts.simple_animator.core.network.packet.batch.ClientUpdateAnimatorPacket; +import org.jetbrains.annotations.Nullable; import java.util.HashMap; import java.util.Map; import java.util.UUID; +import java.util.function.Predicate; public class AnimatorManager { protected final Map animators; @@ -17,6 +18,7 @@ public AnimatorManager() { this.animators = new HashMap<>(); } + @Nullable public T getAnimator(UUID uuid) { return animators.get(uuid); } @@ -40,12 +42,20 @@ public void remove(UUID uuid) { public void tick(float renderTickTime) {} public void sync(ServerPlayer player) { - for (T value : animators.values()) { + /*for (T value : animators.values()) { if (value.getUuid().equals(player.getUUID())) continue; SimpleAnimator.LOGGER.info("Sync: {}", value.getUuid()); - ModNetwork.sendToPlayer(new AnimatorPacket(value, false), player); - } + ModNetwork.sendToPlayer(new AnimatorDataPacket(value, false), player); + }*/ + + ClientUpdateAnimatorPacket packet = new ClientUpdateAnimatorPacket(this.animators.keySet().stream() + .filter(Predicate.not(player.getUUID()::equals)) + .map(this.animators::get) + .map(AnimatorDataPacket::new) + .toList()); + + ModNetwork.sendToPlayer(packet, player); } } diff --git a/src/main/java/net/quepierts/simple_animator/core/common/animation/Interaction.java b/src/main/java/net/quepierts/simple_animator/core/common/animation/Interaction.java new file mode 100644 index 0000000..bee7227 --- /dev/null +++ b/src/main/java/net/quepierts/simple_animator/core/common/animation/Interaction.java @@ -0,0 +1,30 @@ +package net.quepierts.simple_animator.core.common.animation; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; +import org.jetbrains.annotations.NotNull; + +public record Interaction( + @NotNull ResourceLocation invite, + @NotNull ResourceLocation requester, + @NotNull ResourceLocation receiver +) { + public static void toNetwork(FriendlyByteBuf byteBuf, Interaction interaction) { + byteBuf.writeResourceLocation(interaction.invite); + byteBuf.writeResourceLocation(interaction.requester); + byteBuf.writeResourceLocation(interaction.receiver); + + } + + public static Interaction fromNetwork(FriendlyByteBuf byteBuf) { + final ResourceLocation invite = byteBuf.readResourceLocation(); + final ResourceLocation requester = byteBuf.readResourceLocation(); + final ResourceLocation receiver = byteBuf.readResourceLocation(); + + return new Interaction( + invite, + requester, + receiver + ); + } +} diff --git a/src/main/java/net/quepierts/simple_animator/core/common/animation/InteractionManager.java b/src/main/java/net/quepierts/simple_animator/core/common/animation/InteractionManager.java new file mode 100644 index 0000000..4ae560b --- /dev/null +++ b/src/main/java/net/quepierts/simple_animator/core/common/animation/InteractionManager.java @@ -0,0 +1,91 @@ +package net.quepierts.simple_animator.core.common.animation; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.phys.Vec3; +import net.quepierts.simple_animator.core.SimpleAnimator; +import net.quepierts.simple_animator.core.common.PlayerUtils; +import net.quepierts.simple_animator.core.proxy.CommonProxy; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class InteractionManager { + protected final Map requests; + + public InteractionManager() { + requests = new HashMap<>(); + } + + public boolean invite(Player requester, Player receiver, ResourceLocation location) { + if (requester == receiver) + return false; + + CommonProxy proxy = SimpleAnimator.getInstance().getProxy(); + Animator animator = proxy.getAnimatorManager().get(requester.getUUID()); + + if (animator.getAnimation() != null && !animator.getAnimation().isAbortable()) + return false; + + Interaction interaction = proxy.getAnimationManager().getInteraction(location); + System.out.println(interaction); + + if (interaction == null) + return false; + + this.requests.put(requester.getUUID(), new Request(receiver.getUUID(), location)); + animator.play(interaction.invite()); + return true; + } + + public boolean accept(Player requester, Player receiver) { + Request request = this.requests.get(requester.getUUID()); + + if (request == null || !request.target.equals(receiver.getUUID())) + return false; + + Vec3 position = PlayerUtils.getRelativePosition(requester, 1, 0); + if (!PlayerUtils.inSameDimension(receiver, receiver) || receiver.distanceToSqr(position) > 0.01) + return false; + + CommonProxy proxy = SimpleAnimator.getInstance().getProxy(); + Interaction interaction = proxy.getAnimationManager().getInteraction(request.interaction); + + if (interaction == null) + return false; + + proxy.getAnimatorManager().get(requester.getUUID()).play(interaction.requester()); + proxy.getAnimatorManager().get(receiver.getUUID()).play(interaction.receiver()); + this.requests.remove(requester.getUUID()); + return true; + } + + public void clear() { + this.requests.clear(); + } + + @Nullable + public Request get(UUID requester) { + return this.requests.get(requester); + } + + public boolean exist(UUID requester) { + return this.requests.containsKey(requester); + } + + public void cancel(UUID requester) { + Request request = get(requester); + + if (request != null) { + this.requests.remove(requester); + SimpleAnimator.getInstance().getProxy().getAnimatorManager().get(requester).stop(); + } + } + + public record Request( + UUID target, + ResourceLocation interaction + ) {} +} \ No newline at end of file diff --git a/src/main/java/net/quepierts/simple_animator/core/common/animation/LerpMode.java b/src/main/java/net/quepierts/simple_animator/core/common/animation/LerpMode.java new file mode 100644 index 0000000..914eddc --- /dev/null +++ b/src/main/java/net/quepierts/simple_animator/core/common/animation/LerpMode.java @@ -0,0 +1,7 @@ +package net.quepierts.simple_animator.core.common.animation; + +public enum LerpMode { + LINEAR, + CATMULLROM, + STEP +} diff --git a/src/main/java/net/quepierts/simple_animator/core/animation/ModelBone.java b/src/main/java/net/quepierts/simple_animator/core/common/animation/ModelBone.java similarity index 90% rename from src/main/java/net/quepierts/simple_animator/core/animation/ModelBone.java rename to src/main/java/net/quepierts/simple_animator/core/common/animation/ModelBone.java index 6103667..133db09 100644 --- a/src/main/java/net/quepierts/simple_animator/core/animation/ModelBone.java +++ b/src/main/java/net/quepierts/simple_animator/core/common/animation/ModelBone.java @@ -1,4 +1,4 @@ -package net.quepierts.simple_animator.core.animation; +package net.quepierts.simple_animator.core.common.animation; import com.google.common.collect.ImmutableMap; diff --git a/src/main/java/net/quepierts/simple_animator/core/common/command/AnimateCommand.java b/src/main/java/net/quepierts/simple_animator/core/common/command/AnimateCommand.java index a415b09..4782cb3 100644 --- a/src/main/java/net/quepierts/simple_animator/core/common/command/AnimateCommand.java +++ b/src/main/java/net/quepierts/simple_animator/core/common/command/AnimateCommand.java @@ -12,10 +12,10 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.level.GameType; import net.quepierts.simple_animator.core.SimpleAnimator; -import net.quepierts.simple_animator.core.animation.Animator; +import net.quepierts.simple_animator.core.common.animation.Animator; import net.quepierts.simple_animator.core.network.ModNetwork; -import net.quepierts.simple_animator.core.network.packet.PlayPacket; -import net.quepierts.simple_animator.core.network.packet.StopPacket; +import net.quepierts.simple_animator.core.network.packet.AnimatorPlayPacket; +import net.quepierts.simple_animator.core.network.packet.AnimatorStopPacket; import java.util.UUID; @@ -38,7 +38,7 @@ private static int stop(CommandContext context) { Animator animator = SimpleAnimator.getInstance().getProxy().getAnimatorManager().get(uuid); if (animator.isRunning()) { - ModNetwork.sendToAllPlayers(new StopPacket(uuid), player); + ModNetwork.sendToAllPlayers(new AnimatorStopPacket(uuid), player); } } return 1; @@ -62,7 +62,7 @@ private static int play(CommandContext context) { ResourceLocation location = ResourceLocationArgument.getId(context, "animation"); UUID uuid = player.getUUID(); SimpleAnimator.getInstance().getProxy().getAnimatorManager().get(uuid).play(location); - ModNetwork.sendToAllPlayers(new PlayPacket(uuid, location), player); + ModNetwork.sendToAllPlayers(new AnimatorPlayPacket(uuid, location), player); return 1; } return 0; diff --git a/src/main/java/net/quepierts/simple_animator/core/common/command/InteractCommand.java b/src/main/java/net/quepierts/simple_animator/core/common/command/InteractCommand.java index df809f8..f61844d 100644 --- a/src/main/java/net/quepierts/simple_animator/core/common/command/InteractCommand.java +++ b/src/main/java/net/quepierts/simple_animator/core/common/command/InteractCommand.java @@ -13,7 +13,10 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; import net.quepierts.simple_animator.core.SimpleAnimator; +import net.quepierts.simple_animator.core.common.PlayerUtils; +import net.quepierts.simple_animator.core.common.animation.InteractionManager; import net.quepierts.simple_animator.core.network.ModNetwork; +import net.quepierts.simple_animator.core.network.packet.InteractAcceptPacket; import net.quepierts.simple_animator.core.network.packet.InteractInvitePacket; public class InteractCommand { @@ -35,17 +38,45 @@ private static int invite(CommandContext context) throws Com } ServerPlayer player = source.getPlayer(); ServerPlayer target = EntityArgument.getPlayer(context, "target"); + + if (player == target) { + source.sendFailure(Component.translatable("animator.commands.failed.same_player")); + return 0; + } + ResourceLocation location = ResourceLocationArgument.getId(context, "interaction"); - if (player.level() != target.level() || player.distanceToSqr(target) > 64 * 64) { + if (!PlayerUtils.inSameDimension(player, target) || player.distanceToSqr(target) > 1024) { return 0; } - ModNetwork.sendToPlayer(new InteractInvitePacket(player.getUUID(), location), target); + ModNetwork.sendToAllPlayers(new InteractInvitePacket(player.getUUID(), target.getUUID(), location), player); return 1; } - private static int accept(CommandContext context) { + private static int accept(CommandContext context) throws CommandSyntaxException { + CommandSourceStack source = context.getSource(); + if (!source.isPlayer()) { + source.sendFailure(Component.translatable("animator.commands.failed.invalid_source")); + return 0; + } + + ServerPlayer player = source.getPlayer(); + ServerPlayer requester = EntityArgument.getPlayer(context, "requester"); + + if (player == requester) { + source.sendFailure(Component.translatable("animator.commands.failed.same_player")); + return 0; + } + + InteractionManager.Request request = SimpleAnimator.getInstance().getProxy().getInteractionManager().get(requester.getUUID()); + + if (request == null || !request.target().equals(player.getUUID())) { + source.sendFailure(Component.translatable("animator.commands.failed.nonexistent_request")); + return 0; + } + + ModNetwork.sendToAllPlayers(new InteractAcceptPacket(requester.getUUID(), player.getUUID()), player); return 1; } } diff --git a/src/main/java/net/quepierts/simple_animator/core/mixin/CameraMixin.java b/src/main/java/net/quepierts/simple_animator/core/mixin/CameraMixin.java index 2c5a65d..2e43f23 100644 --- a/src/main/java/net/quepierts/simple_animator/core/mixin/CameraMixin.java +++ b/src/main/java/net/quepierts/simple_animator/core/mixin/CameraMixin.java @@ -1,13 +1,16 @@ package net.quepierts.simple_animator.core.mixin; import net.minecraft.client.Camera; +import net.minecraft.client.Minecraft; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.util.Mth; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.phys.Vec2; import net.minecraft.world.phys.Vec3; import net.quepierts.simple_animator.core.SimpleAnimator; -import net.quepierts.simple_animator.core.animation.ModelBone; import net.quepierts.simple_animator.core.client.ClientAnimator; -import net.quepierts.simple_animator.core.client.ClientAnimatorManager; +import net.quepierts.simple_animator.core.common.animation.ModelBone; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -36,16 +39,29 @@ public void applyAnimation(BlockGetter pLevel, Entity pEntity, boolean pDetached if (detached) return; - ClientAnimator animator = ((ClientAnimatorManager) SimpleAnimator.getInstance().getProxy().getAnimatorManager()).getLocalAnimator(); + ClientAnimator animator = SimpleAnimator.getInstance().getClient().getClientAnimatorManager().getLocalAnimator(); if (animator.isRunning()) { ClientAnimator.Cache root = animator.getCache(ModelBone.ROOT); ClientAnimator.Cache head = animator.getCache(ModelBone.HEAD); + + final float left = (root.position().x + head.position().x) / -16.0f; + final float up = (root.position().y + head.position().y) / 16.0f; + final float forward = (root.position().z + head.position().z) / -16.0f; + + LocalPlayer player = Minecraft.getInstance().player; + Vec2 vec2 = new Vec2(0, player.yBodyRot); + float f = Mth.cos((vec2.y + 90.0F) * ((float)Math.PI / 180F)); + float f1 = Mth.sin((vec2.y + 90.0F) * ((float)Math.PI / 180F)); + Vec3 vec31 = new Vec3(f, 0, f1); + Vec3 vec33 = new Vec3(-f1, 0, f); + double d0 = vec31.x * forward + vec33.x * left; + double d2 = vec31.z * forward + vec33.z * left; + this.setPosition( - (root.position().x + head.position().x) / 16.0f + position.x, - (root.position().y + head.position().y) / 16.0f + position.y, - (root.position().z + head.position().z) / 16.0f + position.z - ); + this.position.x + d0, + this.position.y + up, + this.position.z + d2); ci.cancel(); } } diff --git a/src/main/java/net/quepierts/simple_animator/core/mixin/CapeLayerMixin.java b/src/main/java/net/quepierts/simple_animator/core/mixin/CapeLayerMixin.java index beb7b46..6547727 100644 --- a/src/main/java/net/quepierts/simple_animator/core/mixin/CapeLayerMixin.java +++ b/src/main/java/net/quepierts/simple_animator/core/mixin/CapeLayerMixin.java @@ -14,9 +14,8 @@ import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.quepierts.simple_animator.core.SimpleAnimator; -import net.quepierts.simple_animator.core.animation.ModelBone; +import net.quepierts.simple_animator.core.common.animation.ModelBone; import net.quepierts.simple_animator.core.client.ClientAnimator; -import net.quepierts.simple_animator.core.client.ClientAnimatorManager; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -39,7 +38,7 @@ public CapeLayerMixin(RenderLayerParent) (Object) this; diff --git a/src/main/java/net/quepierts/simple_animator/core/network/BiPacket.java b/src/main/java/net/quepierts/simple_animator/core/network/BiPacket.java index 2d352c1..3ce4da9 100644 --- a/src/main/java/net/quepierts/simple_animator/core/network/BiPacket.java +++ b/src/main/java/net/quepierts/simple_animator/core/network/BiPacket.java @@ -1,5 +1,6 @@ package net.quepierts.simple_animator.core.network; +import net.minecraft.server.level.ServerPlayer; import net.minecraftforge.network.NetworkEvent; public abstract class BiPacket implements IPacket { @@ -9,12 +10,14 @@ public void handle(NetworkEvent.Context context) { sync(context); break; case PLAY_TO_SERVER: - update(context); + ServerPlayer sender = context.getSender(); + if (sender != null) + update(context, sender); break; } } - protected abstract void update(NetworkEvent.Context context); + protected abstract void update(NetworkEvent.Context context, ServerPlayer sender); protected abstract void sync(NetworkEvent.Context context); } diff --git a/src/main/java/net/quepierts/simple_animator/core/network/ModNetwork.java b/src/main/java/net/quepierts/simple_animator/core/network/ModNetwork.java index d26d79e..c6cc681 100644 --- a/src/main/java/net/quepierts/simple_animator/core/network/ModNetwork.java +++ b/src/main/java/net/quepierts/simple_animator/core/network/ModNetwork.java @@ -1,11 +1,15 @@ package net.quepierts.simple_animator.core.network; import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; import net.minecraftforge.network.NetworkDirection; import net.minecraftforge.network.NetworkRegistry; import net.minecraftforge.network.PacketDistributor; import net.minecraftforge.network.simple.SimpleChannel; +import org.apache.commons.compress.utils.Sets; + +import java.util.HashSet; public class ModNetwork { private static final String PROTOCOL_VERSION = "1"; @@ -25,6 +29,16 @@ public static void sendToAllPlayers(IPacket packet, ServerPlayer player) { CHANNEL.send(PacketDistributor.TRACKING_ENTITY_AND_SELF.with(() -> player), packet); } + public static void sendToPlayersExcept(IPacket packet, ServerPlayer... except) { + if (except.length == 0) + return; + MinecraftServer server = except[0].getServer(); + HashSet players = Sets.newHashSet(except); + server.getPlayerList().getPlayers().stream() + .filter(players::contains) + .forEach(player -> sendToPlayer(packet, player)); + } + public static void sendToPlayers(IPacket packet, ServerPlayer player) { CHANNEL.send(PacketDistributor.TRACKING_ENTITY.with(() -> player), packet); } diff --git a/src/main/java/net/quepierts/simple_animator/core/network/ModPacket.java b/src/main/java/net/quepierts/simple_animator/core/network/ModPacket.java index 099cd12..7cea82a 100644 --- a/src/main/java/net/quepierts/simple_animator/core/network/ModPacket.java +++ b/src/main/java/net/quepierts/simple_animator/core/network/ModPacket.java @@ -1,36 +1,30 @@ package net.quepierts.simple_animator.core.network; -import java.util.function.BiConsumer; -import java.util.function.Function; -import java.util.function.Supplier; - import net.minecraft.network.FriendlyByteBuf; import net.minecraftforge.network.NetworkDirection; import net.minecraftforge.network.NetworkEvent; import net.quepierts.simple_animator.core.SimpleAnimator; -import net.quepierts.simple_animator.core.network.packet.AnimatorPacket; -import net.quepierts.simple_animator.core.network.packet.data.ClientUpdateAnimationPacket; -import net.quepierts.simple_animator.core.network.packet.PlayPacket; -import net.quepierts.simple_animator.core.network.packet.StopPacket; -import net.quepierts.simple_animator.core.network.packet.data.ClientUpdateInteractionPacket; +import net.quepierts.simple_animator.core.network.packet.*; +import net.quepierts.simple_animator.core.network.packet.batch.ClientUpdateAnimationPacket; +import net.quepierts.simple_animator.core.network.packet.batch.ClientUpdateAnimatorPacket; +import net.quepierts.simple_animator.core.network.packet.batch.ClientUpdateInteractionPacket; + +import java.util.function.BiConsumer; +import java.util.function.Function; +import java.util.function.Supplier; public enum ModPacket { - ANIMATOR_UPDATE(AnimatorPacket.class, AnimatorPacket::new, AnimatorPacket::handle), - PLAY_UPDATE(PlayPacket.class, PlayPacket::new, PlayPacket::handle), - STOP_UPDATE(StopPacket.class, StopPacket::new, StopPacket::handle), + ANIMATOR_UPDATE(AnimatorDataPacket.class, AnimatorDataPacket::new, AnimatorDataPacket::handle), + ANIMATOR_PLAY(AnimatorPlayPacket.class, AnimatorPlayPacket::new, AnimatorPlayPacket::handle), + ANIMATOR_STOP(AnimatorStopPacket.class, AnimatorStopPacket::new, AnimatorStopPacket::handle), + INTERACT_INVITE(InteractInvitePacket.class, InteractInvitePacket::new, InteractInvitePacket::handle), + INTERACT_ACCEPT(InteractAcceptPacket.class, InteractAcceptPacket::new, InteractAcceptPacket::handle), + INTERACT_CANCEL(InteractCancelPacket.class, InteractCancelPacket::new, InteractCancelPacket::handle), CLIENT_UPDATE_ANIMATION(ClientUpdateAnimationPacket.class, ClientUpdateAnimationPacket::new), - CLIENT_UPDATE_INTERACTION(ClientUpdateInteractionPacket.class, ClientUpdateInteractionPacket::new); + CLIENT_UPDATE_INTERACTION(ClientUpdateInteractionPacket.class, ClientUpdateInteractionPacket::new), + CLIENT_UPDATE_ANIMATOR(ClientUpdateAnimatorPacket.class, ClientUpdateAnimatorPacket::new); private final PacketType packet; - ModPacket( - Class type, - Function decoder, - BiConsumer handler, - NetworkDirection direction - ) { - packet = new PacketType<>(type, decoder, handler, direction); - } - ModPacket( Class type, Function decoder, diff --git a/src/main/java/net/quepierts/simple_animator/core/network/packet/AnimatorPacket.java b/src/main/java/net/quepierts/simple_animator/core/network/packet/AnimatorDataPacket.java similarity index 72% rename from src/main/java/net/quepierts/simple_animator/core/network/packet/AnimatorPacket.java rename to src/main/java/net/quepierts/simple_animator/core/network/packet/AnimatorDataPacket.java index 44669ef..388de01 100644 --- a/src/main/java/net/quepierts/simple_animator/core/network/packet/AnimatorPacket.java +++ b/src/main/java/net/quepierts/simple_animator/core/network/packet/AnimatorDataPacket.java @@ -2,17 +2,16 @@ import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; import net.minecraftforge.network.NetworkEvent; import net.quepierts.simple_animator.core.SimpleAnimator; -import net.quepierts.simple_animator.core.animation.Animator; -import net.quepierts.simple_animator.core.animation.AnimationState; -import net.quepierts.simple_animator.core.network.BiPacket; +import net.quepierts.simple_animator.core.common.animation.Animator; +import net.quepierts.simple_animator.core.common.animation.AnimationState; import net.quepierts.simple_animator.core.network.ModNetwork; import java.util.UUID; -public class AnimatorPacket extends BiPacket { - private final UUID uuid; +public class AnimatorDataPacket extends UserPacket { public final ResourceLocation animationLocation; public final AnimationState curState; public final AnimationState nextState; @@ -21,8 +20,8 @@ public class AnimatorPacket extends BiPacket { public final boolean publish; - public AnimatorPacket(FriendlyByteBuf byteBuf) { - this.uuid = byteBuf.readUUID(); + public AnimatorDataPacket(FriendlyByteBuf byteBuf) { + super(byteBuf); this.animationLocation = byteBuf.readResourceLocation(); this.curState = byteBuf.readEnum(AnimationState.class); this.nextState = byteBuf.readEnum(AnimationState.class); @@ -31,8 +30,8 @@ public AnimatorPacket(FriendlyByteBuf byteBuf) { this.publish = byteBuf.readBoolean(); } - public AnimatorPacket(UUID uuid, ResourceLocation animation, AnimationState curState, AnimationState nextState, Animator.ProcessState proState, float timer, boolean publish) { - this.uuid = uuid; + public AnimatorDataPacket(UUID uuid, ResourceLocation animation, AnimationState curState, AnimationState nextState, Animator.ProcessState proState, float timer, boolean publish) { + super(uuid); this.animationLocation = animation; this.curState = curState; this.nextState = nextState; @@ -41,8 +40,12 @@ public AnimatorPacket(UUID uuid, ResourceLocation animation, AnimationState curS this.publish = publish; } - public AnimatorPacket(Animator animator, boolean publish) { - this.uuid = animator.getUuid(); + public AnimatorDataPacket(Animator animator) { + this(animator, false); + } + + public AnimatorDataPacket(Animator animator, boolean publish) { + super(animator.getUuid()); this.animationLocation = animator.getAnimationLocation(); this.curState = animator.getCurState(); this.nextState = animator.getNextState(); @@ -53,7 +56,7 @@ public AnimatorPacket(Animator animator, boolean publish) { @Override public void write(FriendlyByteBuf buffer) { - buffer.writeUUID(this.uuid); + buffer.writeUUID(this.owner); buffer.writeResourceLocation(this.animationLocation); buffer.writeEnum(this.curState); buffer.writeEnum(this.nextState); @@ -63,21 +66,21 @@ public void write(FriendlyByteBuf buffer) { } @Override - public void update(NetworkEvent.Context context) { - SimpleAnimator.getInstance().getProxy().getAnimatorManager().get(this.uuid).sync(this); + public void update(NetworkEvent.Context context, ServerPlayer sender) { + SimpleAnimator.getInstance().getProxy().getAnimatorManager().get(this.owner).sync(this); if (publish) ModNetwork.sendToPlayers(this, context.getSender()); } @Override public void sync(NetworkEvent.Context context) { - SimpleAnimator.getInstance().getProxy().getAnimatorManager().get(uuid).sync(this); + SimpleAnimator.getInstance().getProxy().getAnimatorManager().get(owner).sync(this); } @Override public String toString() { return "AnimatorPacket{" + - "uuid=" + uuid + + "uuid=" + owner + ", animationLocation=" + animationLocation + ", curState=" + curState + ", nextState=" + nextState + diff --git a/src/main/java/net/quepierts/simple_animator/core/network/packet/PlayPacket.java b/src/main/java/net/quepierts/simple_animator/core/network/packet/AnimatorPlayPacket.java similarity index 73% rename from src/main/java/net/quepierts/simple_animator/core/network/packet/PlayPacket.java rename to src/main/java/net/quepierts/simple_animator/core/network/packet/AnimatorPlayPacket.java index c76601a..023166d 100644 --- a/src/main/java/net/quepierts/simple_animator/core/network/packet/PlayPacket.java +++ b/src/main/java/net/quepierts/simple_animator/core/network/packet/AnimatorPlayPacket.java @@ -2,20 +2,21 @@ import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; import net.minecraftforge.network.NetworkEvent; import net.quepierts.simple_animator.core.SimpleAnimator; import net.quepierts.simple_animator.core.network.ModNetwork; import java.util.UUID; -public class PlayPacket extends UserPacket { +public class AnimatorPlayPacket extends UserPacket { public final ResourceLocation animation; - public PlayPacket(FriendlyByteBuf byteBuf) { + public AnimatorPlayPacket(FriendlyByteBuf byteBuf) { super(byteBuf); this.animation = byteBuf.readResourceLocation(); } - public PlayPacket(UUID uuid, ResourceLocation animation) { + public AnimatorPlayPacket(UUID uuid, ResourceLocation animation) { super(uuid); this.animation = animation; } @@ -27,14 +28,14 @@ public void write(FriendlyByteBuf buffer) { } @Override - public void update(NetworkEvent.Context context) { - SimpleAnimator.getInstance().getProxy().getAnimatorManager().get(uuid).play(animation); + public void update(NetworkEvent.Context context, ServerPlayer sender) { + SimpleAnimator.getInstance().getProxy().getAnimatorManager().get(this.owner).play(animation); ModNetwork.sendToPlayers(this, context.getSender()); } @Override public void sync(NetworkEvent.Context context) { SimpleAnimator.LOGGER.info("Handle Sync Play"); - SimpleAnimator.getInstance().getProxy().getAnimatorManager().get(uuid).play(animation); + SimpleAnimator.getInstance().getProxy().getAnimatorManager().get(owner).play(animation); } } diff --git a/src/main/java/net/quepierts/simple_animator/core/network/packet/StopPacket.java b/src/main/java/net/quepierts/simple_animator/core/network/packet/AnimatorStopPacket.java similarity index 65% rename from src/main/java/net/quepierts/simple_animator/core/network/packet/StopPacket.java rename to src/main/java/net/quepierts/simple_animator/core/network/packet/AnimatorStopPacket.java index 4a9ec32..20602ca 100644 --- a/src/main/java/net/quepierts/simple_animator/core/network/packet/StopPacket.java +++ b/src/main/java/net/quepierts/simple_animator/core/network/packet/AnimatorStopPacket.java @@ -1,29 +1,30 @@ package net.quepierts.simple_animator.core.network.packet; import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; import net.minecraftforge.network.NetworkEvent; import net.quepierts.simple_animator.core.SimpleAnimator; import net.quepierts.simple_animator.core.network.ModNetwork; import java.util.UUID; -public class StopPacket extends UserPacket { - public StopPacket(FriendlyByteBuf byteBuf) { +public class AnimatorStopPacket extends UserPacket { + public AnimatorStopPacket(FriendlyByteBuf byteBuf) { super(byteBuf); } - public StopPacket(UUID uuid) { + public AnimatorStopPacket(UUID uuid) { super(uuid); } @Override - public void update(NetworkEvent.Context context) { - SimpleAnimator.getInstance().getProxy().getAnimatorManager().get(this.uuid).stop(); + public void update(NetworkEvent.Context context, ServerPlayer sender) { + SimpleAnimator.getInstance().getProxy().getAnimatorManager().get(this.owner).stop(); ModNetwork.sendToPlayers(this, context.getSender()); } @Override public void sync(NetworkEvent.Context context) { - SimpleAnimator.getInstance().getProxy().getAnimatorManager().get(this.uuid).stop(); + SimpleAnimator.getInstance().getProxy().getAnimatorManager().get(this.owner).stop(); } } diff --git a/src/main/java/net/quepierts/simple_animator/core/network/packet/InteractAcceptPacket.java b/src/main/java/net/quepierts/simple_animator/core/network/packet/InteractAcceptPacket.java index 8ef9a4d..31d3a8e 100644 --- a/src/main/java/net/quepierts/simple_animator/core/network/packet/InteractAcceptPacket.java +++ b/src/main/java/net/quepierts/simple_animator/core/network/packet/InteractAcceptPacket.java @@ -1,26 +1,56 @@ package net.quepierts.simple_animator.core.network.packet; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.player.Player; import net.minecraftforge.network.NetworkEvent; +import net.quepierts.simple_animator.core.SimpleAnimator; +import net.quepierts.simple_animator.core.network.ModNetwork; +import net.quepierts.simple_animator.core.proxy.CommonProxy; import java.util.UUID; public class InteractAcceptPacket extends UserPacket { + private final UUID target; + public InteractAcceptPacket(FriendlyByteBuf byteBuf) { super(byteBuf); + this.target = byteBuf.readUUID(); } - public InteractAcceptPacket(UUID uuid) { - super(uuid); + public InteractAcceptPacket(UUID requester, UUID receiver) { + super(requester); + this.target = receiver; } @Override - public void update(NetworkEvent.Context context) { + public void write(FriendlyByteBuf buffer) { + super.write(buffer); + buffer.writeUUID(this.target); + } + + @Override + public void update(NetworkEvent.Context context, ServerPlayer sender) { + CommonProxy proxy = SimpleAnimator.getInstance().getProxy(); + + ServerPlayer target = (ServerPlayer) sender.serverLevel().getPlayerByUUID(this.target); + if (target == null) + return; + if (proxy.getInteractionManager().accept(sender, target)) { + ModNetwork.sendToPlayers(this, sender); + } } @Override protected void sync(NetworkEvent.Context context) { + ClientLevel level = Minecraft.getInstance().level; + Player requester = level.getPlayerByUUID(this.owner); + Player target = level.getPlayerByUUID(this.target); + SimpleAnimator.LOGGER.info("Accept"); + SimpleAnimator.getInstance().getProxy().getInteractionManager().accept(requester, target); } } diff --git a/src/main/java/net/quepierts/simple_animator/core/network/packet/InteractCancelPacket.java b/src/main/java/net/quepierts/simple_animator/core/network/packet/InteractCancelPacket.java new file mode 100644 index 0000000..7172be0 --- /dev/null +++ b/src/main/java/net/quepierts/simple_animator/core/network/packet/InteractCancelPacket.java @@ -0,0 +1,31 @@ +package net.quepierts.simple_animator.core.network.packet; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import net.minecraftforge.network.NetworkEvent; +import net.quepierts.simple_animator.core.SimpleAnimator; +import net.quepierts.simple_animator.core.network.ModNetwork; + +import java.util.UUID; + +public class InteractCancelPacket extends UserPacket { + + public InteractCancelPacket(FriendlyByteBuf byteBuf) { + super(byteBuf); + } + + public InteractCancelPacket(UUID uuid) { + super(uuid); + } + + @Override + protected void update(NetworkEvent.Context context, ServerPlayer sender) { + SimpleAnimator.getInstance().getProxy().getInteractionManager().cancel(this.owner); + ModNetwork.sendToPlayers(this, sender); + } + + @Override + protected void sync(NetworkEvent.Context context) { + SimpleAnimator.getInstance().getProxy().getInteractionManager().cancel(this.owner); + } +} diff --git a/src/main/java/net/quepierts/simple_animator/core/network/packet/InteractInvitePacket.java b/src/main/java/net/quepierts/simple_animator/core/network/packet/InteractInvitePacket.java index a296a5f..9aa8f7b 100644 --- a/src/main/java/net/quepierts/simple_animator/core/network/packet/InteractInvitePacket.java +++ b/src/main/java/net/quepierts/simple_animator/core/network/packet/InteractInvitePacket.java @@ -1,53 +1,71 @@ package net.quepierts.simple_animator.core.network.packet; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.player.Player; import net.minecraftforge.network.NetworkEvent; import net.quepierts.simple_animator.core.SimpleAnimator; -import net.quepierts.simple_animator.core.client.ClientInteractionHandler; import net.quepierts.simple_animator.core.network.ModNetwork; -import net.quepierts.simple_animator.core.proxy.ClientProxy; -import org.jetbrains.annotations.Nullable; +import net.quepierts.simple_animator.core.proxy.CommonProxy; -import java.util.Optional; import java.util.UUID; public class InteractInvitePacket extends UserPacket { + private final UUID target; private final ResourceLocation interaction; public InteractInvitePacket(FriendlyByteBuf byteBuf) { super(byteBuf); - - this.interaction = byteBuf.readOptional(FriendlyByteBuf::readResourceLocation).orElse(null); + this.target= byteBuf.readUUID(); + this.interaction = byteBuf.readResourceLocation(); } - public InteractInvitePacket(UUID uuid, @Nullable ResourceLocation interaction) { + public InteractInvitePacket(UUID uuid, UUID target, ResourceLocation interaction) { super(uuid); + this.target = target; this.interaction = interaction; } @Override public void write(FriendlyByteBuf byteBuf) { - byteBuf.writeOptional(Optional.ofNullable(this.interaction), FriendlyByteBuf::writeResourceLocation); + super.write(byteBuf); + byteBuf.writeUUID(this.target); + byteBuf.writeResourceLocation(interaction); } @Override - public void update(NetworkEvent.Context context) { - ServerPlayer sender = context.getSender(); - assert sender != null; - if (sender.getUUID().equals(this.uuid)) + public void update(NetworkEvent.Context context, ServerPlayer sender) { + CommonProxy proxy = SimpleAnimator.getInstance().getProxy(); + + ServerPlayer target = (ServerPlayer) sender.serverLevel().getPlayerByUUID(this.target); + if (target == null) return; - if (sender.level().getPlayerByUUID(this.uuid) instanceof ServerPlayer player) { - ModNetwork.sendToPlayer(new InteractInvitePacket(sender.getUUID(), this.interaction), player); + if (proxy.getInteractionManager().invite(sender, target, this.interaction)) { + ModNetwork.sendToPlayers(this, sender); } } @Override public void sync(NetworkEvent.Context context) { - ClientProxy proxy = (ClientProxy) SimpleAnimator.getInstance().getProxy(); - ClientInteractionHandler handler = proxy.getInteractionHandler(); - handler.receive(this.uuid, this.interaction); + ClientLevel level = Minecraft.getInstance().level; + Player requester = level.getPlayerByUUID(this.owner); + Player target = level.getPlayerByUUID(this.target); + + if (requester == null || target == null) + return; + + SimpleAnimator.getInstance().getClient().getClientInteractionHandler().invite(requester, target, this.interaction); + } + + public UUID getTarget() { + return target; + } + + public ResourceLocation getInteraction() { + return interaction; } } diff --git a/src/main/java/net/quepierts/simple_animator/core/network/packet/UserPacket.java b/src/main/java/net/quepierts/simple_animator/core/network/packet/UserPacket.java index cb44789..bc72914 100644 --- a/src/main/java/net/quepierts/simple_animator/core/network/packet/UserPacket.java +++ b/src/main/java/net/quepierts/simple_animator/core/network/packet/UserPacket.java @@ -6,21 +6,21 @@ import java.util.UUID; public abstract class UserPacket extends BiPacket { - protected final UUID uuid; + protected final UUID owner; public UserPacket(FriendlyByteBuf byteBuf) { - this.uuid = byteBuf.readUUID(); + this.owner = byteBuf.readUUID(); } public UserPacket(UUID uuid) { - this.uuid = uuid; + this.owner = uuid; } public void write(FriendlyByteBuf buffer) { - buffer.writeUUID(this.uuid); + buffer.writeUUID(this.owner); } - public UUID getUuid() { - return uuid; + public UUID getOwner() { + return owner; } } diff --git a/src/main/java/net/quepierts/simple_animator/core/network/packet/data/ClientUpdateAnimationPacket.java b/src/main/java/net/quepierts/simple_animator/core/network/packet/batch/ClientUpdateAnimationPacket.java similarity index 83% rename from src/main/java/net/quepierts/simple_animator/core/network/packet/data/ClientUpdateAnimationPacket.java rename to src/main/java/net/quepierts/simple_animator/core/network/packet/batch/ClientUpdateAnimationPacket.java index 01ae037..7118484 100644 --- a/src/main/java/net/quepierts/simple_animator/core/network/packet/data/ClientUpdateAnimationPacket.java +++ b/src/main/java/net/quepierts/simple_animator/core/network/packet/batch/ClientUpdateAnimationPacket.java @@ -1,11 +1,11 @@ -package net.quepierts.simple_animator.core.network.packet.data; +package net.quepierts.simple_animator.core.network.packet.batch; import com.google.common.collect.ImmutableMap; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; import net.minecraftforge.network.NetworkEvent; import net.quepierts.simple_animator.core.SimpleAnimator; -import net.quepierts.simple_animator.core.animation.Animation; +import net.quepierts.simple_animator.core.common.animation.Animation; import net.quepierts.simple_animator.core.network.ISync; import java.util.Map; @@ -28,7 +28,7 @@ public void write(FriendlyByteBuf byteBuf) { @Override public void sync(NetworkEvent.Context context) { - SimpleAnimator.getInstance().getProxy().getAnimationManager().handleUpdateAnimations(this); + SimpleAnimator.getInstance().getClient().getAnimationManager().handleUpdateAnimations(this); } public Map getAnimations() { diff --git a/src/main/java/net/quepierts/simple_animator/core/network/packet/batch/ClientUpdateAnimatorPacket.java b/src/main/java/net/quepierts/simple_animator/core/network/packet/batch/ClientUpdateAnimatorPacket.java new file mode 100644 index 0000000..667ba48 --- /dev/null +++ b/src/main/java/net/quepierts/simple_animator/core/network/packet/batch/ClientUpdateAnimatorPacket.java @@ -0,0 +1,59 @@ +package net.quepierts.simple_animator.core.network.packet.batch; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraftforge.network.NetworkEvent; +import net.quepierts.simple_animator.core.SimpleAnimator; +import net.quepierts.simple_animator.core.common.animation.AnimationState; +import net.quepierts.simple_animator.core.common.animation.Animator; +import net.quepierts.simple_animator.core.network.ISync; +import net.quepierts.simple_animator.core.network.packet.AnimatorDataPacket; + +import java.util.ArrayList; +import java.util.List; + +public class ClientUpdateAnimatorPacket implements ISync { + private final List animators; + + public ClientUpdateAnimatorPacket(List animators) { + this.animators = animators; + } + + public ClientUpdateAnimatorPacket(FriendlyByteBuf byteBuf) { + int capacity = byteBuf.readInt(); + this.animators = new ArrayList<>(capacity); + + for (int i = 0; i < capacity; i++) { + this.animators.add(new AnimatorDataPacket( + byteBuf.readUUID(), + byteBuf.readResourceLocation(), + byteBuf.readEnum(AnimationState.class), + byteBuf.readEnum(AnimationState.class), + byteBuf.readEnum(Animator.ProcessState.class), + byteBuf.readFloat(), + false + )); + } + } + + @Override + public void write(FriendlyByteBuf byteBuf) { + byteBuf.writeInt(this.animators.size()); + for (AnimatorDataPacket packet : this.animators) { + byteBuf.writeUUID(packet.getOwner()); + byteBuf.writeResourceLocation(packet.animationLocation); + byteBuf.writeEnum(packet.curState); + byteBuf.writeEnum(packet.nextState); + byteBuf.writeEnum(packet.procState); + byteBuf.writeFloat(packet.timer); + } + } + + @Override + public void sync(NetworkEvent.Context context) { + SimpleAnimator.getInstance().getClient().getClientAnimatorManager().handleUpdateAnimator(this); + } + + public List getAnimators() { + return animators; + } +} diff --git a/src/main/java/net/quepierts/simple_animator/core/network/packet/data/ClientUpdateInteractionPacket.java b/src/main/java/net/quepierts/simple_animator/core/network/packet/batch/ClientUpdateInteractionPacket.java similarity index 83% rename from src/main/java/net/quepierts/simple_animator/core/network/packet/data/ClientUpdateInteractionPacket.java rename to src/main/java/net/quepierts/simple_animator/core/network/packet/batch/ClientUpdateInteractionPacket.java index 6a83489..f4881da 100644 --- a/src/main/java/net/quepierts/simple_animator/core/network/packet/data/ClientUpdateInteractionPacket.java +++ b/src/main/java/net/quepierts/simple_animator/core/network/packet/batch/ClientUpdateInteractionPacket.java @@ -1,11 +1,11 @@ -package net.quepierts.simple_animator.core.network.packet.data; +package net.quepierts.simple_animator.core.network.packet.batch; import com.google.common.collect.ImmutableMap; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; import net.minecraftforge.network.NetworkEvent; import net.quepierts.simple_animator.core.SimpleAnimator; -import net.quepierts.simple_animator.core.animation.Interaction; +import net.quepierts.simple_animator.core.common.animation.Interaction; import net.quepierts.simple_animator.core.network.ISync; import java.util.Map; @@ -32,7 +32,7 @@ public void write(FriendlyByteBuf byteBuf) { @Override public void sync(NetworkEvent.Context context) { - SimpleAnimator.getInstance().getProxy().getAnimationManager().handleUpdateInteractions(this); + SimpleAnimator.getInstance().getClient().getAnimationManager().handleUpdateInteractions(this); } public Map getInteractions() { diff --git a/src/main/java/net/quepierts/simple_animator/core/proxy/ClientProxy.java b/src/main/java/net/quepierts/simple_animator/core/proxy/ClientProxy.java index e49fb1d..d7a56b6 100644 --- a/src/main/java/net/quepierts/simple_animator/core/proxy/ClientProxy.java +++ b/src/main/java/net/quepierts/simple_animator/core/proxy/ClientProxy.java @@ -7,35 +7,38 @@ import net.minecraft.world.entity.player.Player; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.client.event.InputEvent; import net.minecraftforge.client.event.MovementInputUpdateEvent; import net.minecraftforge.client.event.ViewportEvent; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.TickEvent; import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.quepierts.simple_animator.core.animation.ModelBone; import net.quepierts.simple_animator.core.client.ClientAnimator; import net.quepierts.simple_animator.core.client.ClientAnimatorManager; +import net.quepierts.simple_animator.core.client.ClientInteractionManager; import net.quepierts.simple_animator.core.client.ClientPlayerNavigator; -import net.quepierts.simple_animator.core.client.ClientInteractionHandler; +import net.quepierts.simple_animator.core.common.animation.ModelBone; import net.quepierts.simple_animator.core.network.ModNetwork; -import net.quepierts.simple_animator.core.network.packet.StopPacket; +import net.quepierts.simple_animator.core.network.packet.AnimatorStopPacket; +import net.quepierts.simple_animator.core.network.packet.InteractCancelPacket; + +import java.util.UUID; @OnlyIn(Dist.CLIENT) public class ClientProxy extends CommonProxy { public final ClientPlayerNavigator navigator; - private final ClientInteractionHandler handler; public ClientProxy() { - navigator = new ClientPlayerNavigator(); - handler = new ClientInteractionHandler(this); + this.navigator = new ClientPlayerNavigator(); + this.interactionManager = new ClientInteractionManager(this); + this.animatorManager = new ClientAnimatorManager(); } @Override public void setup(IEventBus bus) { super.setup(bus); MinecraftForge.EVENT_BUS.register(new ForgeHandler()); - this.animatorManager = new ClientAnimatorManager(); } /*public void onRegisterClientReloadListeners(RegisterClientReloadListenersEvent event) { @@ -47,12 +50,12 @@ public boolean isClient() { return true; } - public ClientAnimatorManager getAnimatorManager() { + public ClientAnimatorManager getClientAnimatorManager() { return (ClientAnimatorManager) this.animatorManager; } - public ClientInteractionHandler getInteractionHandler() { - return this.handler; + public ClientInteractionManager getClientInteractionHandler() { + return (ClientInteractionManager) this.interactionManager; } public ClientPlayerNavigator getNavigator() { @@ -84,26 +87,51 @@ public void onClientTick(TickEvent.ClientTickEvent event) { @SubscribeEvent public void onPlayerTick(TickEvent.PlayerTickEvent event) { if (navigator.isNavigating() && event.phase == TickEvent.Phase.END && event.player instanceof LocalPlayer player) { - navigator.tick(player); + navigator.tick(); } } @SubscribeEvent public void onMovementInputUpdate(MovementInputUpdateEvent event) { LocalPlayer player = Minecraft.getInstance().player; - ClientAnimator animator = getAnimatorManager().getAnimator(player.getUUID()); Input input = event.getInput(); - if (animator.isRunning() && !animator.getAnimation().isMovable()) { - if (animator.canStop() && animator.getAnimation().isAbortable() && - (input.forwardImpulse != 0 || input.leftImpulse != 0 || input.jumping || input.shiftKeyDown)) { - animator.stop(); - ModNetwork.sendToServer(new StopPacket(player.getUUID())); + boolean hasInput = input.forwardImpulse != 0 || input.leftImpulse != 0 || input.jumping || input.shiftKeyDown; + + if (hasInput) { + UUID uuid = player.getUUID(); + if (getNavigator().isNavigating()) { + getNavigator().stop(); + } + + if (getClientInteractionHandler().requesting()) { + getClientInteractionHandler().cancel(uuid); + ModNetwork.sendToServer(new InteractCancelPacket(uuid)); + return; + } + + ClientAnimator animator = getClientAnimatorManager().getLocalAnimator(); + + if (animator.isRunning() && !animator.getAnimation().isMovable()) { + if (animator.canStop() && animator.getAnimation().isAbortable()) { + animator.stop(); + ModNetwork.sendToServer(new AnimatorStopPacket(uuid)); + } + + input.forwardImpulse = 0.0f; + input.leftImpulse = 0.0f; + input.jumping = false; + input.shiftKeyDown = false; } + } + } + + @SubscribeEvent + public void onInteractionKeyMappingTriggered(InputEvent.InteractionKeyMappingTriggered event) { + ClientAnimator animator = getClientAnimatorManager().getLocalAnimator(); - input.forwardImpulse = 0.0f; - input.leftImpulse = 0.0f; - input.jumping = false; - input.shiftKeyDown = false; + if (animator.isRunning() && animator.getAnimation().isOverride()) { + event.setCanceled(true); + event.setSwingHand(false); } } @@ -112,7 +140,7 @@ public void onComputeCameraAngles(ViewportEvent.ComputeCameraAngles event) { if (Minecraft.getInstance().options.getCameraType() != CameraType.FIRST_PERSON) return; - ClientAnimator animator = getAnimatorManager().getLocalAnimator(); + ClientAnimator animator = getClientAnimatorManager().getLocalAnimator(); if (animator.isRunning() && animator.getAnimation().isOverride() && animator.isProcessed()) { ClientAnimator.Cache root = animator.getCache(ModelBone.ROOT); diff --git a/src/main/java/net/quepierts/simple_animator/core/proxy/CommonProxy.java b/src/main/java/net/quepierts/simple_animator/core/proxy/CommonProxy.java index 4638bec..d450780 100644 --- a/src/main/java/net/quepierts/simple_animator/core/proxy/CommonProxy.java +++ b/src/main/java/net/quepierts/simple_animator/core/proxy/CommonProxy.java @@ -12,9 +12,10 @@ import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; -import net.quepierts.simple_animator.core.animation.AnimationManager; -import net.quepierts.simple_animator.core.animation.Animator; -import net.quepierts.simple_animator.core.common.AnimatorManager; +import net.quepierts.simple_animator.core.common.animation.AnimationManager; +import net.quepierts.simple_animator.core.common.animation.Animator; +import net.quepierts.simple_animator.core.common.animation.InteractionManager; +import net.quepierts.simple_animator.core.common.animation.AnimatorManager; import net.quepierts.simple_animator.core.common.command.AnimateCommand; import net.quepierts.simple_animator.core.common.command.InteractCommand; import net.quepierts.simple_animator.core.network.ModNetwork; @@ -27,12 +28,12 @@ public class CommonProxy { protected AnimatorManager animatorManager; protected AnimationManager animationManager; + protected InteractionManager interactionManager; public CommonProxy() { - if (!isClient()) { - animatorManager = new AnimatorManager<>(); - } + this.animatorManager = new AnimatorManager<>(); this.animationManager = new AnimationManager(); + this.interactionManager = new InteractionManager(); } public void setup(IEventBus bus) { @@ -58,6 +59,10 @@ public AnimationManager getAnimationManager() { return animationManager; } + public InteractionManager getInteractionManager() { + return interactionManager; + } + private class ForgeHandler { @SubscribeEvent public void onCommandRegister(RegisterCommandsEvent event) { diff --git a/src/main/resources/assets/simple_animator/lang/en_us.json b/src/main/resources/assets/simple_animator/lang/en_us.json index 8c66719..98f7383 100644 --- a/src/main/resources/assets/simple_animator/lang/en_us.json +++ b/src/main/resources/assets/simple_animator/lang/en_us.json @@ -1,3 +1,5 @@ { - "animator.commands.failed.invalid_source": "Invalid execute source for command" + "animator.commands.failed.invalid_source": "Invalid execute source for command", + "animator.commands.failed.same_player": "You cannot get request from your self", + "animator.commands.failed.nonexistent_request": "Nonexistent request" } \ No newline at end of file