diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/server/MixinEntityTrackerEntry.java b/src/main/java/com/minelittlepony/unicopia/mixin/server/MixinEntityTrackerEntry.java new file mode 100644 index 00000000..a33344ad --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/mixin/server/MixinEntityTrackerEntry.java @@ -0,0 +1,29 @@ +package com.minelittlepony.unicopia.mixin.server; + +import java.util.function.Consumer; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import com.minelittlepony.unicopia.network.track.Trackable; + +import net.minecraft.entity.Entity; +import net.minecraft.network.listener.ClientPlayPacketListener; +import net.minecraft.network.packet.Packet; +import net.minecraft.server.network.EntityTrackerEntry; +import net.minecraft.server.network.ServerPlayerEntity; + +@Mixin(EntityTrackerEntry.class) +abstract class MixinEntityTrackerEntry { + @Shadow + private @Final Entity entity; + + @Inject(method = "sendPackets", at = @At("RETURN")) + private void onSendPackets(ServerPlayerEntity player, Consumer> sender, CallbackInfo info) { + Trackable.of(entity).getDataTrackers().sendInitial(player, sender); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/network/track/DataTracker.java b/src/main/java/com/minelittlepony/unicopia/network/track/DataTracker.java index 1c86e164..b730d475 100644 --- a/src/main/java/com/minelittlepony/unicopia/network/track/DataTracker.java +++ b/src/main/java/com/minelittlepony/unicopia/network/track/DataTracker.java @@ -66,8 +66,7 @@ public class DataTracker { } @SuppressWarnings("unchecked") - @Nullable - synchronized void getDirtyPairs(List output) { + private void updateTrackables() { for (var entry : persistentObjects.int2ObjectEntrySet()) { int key = entry.getIntKey(); TrackableObject.Status status = entry.getValue().getStatus(); @@ -76,19 +75,31 @@ public class DataTracker { dirtyIndices.add(key); } } + } + synchronized void getInitialPairs(List output) { + updateTrackables(); + output.add(new MsgTrackedValues.TrackerEntries(id, true, codecs)); + } + + @Nullable + synchronized void getDirtyPairs(List output) { if (initial) { initial = false; dirtyIndices = new IntOpenHashSet(); - output.add(new MsgTrackedValues.TrackerEntries(id, true, codecs)); - } else if (!dirtyIndices.isEmpty()) { - IntSet toSend = dirtyIndices; - dirtyIndices = new IntOpenHashSet(); - List> pairs = new ArrayList<>(); - for (int i : toSend) { - pairs.add(codecs.get(i)); + getInitialPairs(output); + } else { + updateTrackables(); + + if (!dirtyIndices.isEmpty()) { + IntSet toSend = dirtyIndices; + dirtyIndices = new IntOpenHashSet(); + List> pairs = new ArrayList<>(); + for (int i : toSend) { + pairs.add(codecs.get(i)); + } + output.add(new MsgTrackedValues.TrackerEntries(id, false, pairs)); } - output.add(new MsgTrackedValues.TrackerEntries(id, false, pairs)); } } 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 4f945917..f2da876c 100644 --- a/src/main/java/com/minelittlepony/unicopia/network/track/DataTrackerManager.java +++ b/src/main/java/com/minelittlepony/unicopia/network/track/DataTrackerManager.java @@ -2,6 +2,7 @@ package com.minelittlepony.unicopia.network.track; import java.util.ArrayList; import java.util.List; +import java.util.function.Consumer; import java.util.function.Supplier; import com.minelittlepony.unicopia.network.Channel; @@ -9,6 +10,9 @@ import com.minelittlepony.unicopia.util.Tickable; 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 { private final Entity entity; @@ -45,17 +49,12 @@ public class DataTrackerManager implements Tickable { return; } - List toTransmit = new ArrayList<>(); - List objToTransmit = new ArrayList<>(); - synchronized (this) { - for (var entry : trackers) { - entry.getDirtyPairs(toTransmit); - } + List toTransmit = new ArrayList<>(); + List objToTransmit = new ArrayList<>(); - for (var entry : objectTrackers) { - entry.getDirtyPairs(objToTransmit); - } + for (var entry : trackers) entry.getDirtyPairs(toTransmit); + for (var entry : objectTrackers) entry.getDirtyPairs(objToTransmit); if (!toTransmit.isEmpty() || !objToTransmit.isEmpty()) { MsgTrackedValues packet = new MsgTrackedValues( @@ -68,6 +67,25 @@ public class DataTrackerManager implements Tickable { } } + public synchronized void sendInitial(ServerPlayerEntity player, Consumer> sender) { + synchronized (this) { + List toTransmit = new ArrayList<>(); + List objToTransmit = new ArrayList<>(); + + for (var entry : trackers) entry.getInitialPairs(toTransmit); + for (var entry : objectTrackers) entry.getInitialPairs(objToTransmit); + + if (!toTransmit.isEmpty() || !objToTransmit.isEmpty()) { + MsgTrackedValues packet = new MsgTrackedValues( + entity.getId(), + objToTransmit, + toTransmit + ); + sender.accept(Channel.SERVER_TRACKED_ENTITY_DATA.toPacket(packet)); + } + } + } + synchronized void load(MsgTrackedValues packet) { for (var update : packet.updatedTrackers()) { DataTracker tracker = trackers.get(update.id()); 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 b4d00151..384fc589 100644 --- a/src/main/java/com/minelittlepony/unicopia/network/track/ObjectTracker.java +++ b/src/main/java/com/minelittlepony/unicopia/network/track/ObjectTracker.java @@ -73,6 +73,17 @@ public class ObjectTracker implements NbtSerialisable quickAccess = Map.copyOf(trackedObjects); } + synchronized void getInitialPairs(List output) { + if (!trackedObjects.isEmpty()) { + Map trackableCompounds = new HashMap<>(); + quickAccess.entrySet().forEach(object -> { + trackableCompounds.put(object.getKey(), object.getValue().toTrackedNbt()); + }); + + output.add(new MsgTrackedValues.TrackerObjects(id, Set.of(), trackableCompounds)); + } + } + synchronized void getDirtyPairs(List output) { if (!trackedObjects.isEmpty()) { Map trackableCompounds = new HashMap<>(); diff --git a/src/main/java/com/minelittlepony/unicopia/network/track/Trackable.java b/src/main/java/com/minelittlepony/unicopia/network/track/Trackable.java index 5fdcd9a0..6c232740 100644 --- a/src/main/java/com/minelittlepony/unicopia/network/track/Trackable.java +++ b/src/main/java/com/minelittlepony/unicopia/network/track/Trackable.java @@ -3,7 +3,6 @@ package com.minelittlepony.unicopia.network.track; import net.minecraft.entity.Entity; public interface Trackable { - DataTrackerManager getDataTrackers(); static Trackable of(Entity entity) { diff --git a/src/main/resources/unicopia.mixin.json b/src/main/resources/unicopia.mixin.json index 5de80517..17bd2121 100644 --- a/src/main/resources/unicopia.mixin.json +++ b/src/main/resources/unicopia.mixin.json @@ -51,6 +51,7 @@ "MixinWardenEntity", "MixinWorld", "PointOfInterestTypesAccessor", + "server.MixinEntityTrackerEntry", "server.MixinPlayerManager", "server.MixinServerPlayerEntity", "server.MixinServerPlayNetworkHandler",