diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/PlaceableSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/PlaceableSpell.java index 652009c1..3738f171 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/PlaceableSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/PlaceableSpell.java @@ -103,7 +103,6 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS @Override public boolean tick(Caster source, Situation situation) { - System.out.println("Placed Tick: " + source + " " + source.isClient() + " " + situation); if (situation == Situation.BODY) { if (!source.isClient()) { if (dimension == null) { diff --git a/src/main/java/com/minelittlepony/unicopia/entity/Living.java b/src/main/java/com/minelittlepony/unicopia/entity/Living.java index 029922b9..45d15e84 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/Living.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/Living.java @@ -102,7 +102,7 @@ public abstract class Living implements Equine, Caste private final ItemTracker armour = addTicker(new ItemTracker(this)); private final Transportation transportation = new Transportation<>(this); - private final DataTrackerManager trackers; + protected final DataTrackerManager trackers; protected final DataTracker tracker; protected final DataTracker.Entry carrierId; @@ -487,6 +487,7 @@ public abstract class Living implements Equine, Caste public void toNBT(NbtCompound compound) { enchants.toNBT(compound); spells.getSlots().toNBT(compound); + getCarrierId().ifPresent(id -> compound.putUuid("carrier", id)); toSyncronisedNbt(compound); } @@ -494,19 +495,18 @@ public abstract class Living implements Equine, Caste public void fromNBT(NbtCompound compound) { enchants.fromNBT(compound); spells.getSlots().fromNBT(compound); + setCarrier(compound.containsUuid("carrier") ? compound.getUuid("carrier") : null); fromSynchronizedNbt(compound); } @Override public void toSyncronisedNbt(NbtCompound compound) { compound.put("armour", armour.toNBT()); - getCarrierId().ifPresent(id -> compound.putUuid("carrier", id)); } @Override public void fromSynchronizedNbt(NbtCompound compound) { armour.fromNBT(compound.getCompound("armour")); - setCarrier(compound.containsUuid("carrier") ? compound.getUuid("carrier") : null); } public void updateVelocity() { diff --git a/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java b/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java index b819834e..3546231d 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java @@ -111,6 +111,12 @@ public class Pony extends Living implements Copyable, Update public Pony(PlayerEntity player) { super(player); + trackers.addPacketEmitter((sender, initial) -> { + if (initial || dirty) { + dirty = false; + sender.accept(Channel.SERVER_PLAYER_CAPABILITIES.toPacket(new MsgPlayerCapabilities(this))); + } + }); race = this.tracker.startTracking(TrackableDataType.of(Race.PACKET_CODEC), Race.HUMAN); suppressedRace = this.tracker.startTracking(TrackableDataType.of(Race.PACKET_CODEC), Race.HUMAN); this.levels = new PlayerLevelStore(this, tracker, true, USounds.Vanilla.ENTITY_PLAYER_LEVELUP); @@ -314,19 +320,6 @@ public class Pony extends Living implements Copyable, Update dirty = true; } - private void sendCapabilities() { - if (!dirty) { - return; - } - dirty = false; - - if (entity instanceof ServerPlayerEntity) { - MsgOtherPlayerCapabilities packet = new MsgOtherPlayerCapabilities(this); - Channel.SERVER_PLAYER_CAPABILITIES.sendToPlayer(packet, (ServerPlayerEntity)entity); - Channel.SERVER_OTHER_PLAYER_CAPABILITIES.sendToSurroundingPlayers(packet, entity); - } - } - public AbilityDispatcher getAbilities() { return powers; } @@ -582,8 +575,6 @@ public class Pony extends Living implements Copyable, Update setSpecies(newRace); } } - - sendCapabilities(); } @Override @@ -825,10 +816,28 @@ public class Pony extends Living implements Copyable, Update } @Override - public void toSyncronisedNbt(NbtCompound compound) { - super.toSyncronisedNbt(compound); + public void toNBT(NbtCompound compound) { compound.putString("playerSpecies", Race.REGISTRY.getId(getSpecies()).toString()); compound.putString("suppressedSpecies", Race.REGISTRY.getId(getSuppressedRace()).toString()); + compound.put("mana", mana.toNBT()); + compound.putInt("levels", levels.get()); + compound.putInt("corruption", corruption.get()); + super.toNBT(compound); + } + + @Override + public void fromNBT(NbtCompound compound) { + setSpecies(Race.fromName(compound.getString("playerSpecies"), Race.HUMAN)); + setSuppressedRace(Race.fromName(compound.getString("suppressedSpecies"), Race.UNSET)); + levels.set(compound.getInt("levels")); + corruption.set(compound.getInt("corruption")); + mana.fromNBT(compound.getCompound("mana")); + super.fromNBT(compound); + } + + @Override + public void toSyncronisedNbt(NbtCompound compound) { + super.toSyncronisedNbt(compound); compound.putFloat("magicExhaustion", magicExhaustion); compound.putInt("ticksInSun", ticksInSun); compound.putBoolean("hasShades", hasShades); @@ -837,12 +846,8 @@ public class Pony extends Living implements Copyable, Update compound.put("gravity", gravity.toNBT()); compound.put("charms", charms.toNBT()); compound.put("discoveries", discoveries.toNBT()); - compound.put("mana", mana.toNBT()); - compound.putInt("levels", levels.get()); - compound.putInt("corruption", corruption.get()); compound.putInt("ticksInvulnerable", ticksInvulnerable); compound.putInt("ticksMetamorphising", ticksMetamorphising); - NbtCompound progress = new NbtCompound(); advancementProgress.forEach((key, count) -> { progress.putInt(key, count); @@ -853,22 +858,16 @@ public class Pony extends Living implements Copyable, Update @Override public void fromSynchronizedNbt(NbtCompound compound) { super.fromSynchronizedNbt(compound); - setSpecies(Race.fromName(compound.getString("playerSpecies"), Race.HUMAN)); - setSuppressedRace(Race.fromName(compound.getString("suppressedSpecies"), Race.UNSET)); powers.fromNBT(compound.getCompound("powers")); gravity.fromNBT(compound.getCompound("gravity")); charms.fromNBT(compound.getCompound("charms")); discoveries.fromNBT(compound.getCompound("discoveries")); - levels.set(compound.getInt("levels")); - corruption.set(compound.getInt("corruption")); - mana.fromNBT(compound.getCompound("mana")); acrobatics.fromNBT(compound.getCompound("acrobatics")); magicExhaustion = compound.getFloat("magicExhaustion"); ticksInvulnerable = compound.getInt("ticksInvulnerable"); ticksInSun = compound.getInt("ticksInSun"); hasShades = compound.getBoolean("hasShades"); ticksMetamorphising = compound.getInt("ticksMetamorphising"); - NbtCompound progress = compound.getCompound("advancementProgress"); advancementProgress.clear(); for (String key : progress.getKeys()) { diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/MixinEntity.java b/src/main/java/com/minelittlepony/unicopia/mixin/MixinEntity.java index 87e78a7a..41927ec9 100644 --- a/src/main/java/com/minelittlepony/unicopia/mixin/MixinEntity.java +++ b/src/main/java/com/minelittlepony/unicopia/mixin/MixinEntity.java @@ -106,13 +106,6 @@ abstract class MixinEntity implements EntityDuck, Trackable { } } - @Inject(method = "tick()V", at = @At("RETURN")) - private void afterTick(CallbackInfo info) { - if (dataTrackerManager != null) { - dataTrackerManager.tick(); - } - } - @Inject(method = "updatePassengerPosition(Lnet/minecraft/entity/Entity;Lnet/minecraft/entity/Entity$PositionUpdater;)V", at = @At("HEAD"), cancellable = true diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/server/MixinEntityTrackerEntry.java b/src/main/java/com/minelittlepony/unicopia/mixin/server/MixinEntityTrackerEntry.java index a33344ad..d25a3e57 100644 --- a/src/main/java/com/minelittlepony/unicopia/mixin/server/MixinEntityTrackerEntry.java +++ b/src/main/java/com/minelittlepony/unicopia/mixin/server/MixinEntityTrackerEntry.java @@ -21,9 +21,16 @@ import net.minecraft.server.network.ServerPlayerEntity; abstract class MixinEntityTrackerEntry { @Shadow private @Final Entity entity; + @Shadow + abstract void sendSyncPacket(Packet packet); + + @Inject(method = "tick()V", at = @At("TAIL")) + private void unicopia_onTick(CallbackInfo info) { + Trackable.of(entity).getDataTrackers().tick(this::sendSyncPacket); + } @Inject(method = "sendPackets", at = @At("RETURN")) - private void onSendPackets(ServerPlayerEntity player, Consumer> sender, CallbackInfo info) { + private void unicopia_onSendPackets(ServerPlayerEntity player, Consumer> sender, CallbackInfo info) { Trackable.of(entity).getDataTrackers().sendInitial(player, sender); } } diff --git a/src/main/java/com/minelittlepony/unicopia/network/Channel.java b/src/main/java/com/minelittlepony/unicopia/network/Channel.java index e9f86d0d..f7464deb 100644 --- a/src/main/java/com/minelittlepony/unicopia/network/Channel.java +++ b/src/main/java/com/minelittlepony/unicopia/network/Channel.java @@ -33,8 +33,7 @@ public interface Channel { S2CPacketType SERVER_RESOURCES = SimpleNetworking.serverToClient(Unicopia.id("resources"), MsgServerResources::new); S2CPacketType SERVER_TRACKED_ENTITY_DATA = SimpleNetworking.serverToClient(Unicopia.id("tracked_entity_date"), MsgTrackedValues::new); - S2CPacketType SERVER_OTHER_PLAYER_CAPABILITIES = SimpleNetworking.serverToClient(Unicopia.id("other_player_capabilities"), MsgOtherPlayerCapabilities::new); - S2CPacketType SERVER_PLAYER_ANIMATION_CHANGE = SimpleNetworking.serverToClient(Unicopia.id("other_player_animation_change"), MsgPlayerAnimationChange::new); + S2CPacketType SERVER_PLAYER_ANIMATION_CHANGE = SimpleNetworking.serverToClient(Unicopia.id("player_animation_change"), MsgPlayerAnimationChange::new); S2CPacketType SERVER_SKY_ANGLE = SimpleNetworking.serverToClient(Unicopia.id("sky_angle"), MsgSkyAngle::new); S2CPacketType CONFIGURATION_CHANGE = SimpleNetworking.serverToClient(Unicopia.id("config"), MsgConfigurationChange::new); S2CPacketType SERVER_ZAP_STAGE = SimpleNetworking.serverToClient(Unicopia.id("zap_stage"), MsgZapAppleStage::new); diff --git a/src/main/java/com/minelittlepony/unicopia/network/MsgOtherPlayerCapabilities.java b/src/main/java/com/minelittlepony/unicopia/network/MsgOtherPlayerCapabilities.java deleted file mode 100644 index d0492f07..00000000 --- a/src/main/java/com/minelittlepony/unicopia/network/MsgOtherPlayerCapabilities.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.minelittlepony.unicopia.network; - -import com.minelittlepony.unicopia.entity.player.Pony; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.network.PacketByteBuf; - -/** - * Sent by the server to update other player's capabilities. - */ -public class MsgOtherPlayerCapabilities extends MsgPlayerCapabilities { - - MsgOtherPlayerCapabilities(PacketByteBuf buffer) { - super(buffer); - } - - public MsgOtherPlayerCapabilities(Pony player) { - super(player); - } - - @Override - protected Pony getRecipient(PlayerEntity sender) { - return Pony.of(MinecraftClient.getInstance().world.getPlayerByUuid(playerId)); - } -} diff --git a/src/main/java/com/minelittlepony/unicopia/network/MsgPlayerCapabilities.java b/src/main/java/com/minelittlepony/unicopia/network/MsgPlayerCapabilities.java index a665b194..5c390078 100644 --- a/src/main/java/com/minelittlepony/unicopia/network/MsgPlayerCapabilities.java +++ b/src/main/java/com/minelittlepony/unicopia/network/MsgPlayerCapabilities.java @@ -3,9 +3,6 @@ package com.minelittlepony.unicopia.network; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.util.UUID; - -import com.minelittlepony.unicopia.Unicopia; import com.minelittlepony.unicopia.entity.player.Pony; import com.sollace.fabwork.api.packets.HandledPacket; @@ -23,12 +20,12 @@ import net.minecraft.nbt.NbtIo; */ public class MsgPlayerCapabilities implements HandledPacket { - protected final UUID playerId; + protected final int playerId; private final NbtCompound compoundTag; MsgPlayerCapabilities(PacketByteBuf buffer) { - playerId = buffer.readUuid(); + playerId = buffer.readInt(); try (InputStream in = new ByteBufInputStream(buffer)) { compoundTag = NbtIo.readCompressed(in); } catch (IOException e) { @@ -37,14 +34,14 @@ public class MsgPlayerCapabilities implements HandledPacket { } public MsgPlayerCapabilities(Pony player) { - playerId = player.asEntity().getUuid(); + playerId = player.asEntity().getId(); compoundTag = new NbtCompound(); player.toSyncronisedNbt(compoundTag); } @Override public void toBuffer(PacketByteBuf buffer) { - buffer.writeUuid(playerId); + buffer.writeInt(playerId); try (OutputStream out = new ByteBufOutputStream(buffer)) { NbtIo.writeCompressed(compoundTag, out); } catch (IOException e) { @@ -53,16 +50,9 @@ public class MsgPlayerCapabilities implements HandledPacket { @Override public void handle(PlayerEntity sender) { - Pony player = getRecipient(sender); - if (player == null) { - Unicopia.LOGGER.warn("Skipping capabilities for unknown player " + playerId.toString()); - return; + Pony player = Pony.of(sender.getWorld().getEntityById(playerId)).orElse(null); + if (player != null) { + player.fromSynchronizedNbt(compoundTag); } - - player.fromSynchronizedNbt(compoundTag); - } - - protected Pony getRecipient(PlayerEntity sender) { - return Pony.of(sender); } } diff --git a/src/main/java/com/minelittlepony/unicopia/network/track/DataTrackerManager.java b/src/main/java/com/minelittlepony/unicopia/network/track/DataTrackerManager.java index f2da876c..f2058a78 100644 --- a/src/main/java/com/minelittlepony/unicopia/network/track/DataTrackerManager.java +++ b/src/main/java/com/minelittlepony/unicopia/network/track/DataTrackerManager.java @@ -5,29 +5,39 @@ import java.util.List; import java.util.function.Consumer; import java.util.function.Supplier; -import com.minelittlepony.unicopia.network.Channel; -import com.minelittlepony.unicopia.util.Tickable; +import org.jetbrains.annotations.Nullable; +import com.minelittlepony.unicopia.network.Channel; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import net.minecraft.entity.Entity; import net.minecraft.network.listener.ClientPlayPacketListener; import net.minecraft.network.packet.Packet; import net.minecraft.server.network.ServerPlayerEntity; -public class DataTrackerManager implements Tickable { +public class DataTrackerManager { private final Entity entity; final boolean isClient; private final List trackers = new ObjectArrayList<>(); private final List> objectTrackers = new ObjectArrayList<>(); - private final DataTracker primaryTracker = checkoutTracker(); + private final List packetEmitters = new ObjectArrayList<>(); + + @Nullable + private DataTracker primaryTracker; public DataTrackerManager(Entity entity) { this.entity = entity; this.isClient = entity.getWorld().isClient; } + public synchronized void addPacketEmitter(PacketEmitter packetEmitter) { + packetEmitters.add(packetEmitter); + } + public DataTracker getPrimaryTracker() { + if (primaryTracker == null) { + primaryTracker = checkoutTracker(); + } return primaryTracker; } @@ -43,13 +53,16 @@ public class DataTrackerManager implements Tickable { return tracker; } - @Override - public void tick() { - if (isClient) { - return; - } - + public void tick(Consumer> sender) { synchronized (this) { + for (var emitter : packetEmitters) { + emitter.sendPackets(sender, false); + } + + if (trackers.isEmpty() && objectTrackers.isEmpty()) { + return; + } + List toTransmit = new ArrayList<>(); List objToTransmit = new ArrayList<>(); @@ -62,13 +75,22 @@ public class DataTrackerManager implements Tickable { objToTransmit, toTransmit ); - Channel.SERVER_TRACKED_ENTITY_DATA.sendToSurroundingPlayers(packet, entity); + sender.accept(Channel.SERVER_TRACKED_ENTITY_DATA.toPacket(packet)); } } } + @SuppressWarnings({ "rawtypes", "unchecked" }) public synchronized void sendInitial(ServerPlayerEntity player, Consumer> sender) { synchronized (this) { + for (var emitter : packetEmitters) { + emitter.sendPackets((Consumer)sender, true); + } + + if (trackers.isEmpty() && objectTrackers.isEmpty()) { + return; + } + List toTransmit = new ArrayList<>(); List objToTransmit = new ArrayList<>(); @@ -100,4 +122,8 @@ public class DataTrackerManager implements Tickable { } } } + + public interface PacketEmitter { + void sendPackets(Consumer> consumer, boolean initial); + } } diff --git a/src/main/java/com/minelittlepony/unicopia/network/track/ObjectTracker.java b/src/main/java/com/minelittlepony/unicopia/network/track/ObjectTracker.java index 384fc589..b6e3ec57 100644 --- a/src/main/java/com/minelittlepony/unicopia/network/track/ObjectTracker.java +++ b/src/main/java/com/minelittlepony/unicopia/network/track/ObjectTracker.java @@ -135,7 +135,11 @@ public class ObjectTracker implements NbtSerialisable Map values = new Object2ObjectOpenHashMap<>(); compound.getKeys().forEach(key -> { try { - UUID id = UUID.fromString(key); + UUID id = Util.NIL_UUID; + try { + id = UUID.fromString(key); + } catch (Throwable ignore) {} + if (id != null && !Util.NIL_UUID.equals(id)) { NbtCompound nbt = compound.getCompound(key); T entry = constructor.get(); @@ -143,7 +147,7 @@ public class ObjectTracker implements NbtSerialisable values.put(id, entry); } } catch (Throwable t) { - Unicopia.LOGGER.warn("Exception loading tracked object", t); + Unicopia.LOGGER.warn("Exception loading tracked object: {}", t.getMessage()); } }); synchronized (this) {