Skip to content

Commit

Permalink
General fixes and cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
yoshiweegee committed Apr 2, 2024
1 parent 6c31140 commit 18cd32b
Show file tree
Hide file tree
Showing 13 changed files with 194 additions and 85 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,18 @@
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package net.gensokyoreimagined.nitori.core.isolation.net_minecraft_server_level;
package net.gensokyoreimagined.nitori.core;

import com.destroystokyo.paper.util.misc.PooledLinkedHashSets;
import it.unimi.dsi.fastutil.ints.Int2ObjectLinkedOpenHashMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet;
import it.unimi.dsi.fastutil.objects.ReferenceSets;
import net.gensokyoreimagined.nitori.plugins.NitoriConfig;
//import net.gensokyoreimagined.nitori.plugins.NitoriConfig;
import net.gensokyoreimagined.nitori.core.access.IMixinChunkMapAccess;
import net.gensokyoreimagined.nitori.core.access.IMixinChunkMap_TrackedEntityAccess;
import net.gensokyoreimagined.nitori.tracker.MultithreadedTracker;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.ServerEntity;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.network.ServerPlayerConnection;
Expand All @@ -32,6 +33,8 @@
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.gen.Accessor;
import org.spongepowered.asm.mixin.gen.Invoker;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
Expand All @@ -42,73 +45,75 @@
import javax.annotation.Nullable;

@Mixin(ChunkMap.class)
public class ChunkMapMixin {
public class ChunkMapMixin implements IMixinChunkMapAccess {

@Mutable
@Shadow @Final public Int2ObjectMap<ChunkMap.TrackedEntity> entityMap;

// Implementation of 0107-Multithreaded-Tracker.patch
@Shadow @Final
ServerLevel level;
@Final
@Shadow
public ServerLevel level;

// Implementation of 0107-Multithreaded-Tracker.patch
@Unique
private @Nullable MultithreadedTracker multithreadedTracker;
private @Nullable MultithreadedTracker gensouHacks$multithreadedTracker;

// Implementation of 0107-Multithreaded-Tracker.patch
@Unique @Final
private final ConcurrentLinkedQueue<Runnable> trackerMainThreadTasks = new ConcurrentLinkedQueue<>();
@Final
@Unique
private final ConcurrentLinkedQueue<Runnable> gensouHacks$trackerMainThreadTasks = new ConcurrentLinkedQueue<>();

// Implementation of 0107-Multithreaded-Tracker.patch
@Unique
private boolean tracking = false;
private boolean gensouHacks$tracking = false;

@Inject(method = "<init>", at = @At("RETURN"))
private void reassignEntityTrackers(CallbackInfo ci) {
this.entityMap = new Int2ObjectLinkedOpenHashMap<>();
}

// Implementation of 0107-Multithreaded-Tracker.patch
@Override
@Unique
public void runOnTrackerMainThread(final Runnable runnable) {
if (this.tracking) {
this.trackerMainThreadTasks.add(runnable);
public void gensouHacks$runOnTrackerMainThread(final Runnable runnable) {
if (this.gensouHacks$tracking) {
this.gensouHacks$trackerMainThreadTasks.add(runnable);
} else {
runnable.run();
}
}

@Inject(method = "processTrackQueue", at = @At("HEAD"))
@Inject(method = "processTrackQueue", at = @At("HEAD"), cancellable = true)
private void atProcessTrackQueueHead(CallbackInfo callbackInfo) {
// Implementation of 0107-Multithreaded-Tracker.patch
//if (NitoriConfig.enableAsyncEntityTracker) {
if (true) {
if (this.multithreadedTracker == null) {
this.multithreadedTracker = new MultithreadedTracker(this.level.chunkSource.entityTickingChunks, this.trackerMainThreadTasks);
if (this.gensouHacks$multithreadedTracker == null) {
this.gensouHacks$multithreadedTracker = new MultithreadedTracker(this.level.chunkSource.entityTickingChunks, this.gensouHacks$trackerMainThreadTasks);
}

this.tracking = true;
this.gensouHacks$tracking = true;
try {
this.multithreadedTracker.tick();
this.gensouHacks$multithreadedTracker.tick();
} finally {
this.tracking = false;
this.gensouHacks$tracking = false;
}
callbackInfo.cancel();
}
//}
// Mirai end
}

@Mixin(ChunkMap.TrackedEntity.class)
public abstract class TrackedEntity {
// Implementation of 0107-Multithreaded-Tracker.patch
@Shadow @Final
public ServerEntity serverEntity; // Mirai -> public

public static abstract class TrackedEntity implements IMixinChunkMap_TrackedEntityAccess {
// Implementation of 0107-Multithreaded-Tracker.patch
@Shadow @Final
public Entity entity; // Mirai -> public
@Override
@Final
@Accessor
public abstract Entity getEntity(); // Mirai -> public

@Mutable @Shadow @Final
@Final
@Mutable
@Shadow
public Set<ServerPlayerConnection> seenBy;

@Inject(method = "<init>", at = @At("RETURN"))
Expand All @@ -118,16 +123,18 @@ private void reassignSeenBy(CallbackInfo ci) {
}

// Implementation of 0107-Multithreaded-Tracker.patch
@Shadow
public final void updatePlayers(PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<ServerPlayer> newTrackerCandidates) { // Mirai -> public
throw new AssertionError("Mixin failed to apply!");
}
@Override
@Final
@Invoker
public abstract void callUpdatePlayers(PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<ServerPlayer> newTrackerCandidates); // Mirai -> public

// Implementation of 0107-Multithreaded-Tracker.patch
@SuppressWarnings("EmptyMethod")
@Redirect(method = "removePlayer", at = @At(value = "INVOKE", target = "Lorg/spigotmc/AsyncCatcher;catchOp(Ljava/lang/String;)V"))
private void skipSpigotAsyncPlayerTrackerClear(String reason) {} // Mirai - we can remove async too

// Implementation of 0107-Multithreaded-Tracker.patch
@SuppressWarnings("EmptyMethod")
@Redirect(method = "updatePlayer", at = @At(value = "INVOKE", target = "Lorg/spigotmc/AsyncCatcher;catchOp(Ljava/lang/String;)V"))
private void skipSpigotAsyncPlayerTrackerUpdate(String reason) {} // Mirai - we can update async
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,16 @@

import com.destroystokyo.paper.util.maplist.EntityList;
import io.papermc.paper.world.ChunkEntitySlices;
import net.gensokyoreimagined.nitori.core.access.IMixinChunkEntitySlicesAccess;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.gen.Accessor;

@Mixin(ChunkEntitySlices.class)
public abstract class MixinChunkEntitySlices {
public abstract class MixinChunkEntitySlices implements IMixinChunkEntitySlicesAccess {
// Implementation of 0107-Multithreaded-Tracker.patch
@Shadow @Final
public EntityList entities;
@Override
@Final
@Accessor
public abstract EntityList getEntities();
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,17 @@
package net.gensokyoreimagined.nitori.core;

import io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet;
import net.gensokyoreimagined.nitori.core.access.IMixinIteratorSafeOrderedReferenceSetAccess;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.gen.Accessor;

@Mixin(IteratorSafeOrderedReferenceSet.class)
public abstract class MixinIteratorSafeOrderedReferenceSet<E> {
public abstract class MixinIteratorSafeOrderedReferenceSet implements IMixinIteratorSafeOrderedReferenceSetAccess {
// Implementation of 0107-Multithreaded-Tracker.patch
// @Accessor happens to do exactly what is needed, making for nice shorthand
@Accessor @Unique
@Override
@Unique
@Accessor
public abstract int getListSize(); // Mirai - expose listSize
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

import com.google.common.collect.Lists;
import com.llamalad7.mixinextras.sugar.Local;
import net.gensokyoreimagined.nitori.core.isolation.net_minecraft_server_level.ChunkMapMixin;
import net.gensokyoreimagined.nitori.core.access.IMixinChunkMapAccess;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientGamePacketListener;
import net.minecraft.network.protocol.game.ClientboundBundlePacket;
Expand All @@ -27,7 +27,7 @@
import net.minecraft.server.level.ServerEntity;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.network.ServerCommonPacketListenerImpl;
import net.minecraft.server.network.ServerGamePacketListenerImpl;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.ai.attributes.AttributeInstance;
import org.objectweb.asm.Opcodes;
Expand All @@ -46,7 +46,8 @@

@Mixin(ServerEntity.class)
public abstract class MixinServerEntity {
@Shadow @Final
@Final
@Shadow
private Entity entity;

@Shadow
Expand All @@ -58,53 +59,59 @@ public void sendPairingData(ServerPlayer serverplayer, Consumer<Packet<ClientGam
}

// Implementation of 0107-Multithreaded-Tracker.patch
@Redirect(method = "removePairing", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerCommonPacketListenerImpl;send(Lnet/minecraft/network/protocol/Packet;)V"))
private void skipSendForOriginalRemovePairing(ServerCommonPacketListenerImpl self, Packet<?> packet) {}
@SuppressWarnings("EmptyMethod")
@Redirect(method = "removePairing", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;send(Lnet/minecraft/network/protocol/Packet;)V"))
private void skipSendForOriginalRemovePairing(ServerGamePacketListenerImpl self, Packet<?> packet) {}

// Implementation of 0107-Multithreaded-Tracker.patch
@Inject(method = "removePairing", at = @At(value = "TAIL"))
private void invokeRemovePairingSendOnMain(ServerPlayer serverplayer, CallbackInfo callbackInfo) {
// Mirai start - ensure main thread
((ChunkMapMixin) (Object) ((ServerLevel) this.entity.level()).chunkSource.chunkMap).runOnTrackerMainThread(() ->
((IMixinChunkMapAccess) (Object) ((ServerLevel) this.entity.level()).chunkSource.chunkMap).gensouHacks$runOnTrackerMainThread(() ->
serverplayer.connection.send(new ClientboundRemoveEntitiesPacket(this.entity.getId()))
);
// Mirai end
}

// Implementation of 0107-Multithreaded-Tracker.patch
@SuppressWarnings("EmptyMethod")
@Redirect(method = "addPairing", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerEntity;sendPairingData(Lnet/minecraft/server/level/ServerPlayer;Ljava/util/function/Consumer;)V"))
private void skipSendPrepForOriginalAddPairing(ServerEntity self, ServerPlayer serverplayer, Consumer<Packet<ClientGamePacketListener>> consumer) {}

// Implementation of 0107-Multithreaded-Tracker.patch
@Redirect(method = "addPairing", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerCommonPacketListenerImpl;send(Lnet/minecraft/network/protocol/Packet;)V"))
private void skipSendForOriginalAddPairing(ServerCommonPacketListenerImpl self, Packet<?> packet) {}
@SuppressWarnings("EmptyMethod")
@Redirect(method = "addPairing", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;send(Lnet/minecraft/network/protocol/Packet;)V"))
private void skipSendForOriginalAddPairing(ServerGamePacketListenerImpl self, Packet<?> packet) {}

// Implementation of 0107-Multithreaded-Tracker.patch
@Inject(method = "addPairing", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;startSeenByPlayer(Lnet/minecraft/server/level/ServerPlayer;)V"))
private void invokeAddPairingSendOnMain(ServerPlayer serverplayer, CallbackInfo callbackInfo, @Local List<Packet<ClientGamePacketListener>> list) {
((ChunkMapMixin) (Object) ((ServerLevel) this.entity.level()).chunkSource.chunkMap).runOnTrackerMainThread(() -> { // Mirai - main thread
((IMixinChunkMapAccess) (Object) ((ServerLevel) this.entity.level()).chunkSource.chunkMap).gensouHacks$runOnTrackerMainThread(() -> { // Mirai - main thread
this.sendPairingData(serverplayer, list::add);
serverplayer.connection.send(new ClientboundBundlePacket(list));
});
}

// Implementation of 0107-Multithreaded-Tracker.patch
@SuppressWarnings("SameReturnValue")
@Redirect(method = "sendDirtyEntityData", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/syncher/SynchedEntityData;getNonDefaultValues()Ljava/util/List;"))
private List<SynchedEntityData.DataValue<?>> skipGetForGenericNonDefault(SynchedEntityData self) {return null;}

// Implementation of 0107-Multithreaded-Tracker.patch
@SuppressWarnings("EmptyMethod")
@Redirect(method = "sendDirtyEntityData", at = @At(value = "FIELD", target = "Lnet/minecraft/server/level/ServerEntity;trackedDataValues:Ljava/util/List;", opcode = Opcodes.PUTFIELD))
private void skipSetForGenericNonDefault(ServerEntity self, List<SynchedEntityData.DataValue<?>> nonDefaultValues) {}

// Implementation of 0107-Multithreaded-Tracker.patch
@SuppressWarnings("EmptyMethod")
@Redirect(method = "sendDirtyEntityData", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerEntity;broadcastAndSend(Lnet/minecraft/network/protocol/Packet;)V"))
private void skipTrasmitForNonDefault(ServerEntity self, Packet<?> packet) {}

// Implementation of 0107-Multithreaded-Tracker.patch
@Inject(method = "sendDirtyEntityData", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "FIELD", target = "Lnet/minecraft/server/level/ServerEntity;entity:Lnet/minecraft/world/entity/Entity;", opcode = Opcodes.GETFIELD, ordinal = 2))
private void invokeSendForGenericDirtyEntityDataOnMain(CallbackInfo callbackInfo, @Local SynchedEntityData synchedentitydata, @Local List<SynchedEntityData.DataValue<?>> list) {
// Mirai start - sync
((ChunkMapMixin) (Object) ((ServerLevel) this.entity.level()).chunkSource.chunkMap).runOnTrackerMainThread(() -> {
((IMixinChunkMapAccess) (Object) ((ServerLevel) this.entity.level()).chunkSource.chunkMap).gensouHacks$runOnTrackerMainThread(() -> {
this.trackedDataValues = synchedentitydata.getNonDefaultValues();
this.broadcastAndSend(new ClientboundSetEntityDataPacket(this.entity.getId(), list));
});
Expand All @@ -118,7 +125,7 @@ private void invokeSendForGenericDirtyEntityDataOnMain(CallbackInfo callbackInfo
private void invokeSendForLivingDirtyEntityDataOnMain(CallbackInfo callbackInfo, @Local Set<AttributeInstance> set) {
// Mirai start - sync
final var copy = Lists.newArrayList(set);
((ChunkMapMixin) (Object) ((ServerLevel) this.entity.level()).chunkSource.chunkMap).runOnTrackerMainThread(() -> {
((IMixinChunkMapAccess) (Object) ((ServerLevel) this.entity.level()).chunkSource.chunkMap).gensouHacks$runOnTrackerMainThread(() -> {
// CraftBukkit start - Send scaled max health
if (this.entity instanceof ServerPlayer) {
((ServerPlayer) this.entity).getBukkitEntity().injectScaledMaxHealth(copy, false);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Nitori Copyright (C) 2024 Gensokyo Reimagined
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package net.gensokyoreimagined.nitori.core.access;

import com.destroystokyo.paper.util.maplist.EntityList;

public interface IMixinChunkEntitySlicesAccess {
@SuppressWarnings("EmptyMethod")
EntityList getEntities();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Nitori Copyright (C) 2024 Gensokyo Reimagined
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package net.gensokyoreimagined.nitori.core.access;

public interface IMixinChunkMapAccess {
void gensouHacks$runOnTrackerMainThread(final Runnable runnable);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Nitori Copyright (C) 2024 Gensokyo Reimagined
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package net.gensokyoreimagined.nitori.core.access;

import com.destroystokyo.paper.util.misc.PooledLinkedHashSets;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.Entity;

public interface IMixinChunkMap_TrackedEntityAccess {
@SuppressWarnings("EmptyMethod")
Entity getEntity();

@SuppressWarnings("EmptyMethod")
void callUpdatePlayers(PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<ServerPlayer> newTrackerCandidates);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Nitori Copyright (C) 2024 Gensokyo Reimagined
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package net.gensokyoreimagined.nitori.core.access;

public interface IMixinIteratorSafeOrderedReferenceSetAccess {
@SuppressWarnings("EmptyMethod")
int getListSize();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Mixin Access

Folders are for isolating mixin access where package visibility is relevant, such as `protected`.
Loading

0 comments on commit 18cd32b

Please sign in to comment.