diff --git a/src/main/java/io/github/skippyall/minions/Minions.java b/src/main/java/io/github/skippyall/minions/Minions.java index 536c19d..3b793cc 100644 --- a/src/main/java/io/github/skippyall/minions/Minions.java +++ b/src/main/java/io/github/skippyall/minions/Minions.java @@ -1,9 +1,12 @@ package io.github.skippyall.minions; import eu.pb4.polymer.core.api.entity.PolymerEntityUtils; +import io.github.skippyall.minions.fakeplayer.MinionFakePlayer; import io.github.skippyall.minions.minion.MinionItem; +import io.github.skippyall.minions.minion.MinionPersistentState; import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; import net.minecraft.registry.Registries; import net.minecraft.registry.Registry; import net.minecraft.server.MinecraftServer; @@ -11,16 +14,45 @@ import net.minecraft.util.Identifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.ArrayList; +import java.util.List; + public class Minions implements ModInitializer { public static final String MOD_ID = "minions"; public static final MinionItem MINION_ITEM = Registry.register(Registries.ITEM, Identifier.of(MOD_ID, "minion"), new MinionItem(false)); public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID); + + private static final List executeOnNextTick = new ArrayList<>(); + @Override public void onInitialize() { + LOGGER.debug("Add Customthing"); PolymerEntityUtils.registerType(); ServerLifecycleEvents.SERVER_STARTED.register(server -> { + MinionPersistentState.create(server); + MinionPersistentState.INSTANCE.getMinionData().forEach(data -> { + System.out.println("spawn Minion " + data.name); + MinionFakePlayer.spawnMinion(data, server.getOverworld()); + }); + }); + ServerTickEvents.START_SERVER_TICK.register(server -> { + exec(() -> { + for (Runnable run:executeOnNextTick) { + run.run(); + } + executeOnNextTick.clear(); + }); + }); + } + private static synchronized void exec(Runnable run) { + run.run(); + } + + public static void addExecuteOnNextTick(Runnable run) { + exec(() -> { + executeOnNextTick.add(run); }); } } diff --git a/src/main/java/io/github/skippyall/minions/fakeplayer/MinionFakePlayer.java b/src/main/java/io/github/skippyall/minions/fakeplayer/MinionFakePlayer.java index f46bb8c..34c7d80 100644 --- a/src/main/java/io/github/skippyall/minions/fakeplayer/MinionFakePlayer.java +++ b/src/main/java/io/github/skippyall/minions/fakeplayer/MinionFakePlayer.java @@ -4,9 +4,14 @@ import com.mojang.authlib.GameProfile; import com.mojang.authlib.yggdrasil.ProfileResult; import io.github.skippyall.minions.Minions; import io.github.skippyall.minions.minion.MinionInventory; +import io.github.skippyall.minions.minion.MinionItem; +import io.github.skippyall.minions.minion.MinionPersistentState; import io.github.skippyall.minions.minion.ModuleInventory; +import io.github.skippyall.minions.mixins.GameProfileMixin; import io.github.skippyall.minions.program.runtime.MinionRuntime; import net.minecraft.block.BlockState; +import net.minecraft.component.ComponentType; +import net.minecraft.component.DataComponentTypes; import net.minecraft.entity.Entity; import net.minecraft.entity.EquipmentSlot; import net.minecraft.entity.MovementType; @@ -18,13 +23,11 @@ import net.minecraft.item.ItemStack; import net.minecraft.nbt.NbtCompound; import net.minecraft.network.DisconnectionInfo; import net.minecraft.network.NetworkSide; -import net.minecraft.network.packet.StatusPackets; import net.minecraft.network.packet.c2s.common.SyncedClientOptions; import net.minecraft.network.packet.c2s.play.ClientStatusC2SPacket; import net.minecraft.network.packet.s2c.play.EntityPositionS2CPacket; import net.minecraft.network.packet.s2c.play.EntitySetHeadYawS2CPacket; import net.minecraft.network.packet.s2c.play.PlayerListS2CPacket; -import net.minecraft.network.packet.s2c.query.PingResultS2CPacket; import net.minecraft.server.MinecraftServer; import net.minecraft.server.ServerTask; import net.minecraft.server.network.ConnectedClientData; @@ -34,12 +37,12 @@ import net.minecraft.text.Text; import net.minecraft.text.TranslatableTextContent; import net.minecraft.util.ActionResult; import net.minecraft.util.Hand; -import net.minecraft.util.Uuids; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import net.minecraft.world.GameMode; import net.minecraft.world.TeleportTarget; +import java.util.Optional; import java.util.UUID; public class MinionFakePlayer extends ServerPlayerEntity { @@ -56,30 +59,112 @@ public class MinionFakePlayer extends ServerPlayerEntity { public static void createMinion(String username, ServerWorld level, ServerPlayerEntity owner, boolean canProgram, Vec3d pos, double yaw, double pitch) { MinecraftServer server = level.getServer(); server.getUserCache().findByNameAsync(username).thenAcceptAsync((optional) -> { + try { + GameProfile profile = null; + if(optional.isPresent()){ + UUID uuid = optional.get().getId(); + ProfileResult result = server.getSessionService().fetchProfile(uuid, true); + if(result != null) { + profile = result.profile(); + } + } + if(profile == null) { + profile = new GameProfile(new UUID(0,0), username); + } + GameProfile newProfile = new GameProfile(UUID.randomUUID(), username); + newProfile.getProperties().putAll(profile.getProperties()); + GameProfile finalProfile = newProfile; + ((GameProfileMixin)finalProfile).setId(UUID.randomUUID()); + Minions.addExecuteOnNextTick(() -> { + MinionFakePlayer instance = new MinionFakePlayer(server, level, finalProfile, SyncedClientOptions.createDefault(), false, canProgram); + instance.fixStartingPosition = () -> instance.refreshPositionAndAngles(pos.x, pos.y, pos.z, (float) yaw, (float) pitch); + server.getPlayerManager().onPlayerConnect(new FakeClientConnection(NetworkSide.SERVERBOUND), instance, new ConnectedClientData(finalProfile, 0, instance.getClientOptions(), false)); + instance.teleport(level, pos.x, pos.y, pos.z, (float) yaw, (float) pitch); + instance.setHealth(20.0F); + instance.unsetRemoved(); + instance.getAttributeInstance(EntityAttributes.GENERIC_STEP_HEIGHT).setBaseValue(0.6F); + instance.interactionManager.changeGameMode(GameMode.SURVIVAL); + server.getPlayerManager().sendToDimension(new EntitySetHeadYawS2CPacket(instance, (byte) (instance.headYaw * 256 / 360)), level.getRegistryKey());//instance.dimension); + server.getPlayerManager().sendToDimension(new EntityPositionS2CPacket(instance), level.getRegistryKey());//instance.dimension); + //instance.world.getChunkManager(). updatePosition(instance); + instance.dataTracker.set(PLAYER_MODEL_PARTS, (byte) 0x7f); // show all model layers (incl. capes) + instance.getAbilities().flying = false; + MinionPersistentState.INSTANCE.addMinion(instance); + }); + }catch (Throwable ex) { + ex.printStackTrace(); + } + }); + } + + public static void spawnMinion(MinionPersistentState.MinionData data, ServerWorld level) { + MinecraftServer server = level.getServer(); + server.getUserCache().findByNameAsync(data.name).thenAcceptAsync((optional) -> { GameProfile profile = null; - if(optional.isPresent()){ - UUID uuid = optional.get().getId(); - ProfileResult result = server.getSessionService().fetchProfile(uuid, true); - if(result != null) { + if (optional.isPresent()) { + ProfileResult result = server.getSessionService().fetchProfile(optional.get().getId(), true); + if (result != null) { profile = result.profile(); } } - if(profile == null) { - profile = new GameProfile(Uuids.getOfflinePlayerUuid(username), username); + if (profile == null) { + profile = new GameProfile(new UUID(0, 0), data.name); } - MinionFakePlayer instance = new MinionFakePlayer(server, level, profile, SyncedClientOptions.createDefault(), false, canProgram); - instance.fixStartingPosition = () -> instance.refreshPositionAndAngles(pos.x, pos.y, pos.z, (float) yaw, (float) pitch); - server.getPlayerManager().onPlayerConnect(new FakeClientConnection(NetworkSide.SERVERBOUND), instance, new ConnectedClientData(profile, 0, instance.getClientOptions(), false)); - instance.teleport(level, pos.x, pos.y, pos.z, (float) yaw, (float) pitch); - instance.setHealth(20.0F); - instance.unsetRemoved(); - instance.getAttributeInstance(EntityAttributes.GENERIC_STEP_HEIGHT).setBaseValue(0.6F); - instance.interactionManager.changeGameMode(GameMode.SURVIVAL); - server.getPlayerManager().sendToDimension(new EntitySetHeadYawS2CPacket(instance, (byte) (instance.headYaw * 256 / 360)), level.getRegistryKey());//instance.dimension); - server.getPlayerManager().sendToDimension(new EntityPositionS2CPacket(instance), level.getRegistryKey());//instance.dimension); - //instance.world.getChunkManager(). updatePosition(instance); - instance.dataTracker.set(PLAYER_MODEL_PARTS, (byte) 0x7f); // show all model layers (incl. capes) - instance.getAbilities().flying = false; + GameProfile newProfile = new GameProfile(data.uuid, data.name); + newProfile.getProperties().putAll(profile.getProperties()); + GameProfile finalProfile = newProfile; + ((GameProfileMixin)finalProfile).setId(data.uuid); + Minions.addExecuteOnNextTick(() -> { + MinionFakePlayer instance = new MinionFakePlayer(server, level, finalProfile, SyncedClientOptions.createDefault(), false, data.programmable); + System.out.println(instance.getPos()); + server.getPlayerManager().onPlayerConnect(new FakeClientConnection(NetworkSide.SERVERBOUND), instance, new ConnectedClientData(finalProfile, 0, instance.getClientOptions(), false)); + System.out.println(instance.getPos()); + instance.setHealth(20.0F); + instance.unsetRemoved(); + instance.interactionManager.changeGameMode(GameMode.SURVIVAL); + server.getPlayerManager().sendToDimension(new EntitySetHeadYawS2CPacket(instance, (byte) (instance.headYaw * 256 / 360)), level.getRegistryKey());//instance.dimension); + server.getPlayerManager().sendToDimension(new EntityPositionS2CPacket(instance), level.getRegistryKey());//instance.dimension); + //instance.world.getChunkManager(). updatePosition(instance); + instance.dataTracker.set(PLAYER_MODEL_PARTS, (byte) 0x7f); // show all model layers (incl. capes) + instance.getAbilities().flying = false; + }); + }); + } + + public static void spawnMinionAt(MinionPersistentState.MinionData data, ServerWorld level, Vec3d pos, double yaw, double pitch) { + MinecraftServer server = level.getServer(); + server.getUserCache().findByNameAsync(data.name).thenAcceptAsync((optional) -> { + GameProfile profile = null; + if (optional.isPresent()) { + ProfileResult result = server.getSessionService().fetchProfile(optional.get().getId(), true); + if (result != null) { + profile = result.profile(); + } + } + if (profile == null) { + profile = new GameProfile(new UUID(0, 0), data.name); + } + GameProfile newProfile = new GameProfile(data.uuid, data.name); + newProfile.getProperties().putAll(profile.getProperties()); + GameProfile finalProfile = newProfile; + ((GameProfileMixin)finalProfile).setId(data.uuid); + Minions.addExecuteOnNextTick(() -> { + MinionFakePlayer instance = new MinionFakePlayer(server, level, finalProfile, SyncedClientOptions.createDefault(), false, data.programmable); + instance.fixStartingPosition = () -> instance.refreshPositionAndAngles(pos.x, pos.y, pos.z, (float) yaw, (float) pitch); + System.out.println(instance.getPos()); + server.getPlayerManager().onPlayerConnect(new FakeClientConnection(NetworkSide.SERVERBOUND), instance, new ConnectedClientData(finalProfile, 0, instance.getClientOptions(), false)); + System.out.println(instance.getPos()); + instance.teleport(level, pos.x, pos.y, pos.z, (float) yaw, (float) pitch); + instance.setVelocity(0,0,0); + instance.setHealth(20.0F); + instance.unsetRemoved(); + instance.interactionManager.changeGameMode(GameMode.SURVIVAL); + server.getPlayerManager().sendToDimension(new EntitySetHeadYawS2CPacket(instance, (byte) (instance.headYaw * 256 / 360)), level.getRegistryKey());//instance.dimension); + server.getPlayerManager().sendToDimension(new EntityPositionS2CPacket(instance), level.getRegistryKey());//instance.dimension); + //instance.world.getChunkManager(). updatePosition(instance); + instance.dataTracker.set(PLAYER_MODEL_PARTS, (byte) 0x7f); // show all model layers (incl. capes) + instance.getAbilities().flying = false; + }); }); } @@ -117,7 +202,7 @@ public class MinionFakePlayer extends ServerPlayerEntity { { super(server, worldIn, profile, cli); isAShadow = shadow; - + this.programmable = programmable; } public boolean isProgrammable() { @@ -155,11 +240,11 @@ public class MinionFakePlayer extends ServerPlayerEntity { if (!isUsingItem()) super.onEquipStack(slot, previous, stack); } - @Override + /*@Override public void kill() { kill(Text.literal("Killed")); - } + }*/ public void kill(Text reason) { @@ -172,6 +257,8 @@ public class MinionFakePlayer extends ServerPlayerEntity { this.networkHandler.onDisconnected(new DisconnectionInfo(reason)); })); } + + MinionPersistentState.INSTANCE.removeMinion(this); } @Override @@ -269,14 +356,14 @@ public class MinionFakePlayer extends ServerPlayerEntity { float newForward = (float) (moveForward - movement.z); float newSideways = (float) (moveSideways - movement.x); Vec3d newMovement = movement; - if ((newForward < 0 && moveForward >= 0) || (newForward > 0 && moveForward <= 0)) { + if ((newForward < 0 && moveForward > 0) || (newForward > 0 && moveForward < 0)) { newMovement = new Vec3d(newMovement.x, newMovement.y, moveForward); moveForward = 0; getMinionActionPack().setForward(0); }else { moveForward = newForward; } - if ((newSideways < 0 && moveSideways >= 0) || (newSideways > 0 && moveSideways <= 0)) { + if ((newSideways < 0 && moveSideways > 0) || (newSideways > 0 && moveSideways < 0)) { newMovement = new Vec3d(newMovement.x, newMovement.y, moveSideways); moveSideways = 0; getMinionActionPack().setStrafing(0); @@ -289,13 +376,22 @@ public class MinionFakePlayer extends ServerPlayerEntity { @Override protected void drop(ServerWorld world, DamageSource damageSource) { super.drop(world, damageSource); - dropItem(new ItemStack(Minions.MINION_ITEM), true, false); + dropItem(toItemStack(), true, false); for(ItemStack item : moduleInventory.getItems()) { dropItem(item, true, false); } moduleInventory.clear(); } + private ItemStack toItemStack() { + ItemStack stack = new ItemStack(Minions.MINION_ITEM); + MinionItem.setData(MinionPersistentState.MinionData.fromMinion(this), stack); + if (!getMinionName().equals("Minion")) { + stack.set(DataComponentTypes.CUSTOM_NAME, Text.of(getMinionName())); + } + return stack; + } + @Override public void writeCustomDataToNbt(NbtCompound nbt) { super.writeCustomDataToNbt(nbt); @@ -307,4 +403,8 @@ public class MinionFakePlayer extends ServerPlayerEntity { super.readCustomDataFromNbt(nbt); moduleInventory.readNbt(nbt.getCompound("modules"), getRegistryManager()); } + + public String getMinionName() { + return getGameProfile().getName(); + } } \ No newline at end of file diff --git a/src/main/java/io/github/skippyall/minions/minion/MinionItem.java b/src/main/java/io/github/skippyall/minions/minion/MinionItem.java index 33cae11..d385fdc 100644 --- a/src/main/java/io/github/skippyall/minions/minion/MinionItem.java +++ b/src/main/java/io/github/skippyall/minions/minion/MinionItem.java @@ -3,9 +3,14 @@ package io.github.skippyall.minions.minion; import eu.pb4.polymer.core.api.item.PolymerItem; import eu.pb4.polymer.core.api.item.PolymerItemUtils; import io.github.skippyall.minions.fakeplayer.MinionFakePlayer; +import net.minecraft.client.render.VertexFormatElement; +import net.minecraft.component.ComponentType; import net.minecraft.component.DataComponentTypes; +import net.minecraft.component.type.NbtComponent; import net.minecraft.item.*; import net.minecraft.item.tooltip.TooltipType; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtElement; import net.minecraft.registry.RegistryWrapper; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; @@ -41,8 +46,37 @@ public class MinionItem extends Item implements PolymerItem { name = "Minion"; } if(!context.getWorld().isClient) { - MinionFakePlayer.createMinion(name, (ServerWorld) context.getWorld(), (ServerPlayerEntity) context.getPlayer(), canProgram, context.getBlockPos().toCenterPos().add(0,0.5,0), 0, 0); + MinionPersistentState.MinionData data = getData(context.getStack()); + if (data == null) { + MinionFakePlayer.createMinion(name, (ServerWorld) context.getWorld(), (ServerPlayerEntity) context.getPlayer(), canProgram, context.getBlockPos().toCenterPos().add(0,0.5,0), 0, 0); + }else { + MinionFakePlayer.spawnMinionAt(data, (ServerWorld) context.getWorld(), context.getBlockPos().toCenterPos().add(0,0.5,0), 0, 0); + MinionPersistentState.INSTANCE.addMinion(data); + } } return ActionResult.SUCCESS; } + + public static void setData(MinionPersistentState.MinionData data, ItemStack item) { + NbtCompound nbt = item.getOrDefault(DataComponentTypes.CUSTOM_DATA, NbtComponent.DEFAULT).copyNbt(); + nbt.put("data", data.writeNbt()); + item.set(DataComponentTypes.CUSTOM_DATA, NbtComponent.of(nbt)); + } + + @Nullable + public static MinionPersistentState.MinionData getData(ItemStack item) { + NbtCompound nbt = item.getOrDefault(DataComponentTypes.CUSTOM_DATA, NbtComponent.DEFAULT).copyNbt(); + if (nbt.getType("data") == NbtElement.COMPOUND_TYPE) { + return MinionPersistentState.MinionData.readNbt(nbt.getCompound("data")); + } + return null; + } + + public static boolean containsData(ItemStack item) { + NbtComponent nbt = item.get(DataComponentTypes.CUSTOM_DATA); + if (nbt == null) { + return false; + } + return nbt.copyNbt().contains("data"); + } } diff --git a/src/main/java/io/github/skippyall/minions/minion/MinionPersistentState.java b/src/main/java/io/github/skippyall/minions/minion/MinionPersistentState.java index b327ebd..2548902 100644 --- a/src/main/java/io/github/skippyall/minions/minion/MinionPersistentState.java +++ b/src/main/java/io/github/skippyall/minions/minion/MinionPersistentState.java @@ -16,7 +16,7 @@ public class MinionPersistentState extends PersistentState { public static MinionPersistentState INSTANCE; - public static List minionData = new ArrayList<>(); + private List minionData = new ArrayList<>(); @Override public NbtCompound writeNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup registryLookup) { @@ -30,10 +30,42 @@ public class MinionPersistentState extends PersistentState { public static MinionPersistentState read(NbtCompound compound, RegistryWrapper.WrapperLookup lookup) { NbtList list = compound.getList("minions", NbtElement.COMPOUND_TYPE); + MinionPersistentState instance = new MinionPersistentState(); for(NbtElement element : list) { - minionData.add(MinionData.readNbt((NbtCompound) element)); + instance.addMinion(MinionData.readNbt((NbtCompound) element)); } - return new MinionPersistentState(); + return instance; + } + + public void addMinion(MinionFakePlayer minion) { + addMinion(MinionData.fromMinion(minion)); + } + + public void addMinion(MinionData data) { + System.out.println("add Minion " + data.name); + minionData.add(data); + markDirty(); + } + + public void removeMinion(MinionFakePlayer minionData) { + removeMinion(minionData.getUuid()); + } + + public void removeMinion(UUID minionUUID) { + MinionData removal = null; + for (MinionData data : minionData) { + if (data.uuid.equals(minionUUID)) { + removal = data; + } + } + if (removal != null) { + minionData.remove(removal); + } + markDirty(); + } + + public List getMinionData() { + return minionData; } public static void create(MinecraftServer server) { @@ -42,9 +74,13 @@ public class MinionPersistentState extends PersistentState { public static class MinionData { public UUID uuid; + public String name; + public boolean programmable; - public MinionData(UUID uuid) { + public MinionData(UUID uuid, String name, boolean programmable) { this.uuid = uuid; + this.name = name; + this.programmable = programmable; } public NbtCompound writeNbt() { @@ -62,6 +98,8 @@ public class MinionPersistentState extends PersistentState { nbt.put("rotation", rotList);*/ nbt.putUuid("uuid", uuid); + nbt.putString("name", name); + nbt.putBoolean("programmable", programmable); return nbt; } @@ -79,12 +117,14 @@ public class MinionPersistentState extends PersistentState { Vec2f rot = new Vec2f(yaw, pitch);*/ UUID uuid = nbt.getUuid("uuid"); + String name = nbt.getString("name"); + boolean programmable = nbt.getBoolean("programmable"); - return new MinionData(uuid); + return new MinionData(uuid, name, programmable); } public static MinionData fromMinion(MinionFakePlayer minion) { - return new MinionData(minion.getUuid()); + return new MinionData(minion.getUuid(), minion.getMinionName(), minion.isProgrammable()); } } } diff --git a/src/main/java/io/github/skippyall/minions/mixins/ChunkTicketManagerFixMixin.java b/src/main/java/io/github/skippyall/minions/mixins/ChunkTicketManagerFixMixin.java new file mode 100644 index 0000000..a7b3b43 --- /dev/null +++ b/src/main/java/io/github/skippyall/minions/mixins/ChunkTicketManagerFixMixin.java @@ -0,0 +1,29 @@ +package io.github.skippyall.minions.mixins; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import it.unimi.dsi.fastutil.objects.ObjectSet; +import net.minecraft.server.world.ChunkTicketManager; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(value = ChunkTicketManager.class, remap = false) +public class ChunkTicketManagerFixMixin { + @WrapOperation(method = "handleChunkLeave", at = @At(value = "INVOKE", target = "Lit/unimi/dsi/fastutil/objects/ObjectSet;remove(Ljava/lang/Object;)Z")) + public boolean filterIfNull(ObjectSet instance, Object o, Operation original) { + if (instance != null) { + return original.call(instance, o); + } + + return false;//Unused + } + + @WrapOperation(method = "handleChunkLeave", at = @At(value = "INVOKE", target = "Lit/unimi/dsi/fastutil/objects/ObjectSet;isEmpty()Z")) + public boolean filterIfNull(ObjectSet instance, Operation original) { + if (instance != null) { + return original.call(instance); + } + + return true;//Unused + } +} diff --git a/src/main/java/io/github/skippyall/minions/mixins/Debug2Mixin.java b/src/main/java/io/github/skippyall/minions/mixins/Debug2Mixin.java new file mode 100644 index 0000000..3fa0e58 --- /dev/null +++ b/src/main/java/io/github/skippyall/minions/mixins/Debug2Mixin.java @@ -0,0 +1,24 @@ +package io.github.skippyall.minions.mixins; + +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.world.PlayerSaveHandler; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.Optional; + +@Mixin(PlayerSaveHandler.class) +public class Debug2Mixin { + @Inject(method = "method_55788", at = @At("HEAD")) + public void debug(PlayerEntity playerEntity, NbtCompound nbt, CallbackInfoReturnable cir) { + System.out.println("loadPlayerData " + playerEntity.getNameForScoreboard()); + } + + @Inject(method = "loadPlayerData(Lnet/minecraft/entity/player/PlayerEntity;Ljava/lang/String;)Ljava/util/Optional;", at = @At("RETURN")) + public void debug(PlayerEntity player, String extension, CallbackInfoReturnable> cir) { + System.out.println(cir.getReturnValue().isEmpty() + player.getUuidAsString()); + } +} diff --git a/src/main/java/io/github/skippyall/minions/mixins/DebugMixin.java b/src/main/java/io/github/skippyall/minions/mixins/DebugMixin.java new file mode 100644 index 0000000..7512276 --- /dev/null +++ b/src/main/java/io/github/skippyall/minions/mixins/DebugMixin.java @@ -0,0 +1,32 @@ +package io.github.skippyall.minions.mixins; + +import com.llamalad7.mixinextras.sugar.Local; +import io.github.skippyall.minions.fakeplayer.MinionFakePlayer; +import net.minecraft.entity.Entity; +import net.minecraft.nbt.NbtCompound; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +//@Mixin(SectionedEntityCache.class) +@Mixin(Entity.class) +public class DebugMixin { + /*@Inject(method = "forEachInBox", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/math/ChunkSectionPos;asLong(III)J", shift = At.Shift.BEFORE, ordinal = 0)) + private void debug(Box box, LazyIterationConsumer> consumer, CallbackInfo ci) { + System.out.println("call"); + }*/ + @Inject(method = "readNbt", at = @At("HEAD")) + public void debug(NbtCompound nbt, CallbackInfo ci) { + if ((Object) this instanceof MinionFakePlayer) { + System.out.println("readNBT"); + } + } + + @Inject(method = "setPos", at = @At("HEAD")) + public void debug(double x, double y, double z, CallbackInfo ci) { + if ((Object) this instanceof MinionFakePlayer) { + System.out.println("Set Minion Pos to " + x + " " + y + " " + z); + } + } +} diff --git a/src/main/java/io/github/skippyall/minions/mixins/GameProfileMixin.java b/src/main/java/io/github/skippyall/minions/mixins/GameProfileMixin.java new file mode 100644 index 0000000..96bcf99 --- /dev/null +++ b/src/main/java/io/github/skippyall/minions/mixins/GameProfileMixin.java @@ -0,0 +1,15 @@ +package io.github.skippyall.minions.mixins; + +import com.mojang.authlib.GameProfile; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Mutable; +import org.spongepowered.asm.mixin.gen.Accessor; + +import java.util.UUID; + +@Mixin(value = GameProfile.class, remap = false) +public interface GameProfileMixin{ + @Mutable + @Accessor("id") + void setId(UUID id); +} diff --git a/src/main/java/io/github/skippyall/minions/mixins/PlayerListMixin.java b/src/main/java/io/github/skippyall/minions/mixins/PlayerListMixin.java index 6ca61a0..60c8be2 100644 --- a/src/main/java/io/github/skippyall/minions/mixins/PlayerListMixin.java +++ b/src/main/java/io/github/skippyall/minions/mixins/PlayerListMixin.java @@ -2,6 +2,7 @@ package io.github.skippyall.minions.mixins; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; import com.mojang.authlib.GameProfile; import io.github.skippyall.minions.fakeplayer.MinionFakePlayer; import io.github.skippyall.minions.fakeplayer.NetHandlerPlayServerFake; @@ -14,6 +15,8 @@ import net.minecraft.server.network.ConnectedClientData; import net.minecraft.server.network.ServerPlayNetworkHandler; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; +import net.minecraft.text.Text; +import org.apache.logging.log4j.core.jmx.Server; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -50,4 +53,11 @@ public class PlayerListMixin { } return original.call(minecraftServer, serverLevel, gameProfile, clientInformation); } + + @WrapOperation(method = "onPlayerConnect", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/PlayerManager;broadcast(Lnet/minecraft/text/Text;Z)V")) + public void noLoginMessage(PlayerManager instance, Text message, boolean overlay, Operation original, @Local(argsOnly = true) ServerPlayerEntity player) { + if(!(player instanceof MinionFakePlayer)) { + original.call(instance, message, overlay); + } + } } diff --git a/src/main/java/io/github/skippyall/minions/mixins/ServerPlayNetworkHandlerMixin.java b/src/main/java/io/github/skippyall/minions/mixins/ServerPlayNetworkHandlerMixin.java new file mode 100644 index 0000000..0696fa9 --- /dev/null +++ b/src/main/java/io/github/skippyall/minions/mixins/ServerPlayNetworkHandlerMixin.java @@ -0,0 +1,25 @@ +package io.github.skippyall.minions.mixins; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import io.github.skippyall.minions.fakeplayer.MinionFakePlayer; +import net.minecraft.server.PlayerManager; +import net.minecraft.server.network.ServerPlayNetworkHandler; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.Text; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(ServerPlayNetworkHandler.class) +public class ServerPlayNetworkHandlerMixin { + @Shadow + public ServerPlayerEntity player; + + @WrapOperation(method = "cleanUp", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/PlayerManager;broadcast(Lnet/minecraft/text/Text;Z)V")) + public void noLogoutMessage(PlayerManager instance, Text message, boolean overlay, Operation original) { + if(!(player instanceof MinionFakePlayer)) { + original.call(instance, message, overlay); + } + } +} diff --git a/src/main/resources/minions.mixins.json b/src/main/resources/minions.mixins.json index 476382c..ee4de1e 100644 --- a/src/main/resources/minions.mixins.json +++ b/src/main/resources/minions.mixins.json @@ -4,11 +4,16 @@ "package": "io.github.skippyall.minions.mixins", "compatibilityLevel": "JAVA_17", "mixins": [ + "ChunkTicketManagerFixMixin", "ConnectionMixin", + "Debug2Mixin", + "DebugMixin", + "GameProfileMixin", "MinecraftServerMixin", "PlayerListEntryS2CPacket$EntryMixin", "PlayerListMixin", - "ServerPlayerMixin" + "ServerPlayerMixin", + "ServerPlayNetworkHandlerMixin" ], "client": [], "server": [],