6 Commits
master ... next

Author SHA1 Message Date
Taiyou06
aa1632a21f v2 2024-08-14 00:03:39 +03:00
Taiyou06
5eabd83633 fix some of the unapplied mixins, improve perf 2024-08-13 15:36:08 +03:00
Taiyou06
dd31ed6b54 fix performance regressions and fix issues 2024-08-13 01:20:44 +03:00
Taiyou06
36e5c571de refactor 2024-08-12 16:03:17 +03:00
Taiyou06
94fc986edd remove unneeded logic 2024-08-12 15:49:58 +03:00
Taiyou06
53ebfb462c cleanup continues. paper gotten good, god damn 2024-08-10 00:05:20 +03:00
70 changed files with 1430 additions and 1352 deletions

View File

@@ -1,9 +1,6 @@
# Nitori # Nitori
A performance mod that converts patches into mixins using the Ignite Framework for Paper/Spigot. A performance mod that converts patches into mixins using the Ignite Framework for Paper/Spigot.
> [!CAUTION]
> Nitori is more or less depraced to use [Leaf](https://github.com/Winds-Studio/Leaf) in it's replacement for performance orianted features.
## Optimizations: ## Optimizations:
This plugin provides the following optimizations: This plugin provides the following optimizations:
- Faster Entity tracker by utilizing **Multiple Cores** this will allow larger servers to have way more entities - Faster Entity tracker by utilizing **Multiple Cores** this will allow larger servers to have way more entities

View File

@@ -1,5 +1,5 @@
group=net.gensokyoreimagined.nitori group=net.gensokyoreimagined.nitori
version=1.5-SNAPSHOT version=1.6-SNAPSHOT
description=Converting patches into mixins, for the Ignite Framework description=Converting patches into mixins, for the Ignite Framework
org.gradle.parallel=true org.gradle.parallel=true

View File

@@ -1,8 +0,0 @@
package net.gensokyoreimagined.nitori.access;
public interface ITypeFilterableList {
Object[] getBackingArray();
}

View File

@@ -1,9 +1,9 @@
package net.gensokyoreimagined.nitori.common.chunkwatching; package net.gensokyoreimagined.nitori.common.chunkwatching;
public interface PlayerClientVDTracking { //public interface PlayerClientVDTracking {
//
boolean isClientViewDistanceChanged(); // boolean isClientViewDistanceChanged();
//
int getClientViewDistance(); // int getClientViewDistance();
//
} //}

View File

@@ -1,26 +1,26 @@
package net.gensokyoreimagined.nitori.common.world.chunk; package net.gensokyoreimagined.nitori.common.world.chunk;
import net.minecraft.server.level.FullChunkStatus; //import net.minecraft.server.level.FullChunkStatus;
import net.minecraft.server.level.ServerLevel; //import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.ChunkPos; //import net.minecraft.world.level.ChunkPos;
//
import java.util.ArrayList; //import java.util.ArrayList;
import java.util.function.BiConsumer; //import java.util.function.BiConsumer;
//
public class ChunkStatusTracker { //public class ChunkStatusTracker {
//
//Add other callback types in the future when needed // //Add other callback types in the future when needed
private static final ArrayList<BiConsumer<ServerLevel, ChunkPos>> UNLOAD_CALLBACKS = new ArrayList<>(); // private static final ArrayList<BiConsumer<ServerLevel, ChunkPos>> UNLOAD_CALLBACKS = new ArrayList<>();
public static void onChunkStatusChange(ServerLevel serverWorld, ChunkPos pos, FullChunkStatus levelType) { // public static void onChunkStatusChange(ServerLevel serverWorld, ChunkPos pos, FullChunkStatus levelType) {
boolean loaded = levelType.isOrAfter(FullChunkStatus.FULL); // boolean loaded = levelType.isOrAfter(FullChunkStatus.FULL);
if (!loaded) { // if (!loaded) {
for (int i = 0; i < UNLOAD_CALLBACKS.size(); i++) { // for (int i = 0; i < UNLOAD_CALLBACKS.size(); i++) {
UNLOAD_CALLBACKS.get(i).accept(serverWorld, pos); // UNLOAD_CALLBACKS.get(i).accept(serverWorld, pos);
} // }
} // }
} // }
//
public static void registerUnloadCallback(BiConsumer<ServerLevel, ChunkPos> callback) { // public static void registerUnloadCallback(BiConsumer<ServerLevel, ChunkPos> callback) {
UNLOAD_CALLBACKS.add(callback); // UNLOAD_CALLBACKS.add(callback);
} // }
} //}

View File

@@ -0,0 +1,48 @@
package net.gensokyoreimagined.nitori.common.world.listeners;
import net.minecraft.world.level.border.WorldBorder;
import net.minecraft.world.level.border.BorderChangeListener;
public interface WorldBorderListenerOnce extends BorderChangeListener {
void lithium$onWorldBorderShapeChange(WorldBorder worldBorder);
default void onAreaReplaced(WorldBorder border) {
this.lithium$onWorldBorderShapeChange(border);
}
@Override
default void onBorderSizeSet(WorldBorder border, double size) {
this.lithium$onWorldBorderShapeChange(border);
}
@Override
default void onBorderSizeLerping(WorldBorder border, double fromSize, double toSize, long time) {
this.lithium$onWorldBorderShapeChange(border);
}
@Override
default void onBorderCenterSet(WorldBorder border, double centerX, double centerZ) {
this.lithium$onWorldBorderShapeChange(border);
}
@Override
default void onBorderSetWarningTime(WorldBorder border, int warningTime) {
}
@Override
default void onBorderSetWarningBlocks(WorldBorder border, int warningBlockDistance) {
}
@Override
default void onBorderSetDamagePerBlock(WorldBorder border, double damagePerBlock) {
}
@Override
default void onBorderSetDamageSafeZOne(WorldBorder border, double safeZoneRadius) {
}
}

View File

@@ -1,70 +0,0 @@
package net.gensokyoreimagined.nitori.mixin;
import it.unimi.dsi.fastutil.ints.Int2ObjectLinkedOpenHashMap;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.entity.EntityTickList;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.function.Consumer;
@Mixin(EntityTickList.class)
public class MixinEntityTickList {
@Unique
private Int2ObjectLinkedOpenHashMap<Entity> nitori$entities = new Int2ObjectLinkedOpenHashMap<>();
@Unique
private Int2ObjectLinkedOpenHashMap<Entity> nitori$iteratorPointer = null;
// I've decided I hate Paper's design.
// All of these are effectively Overwrites.
@Unique
private void nitori$ensureActiveIsNotIterated() {
if (nitori$iteratorPointer == nitori$entities) {
// Avoid a ConcurrentModificationException by cloning the map before modifying it.
// Side effect is that it allocates more memory to avoid blocking the main thread, but it's all pointers anyway.
nitori$entities = nitori$entities.clone();
}
}
@Inject(method = "add", at = @At("HEAD"), cancellable = true)
public void add(Entity entity, CallbackInfo ci) {
nitori$ensureActiveIsNotIterated();
nitori$entities.put(entity.getId(), entity);
ci.cancel();
}
@Inject(method = "remove", at = @At("HEAD"), cancellable = true)
public void remove(Entity entity, CallbackInfo ci) {
nitori$ensureActiveIsNotIterated();
nitori$entities.remove(entity.getId());
ci.cancel();
}
@Inject(method = "contains", at = @At("HEAD"), cancellable = true)
public void contains(Entity entity, CallbackInfoReturnable<Boolean> ci) {
ci.setReturnValue(nitori$entities.containsKey(entity.getId()));
ci.cancel();
}
@Inject(method = "forEach", at = @At("HEAD"), cancellable = true)
public void forEach(Consumer<Entity> action, CallbackInfo ci) {
if (nitori$iteratorPointer == nitori$entities) {
nitori$entities = nitori$entities.clone(); // Avoid a ConcurrentModificationException by cloning the map before iterating over it.
}
nitori$iteratorPointer = nitori$entities; // Mark the map as being iterated.
try {
nitori$iteratorPointer.values().forEach(action); // Iterate over the map.
} finally {
nitori$iteratorPointer = null; // Mark the map as no longer being iterated.
}
ci.cancel();
}
}

View File

@@ -1,23 +0,0 @@
package net.gensokyoreimagined.nitori.mixin.alloc.chunk_random;
import net.gensokyoreimagined.nitori.common.world.ChunkRandomSource;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.Level;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(Level.class)
public class WorldMixin implements ChunkRandomSource {
@Shadow
protected int randValue;
/**
* {@inheritDoc}
*/
@Override
public void nitori$getRandomPosInChunk(int x, int y, int z, int mask, BlockPos.MutableBlockPos out) {
this.randValue = this.randValue * 3 + 1013904223;
int rand = this.randValue >> 2;
out.set(x + (rand & 15), y + (rand >> 16 & mask), z + (rand >> 8 & 15));
}
}

View File

@@ -1,33 +0,0 @@
package net.gensokyoreimagined.nitori.mixin.collections.goals;
import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet;
import net.minecraft.world.entity.ai.goal.GoalSelector;
import net.minecraft.world.entity.ai.goal.WrappedGoal;
import net.minecraft.util.profiling.ProfilerFiller;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
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 java.util.Set;
import java.util.function.Supplier;
@Mixin(GoalSelector.class)
public abstract class GoalSelectorMixin {
@Mutable
@Shadow
@Final
private Set<WrappedGoal> availableGoals;
/**
* Replace the goal set with an optimized collection type which performs better for iteration.
*/
@Inject(method = "<init>", at = @At("RETURN"))
private void reinit(Supplier<ProfilerFiller> supplier, CallbackInfo ci) {
this.availableGoals = new ObjectLinkedOpenHashSet<>(this.availableGoals);
}
}

View File

@@ -1,66 +0,0 @@
package net.gensokyoreimagined.nitori.mixin.entity.inactive_navigations;
import net.gensokyoreimagined.nitori.common.entity.NavigatingEntity;
import net.gensokyoreimagined.nitori.common.world.ServerWorldExtended;
import net.minecraft.world.entity.ai.navigation.PathNavigation;
import net.minecraft.world.level.pathfinder.Path;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.level.Level;
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 org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(PathNavigation.class)
public abstract class EntityNavigationMixin {
@Shadow
@Final
protected Level level;
@Shadow
protected Path path;
@Shadow
@Final
protected Mob mob;
@Inject(
method = "recomputePath",
at = @At(
value = "INVOKE_ASSIGN",
target = "Lnet/minecraft/world/entity/ai/navigation/PathNavigation;createPath(Lnet/minecraft/core/BlockPos;I)Lnet/minecraft/world/level/pathfinder/Path;",
shift = At.Shift.AFTER
)
)
private void updateListeningState(CallbackInfo ci) {
if (((NavigatingEntity) this.mob).lithium$isRegisteredToWorld()) {
if (this.path == null) {
((ServerWorldExtended) this.level).lithium$setNavigationInactive(this.mob);
} else {
((ServerWorldExtended) this.level).lithium$setNavigationActive(this.mob);
}
}
}
@Inject(method = "moveTo(Lnet/minecraft/world/level/pathfinder/Path;D)Z", at = @At(value = "RETURN"))
private void updateListeningState2(Path path, double speed, CallbackInfoReturnable<Boolean> cir) {
if (((NavigatingEntity) this.mob).lithium$isRegisteredToWorld()) {
if (this.path == null) {
((ServerWorldExtended) this.level).lithium$setNavigationInactive(this.mob);
} else {
((ServerWorldExtended) this.level).lithium$setNavigationActive(this.mob);
}
}
}
@Inject(method = "stop", at = @At(value = "RETURN"))
private void stopListening(CallbackInfo ci) {
if (((NavigatingEntity) this.mob).lithium$isRegisteredToWorld()) {
((ServerWorldExtended) this.level).lithium$setNavigationInactive(this.mob);
}
}
}

View File

@@ -1,76 +0,0 @@
package net.gensokyoreimagined.nitori.mixin.entity.inactive_navigations;
import net.gensokyoreimagined.nitori.common.entity.NavigatingEntity;
import net.gensokyoreimagined.nitori.common.world.ServerWorldExtended;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.ai.navigation.PathNavigation;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.level.Level;
import org.spongepowered.asm.mixin.Intrinsic;
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 org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(Mob.class)
public abstract class MobEntityMixin extends Entity implements NavigatingEntity {
private PathNavigation nitori$registeredNavigation;
public MobEntityMixin(EntityType<?> type, Level world) {
super(type, world);
}
@Shadow
public abstract PathNavigation getNavigation();
@Override
public boolean lithium$isRegisteredToWorld() {
return this.nitori$registeredNavigation != null;
}
@Override
public void lithium$setRegisteredToWorld(PathNavigation navigation) {
this.nitori$registeredNavigation = navigation;
}
@Override
public PathNavigation lithium$getRegisteredNavigation() {
return this.nitori$registeredNavigation;
}
@Inject(method = "startRiding", at = @At("RETURN"))
private void onNavigationReplacement(Entity entity, boolean force, CallbackInfoReturnable<Boolean> cir) {
this.lithium$updateNavigationRegistration();
}
@Override
@Intrinsic
public void stopRiding() {
super.stopRiding();
}
@SuppressWarnings({"MixinAnnotationTarget", "UnresolvedMixinReference"})
@Inject(method = "stopRiding()V", at = @At("RETURN"))
private void updateOnStopRiding(CallbackInfo ci) {
this.lithium$updateNavigationRegistration();
}
@Override
public void lithium$updateNavigationRegistration() {
if (this.lithium$isRegisteredToWorld()) {
PathNavigation navigation = this.getNavigation();
if (this.nitori$registeredNavigation != navigation) {
((ServerWorldExtended) this.level()).lithium$setNavigationInactive((Mob) (Object) this);
this.nitori$registeredNavigation = navigation;
if (navigation.getPath() != null) {
((ServerWorldExtended) this.level()).lithium$setNavigationActive((Mob) (Object) this);
}
}
}
}
}

View File

@@ -1,13 +0,0 @@
package net.gensokyoreimagined.nitori.mixin.logic.fast_bits_blockpos;
import net.minecraft.core.SectionPos;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;
@Mixin(SectionPos.class)
public interface ChunkSectionPosAccessor {
@Invoker("<init>")
public static SectionPos invokeChunkSectionPos(int i, int j, int k) {
throw new AssertionError();
}
}

View File

@@ -1,67 +0,0 @@
package net.gensokyoreimagined.nitori.mixin.logic.fast_bits_blockpos;
import net.minecraft.core.BlockPos;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
/**
* Credit to PaperMC Patch #0421
*/
@Mixin(BlockPos.class)
public class OptimizedBlockPosBitsMixin {
/**
* @author QPCrummer
* @reason Inline
*/
@Overwrite
public static long offset(long value, int x, int y, int z) {
return asLong((int) (value >> 38) + x, (int) ((value << 52) >> 52) + y, (int) ((value << 26) >> 38) + z);
}
/**
* @author QPCrummer
* @reason Inline
*/
@Overwrite
public static int getX(long packedPos) {
return (int) (packedPos >> 38);
}
/**
* @author QPCrummer
* @reason Inline
*/
@Overwrite
public static int getY(long packedPos) {
return (int) ((packedPos << 52) >> 52);
}
/**
* @author QPCrummer
* @reason Inline
*/
@Overwrite
public static int getZ(long packedPos) {
return (int) ((packedPos << 26) >> 38);
}
/**
* @author QPCrummer
* @reason Inline
*/
@Overwrite
public static BlockPos of(long packedPos) {
return new BlockPos((int) (packedPos >> 38), (int) ((packedPos << 52) >> 52), (int) ((packedPos << 26) >> 38));
}
/**
* @author QPCrummer
* @reason Inline
*/
@Overwrite
public static long asLong(int x, int y, int z) {
return (((long) x & (long) 67108863) << 38) | (((long) y & (long) 4095)) | (((long) z & (long) 67108863) << 12);
}
}

View File

@@ -1,127 +0,0 @@
package net.gensokyoreimagined.nitori.mixin.math.fast_blockops;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Vec3i;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
@Mixin(BlockPos.class)
public abstract class BlockPosMixin extends Vec3i {
public BlockPosMixin(int x, int y, int z) {
super(x, y, z);
}
/**
* @author JellySquid
* @reason Simplify and inline
*/
@Override
@Overwrite
public BlockPos above() {
return new BlockPos(this.getX(), this.getY() + 1, this.getZ());
}
/**
* @author JellySquid
* @reason Simplify and inline
*/
@Override
@Overwrite
public BlockPos above(int distance) {
return new BlockPos(this.getX(), this.getY() + distance, this.getZ());
}
/**
* @author JellySquid
* @reason Simplify and inline
*/
@Override
@Overwrite
public BlockPos below() {
return new BlockPos(this.getX(), this.getY() - 1, this.getZ());
}
/**
* @author JellySquid
* @reason Simplify and inline
*/
@Override
@Overwrite
public BlockPos below(int distance) {
return new BlockPos(this.getX(), this.getY() - distance, this.getZ());
}
/**
* @author JellySquid
* @reason Simplify and inline
*/
@Overwrite
public BlockPos north() {
return new BlockPos(this.getX(), this.getY(), this.getZ() - 1);
}
/**
* @author JellySquid
* @reason Simplify and inline
*/
@Overwrite
public BlockPos north(int distance) {
return new BlockPos(this.getX(), this.getY(), this.getZ() - distance);
}
/**
* @author JellySquid
* @reason Simplify and inline
*/
@Overwrite
public BlockPos south() {
return new BlockPos(this.getX(), this.getY(), this.getZ() + 1);
}
/**
* @author JellySquid
* @reason Simplify and inline
*/
@Overwrite
public BlockPos south(int distance) {
return new BlockPos(this.getX(), this.getY(), this.getZ() + distance);
}
/**
* @author JellySquid
* @reason Simplify and inline
*/
@Overwrite
public BlockPos west() {
return new BlockPos(this.getX() - 1, this.getY(), this.getZ());
}
/**
* @author JellySquid
* @reason Simplify and inline
*/
@Overwrite
public BlockPos west(int distance) {
return new BlockPos(this.getX() - distance, this.getY(), this.getZ());
}
/**
* @author JellySquid
* @reason Simplify and inline
*/
@Overwrite
public BlockPos east() {
return new BlockPos(this.getX() + 1, this.getY(), this.getZ());
}
/**
* @author JellySquid
* @reason Simplify and inline
*/
@Overwrite
public BlockPos east(int distance) {
return new BlockPos(this.getX() + distance, this.getY(), this.getZ());
}
}

View File

@@ -1,54 +0,0 @@
package net.gensokyoreimagined.nitori.mixin.math.fast_blockops;
import net.minecraft.core.Direction;
import net.minecraft.core.Vec3i;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
/**
* The vector of each Direction is usually stored inside another object, which introduces indirection and makes things
* harder for the JVM to optimize. This patch simply hoists the offset fields to the Direction enum itself.
*/
@Mixin(Direction.class)
public class DirectionMixin {
@Unique
private int nitori$getStepX, nitori$getStepY, nitori$getStepZ;
@Inject(method = "<init>", at = @At("RETURN"))
private void reinit(String enumName, int ordinal, int id, int idOpposite, int idHorizontal, String name, Direction.AxisDirection direction, Direction.Axis axis, Vec3i vector, CallbackInfo ci) {
this.nitori$getStepX = vector.getX();
this.nitori$getStepY = vector.getY();
this.nitori$getStepZ = vector.getZ();
}
/**
* @reason Avoid indirection to aid inlining
* @author JellySquid
*/
@Overwrite
public int getStepX() {
return this.nitori$getStepX;
}
/**
* @reason Avoid indirection to aid inlining
* @author JellySquid
*/
@Overwrite
public int getStepY() {
return this.nitori$getStepY;
}
/**
* @reason Avoid indirection to aid inlining
* @author JellySquid
*/
@Overwrite
public int getStepZ() {
return this.nitori$getStepZ;
}
}

View File

@@ -1,29 +0,0 @@
package net.gensokyoreimagined.nitori.mixin.math.random;
import net.gensokyoreimagined.nitori.common.math.random.RandomGeneratorRandom;
import io.netty.util.internal.ThreadLocalRandom;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.levelgen.RandomSupport;
import org.jetbrains.annotations.NotNull;
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;
@Mixin(RandomSource.class)
public interface RandomMixin {
@Inject(method = "create(J)Lnet/minecraft/util/RandomSource;", at = @At(value = "HEAD"), cancellable = true)
private static void fasterrandom$createInject(long seed, @NotNull CallbackInfoReturnable<RandomSource> cir) {
cir.setReturnValue(new RandomGeneratorRandom(seed));
}
@Inject(method = "createNewThreadLocalInstance", at = @At(value = "HEAD"), cancellable = true)
private static void fasterrandom$createLocalInject(@NotNull CallbackInfoReturnable<RandomSource> cir) {
cir.setReturnValue(new RandomGeneratorRandom(ThreadLocalRandom.current().nextLong()));
}
@Inject(method = "createThreadSafe", at = @At(value = "HEAD"), cancellable = true)
private static void fasterrandom$createThreadSafeInject(@NotNull CallbackInfoReturnable<RandomSource> cir) {
cir.setReturnValue(new RandomGeneratorRandom(RandomSupport.generateUniqueSeed()));
}
}

View File

@@ -1,4 +1,4 @@
package net.gensokyoreimagined.nitori.mixin.vmp.entity.move_zero_velocity; package net.gensokyoreimagined.nitori.mixin.network.move_zero_velocity;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.MoverType; import net.minecraft.world.entity.MoverType;

View File

@@ -0,0 +1,70 @@
package net.gensokyoreimagined.nitori.mixin.removed;
//import it.unimi.dsi.fastutil.ints.Int2ObjectLinkedOpenHashMap;
//import net.minecraft.world.entity.Entity;
//import net.minecraft.world.level.entity.EntityTickList;
//import org.spongepowered.asm.mixin.Mixin;
//import org.spongepowered.asm.mixin.Unique;
//import org.spongepowered.asm.mixin.injection.At;
//import org.spongepowered.asm.mixin.injection.Inject;
//import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
//import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
//
//import java.util.function.Consumer;
//
//@Mixin(EntityTickList.class)
//public class MixinEntityTickList {
// @Unique
// private Int2ObjectLinkedOpenHashMap<Entity> nitori$entities = new Int2ObjectLinkedOpenHashMap<>();
// @Unique
// private Int2ObjectLinkedOpenHashMap<Entity> nitori$iteratorPointer = null;
//
// // I've decided I hate Paper's design.
// // All of these are effectively Overwrites.
//
// @Unique
// private void nitori$ensureActiveIsNotIterated() {
// if (nitori$iteratorPointer == nitori$entities) {
// // Avoid a ConcurrentModificationException by cloning the map before modifying it.
// // Side effect is that it allocates more memory to avoid blocking the main thread, but it's all pointers anyway.
// nitori$entities = nitori$entities.clone();
// }
// }
//
// @Inject(method = "add", at = @At("HEAD"), cancellable = true)
// public void add(Entity entity, CallbackInfo ci) {
// nitori$ensureActiveIsNotIterated();
// nitori$entities.put(entity.getId(), entity);
// ci.cancel();
// }
//
// @Inject(method = "remove", at = @At("HEAD"), cancellable = true)
// public void remove(Entity entity, CallbackInfo ci) {
// nitori$ensureActiveIsNotIterated();
// nitori$entities.remove(entity.getId());
// ci.cancel();
// }
//
// @Inject(method = "contains", at = @At("HEAD"), cancellable = true)
// public void contains(Entity entity, CallbackInfoReturnable<Boolean> ci) {
// ci.setReturnValue(nitori$entities.containsKey(entity.getId()));
// ci.cancel();
// }
//
// @Inject(method = "forEach", at = @At("HEAD"), cancellable = true)
// public void forEach(Consumer<Entity> action, CallbackInfo ci) {
// if (nitori$iteratorPointer == nitori$entities) {
// nitori$entities = nitori$entities.clone(); // Avoid a ConcurrentModificationException by cloning the map before iterating over it.
// }
//
// nitori$iteratorPointer = nitori$entities; // Mark the map as being iterated.
//
// try {
// nitori$iteratorPointer.values().forEach(action); // Iterate over the map.
// } finally {
// nitori$iteratorPointer = null; // Mark the map as no longer being iterated.
// }
//
// ci.cancel();
// }
//}

View File

@@ -12,7 +12,7 @@
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
package net.gensokyoreimagined.nitori.access; package net.gensokyoreimagined.nitori.mixin.removed.access;
//import ca.spottedleaf.moonrise.common.list.EntityList; //import ca.spottedleaf.moonrise.common.list.EntityList;
// //

View File

@@ -12,7 +12,7 @@
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
package net.gensokyoreimagined.nitori.access; package net.gensokyoreimagined.nitori.mixin.removed.access;
//public interface IMixinIteratorSafeOrderedReferenceSetAccess { //public interface IMixinIteratorSafeOrderedReferenceSetAccess {
// @SuppressWarnings("EmptyMethod") // @SuppressWarnings("EmptyMethod")

View File

@@ -0,0 +1,8 @@
package net.gensokyoreimagined.nitori.mixin.removed.access;
//public interface ITypeFilterableList {
//
// Object[] getBackingArray();
//
//
//}

View File

@@ -1,4 +1,4 @@
package net.gensokyoreimagined.nitori.mixin.unapplied.alloc.chunk_random; package net.gensokyoreimagined.nitori.mixin.removed.alloc.chunk_random;
//import net.gensokyoreimagined.nitori.common.world.ChunkRandomSource; //import net.gensokyoreimagined.nitori.common.world.ChunkRandomSource;
//import net.minecraft.world.level.block.state.BlockState; //import net.minecraft.world.level.block.state.BlockState;

View File

@@ -0,0 +1,23 @@
package net.gensokyoreimagined.nitori.mixin.removed.alloc.chunk_random;
//import net.gensokyoreimagined.nitori.common.world.ChunkRandomSource;
//import net.minecraft.core.BlockPos;
//import net.minecraft.world.level.Level;
//import org.spongepowered.asm.mixin.Mixin;
//import org.spongepowered.asm.mixin.Shadow;
//
//@Mixin(Level.class)
//public class WorldMixin implements ChunkRandomSource {
// @Shadow
// protected int randValue;
//
// /**
// * {@inheritDoc}
// */
// @Override
// public void nitori$getRandomPosInChunk(int x, int y, int z, int mask, BlockPos.MutableBlockPos out) {
// this.randValue = this.randValue * 3 + 1013904223;
// int rand = this.randValue >> 2;
// out.set(x + (rand & 15), y + (rand >> 16 & mask), z + (rand >> 8 & 15));
// }
//}

View File

@@ -0,0 +1,33 @@
package net.gensokyoreimagined.nitori.mixin.removed.collections.goals;
//import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet;
//import net.minecraft.world.entity.ai.goal.GoalSelector;
//import net.minecraft.world.entity.ai.goal.WrappedGoal;
//import net.minecraft.util.profiling.ProfilerFiller;
//import org.spongepowered.asm.mixin.Final;
//import org.spongepowered.asm.mixin.Mixin;
//import org.spongepowered.asm.mixin.Mutable;
//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 java.util.Set;
//import java.util.function.Supplier;
//
//@Mixin(GoalSelector.class)
//public abstract class GoalSelectorMixin {
//
// @Mutable
// @Shadow
// @Final
// private Set<WrappedGoal> availableGoals;
//
// /**
// * Replace the goal set with an optimized collection type which performs better for iteration.
// */
// @Inject(method = "<init>", at = @At("RETURN"))
// private void reinit(Supplier<ProfilerFiller> supplier, CallbackInfo ci) {
// this.availableGoals = new ObjectLinkedOpenHashSet<>(this.availableGoals);
// }
//}

View File

@@ -0,0 +1,66 @@
package net.gensokyoreimagined.nitori.mixin.removed.entity.inactive_navigations;
//import net.gensokyoreimagined.nitori.common.entity.NavigatingEntity;
//import net.gensokyoreimagined.nitori.common.world.ServerWorldExtended;
//import net.minecraft.world.entity.ai.navigation.PathNavigation;
//import net.minecraft.world.level.pathfinder.Path;
//import net.minecraft.world.entity.Mob;
//import net.minecraft.world.level.Level;
//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 org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
//
//@Mixin(PathNavigation.class)
//public abstract class EntityNavigationMixin {
//
// @Shadow
// @Final
// protected Level level;
//
// @Shadow
// protected Path path;
//
// @Shadow
// @Final
// protected Mob mob;
//
// @Inject(
// method = "recomputePath",
// at = @At(
// value = "INVOKE_ASSIGN",
// target = "Lnet/minecraft/world/entity/ai/navigation/PathNavigation;createPath(Lnet/minecraft/core/BlockPos;I)Lnet/minecraft/world/level/pathfinder/Path;",
// shift = At.Shift.AFTER
// )
// )
// private void updateListeningState(CallbackInfo ci) {
// if (((NavigatingEntity) this.mob).lithium$isRegisteredToWorld()) {
// if (this.path == null) {
// ((ServerWorldExtended) this.level).lithium$setNavigationInactive(this.mob);
// } else {
// ((ServerWorldExtended) this.level).lithium$setNavigationActive(this.mob);
// }
// }
// }
//
// @Inject(method = "moveTo(Lnet/minecraft/world/level/pathfinder/Path;D)Z", at = @At(value = "RETURN"))
// private void updateListeningState2(Path path, double speed, CallbackInfoReturnable<Boolean> cir) {
// if (((NavigatingEntity) this.mob).lithium$isRegisteredToWorld()) {
// if (this.path == null) {
// ((ServerWorldExtended) this.level).lithium$setNavigationInactive(this.mob);
// } else {
// ((ServerWorldExtended) this.level).lithium$setNavigationActive(this.mob);
// }
// }
// }
//
// @Inject(method = "stop", at = @At(value = "RETURN"))
// private void stopListening(CallbackInfo ci) {
// if (((NavigatingEntity) this.mob).lithium$isRegisteredToWorld()) {
// ((ServerWorldExtended) this.level).lithium$setNavigationInactive(this.mob);
// }
// }
//}

View File

@@ -0,0 +1,76 @@
package net.gensokyoreimagined.nitori.mixin.removed.entity.inactive_navigations;
//import net.gensokyoreimagined.nitori.common.entity.NavigatingEntity;
//import net.gensokyoreimagined.nitori.common.world.ServerWorldExtended;
//import net.minecraft.world.entity.Entity;
//import net.minecraft.world.entity.EntityType;
//import net.minecraft.world.entity.ai.navigation.PathNavigation;
//import net.minecraft.world.entity.Mob;
//import net.minecraft.world.level.Level;
//import org.spongepowered.asm.mixin.Intrinsic;
//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 org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
//
//@Mixin(Mob.class)
//public abstract class MobEntityMixin extends Entity implements NavigatingEntity {
// private PathNavigation nitori$registeredNavigation;
//
// public MobEntityMixin(EntityType<?> type, Level world) {
// super(type, world);
// }
//
// @Shadow
// public abstract PathNavigation getNavigation();
//
// @Override
// public boolean lithium$isRegisteredToWorld() {
// return this.nitori$registeredNavigation != null;
// }
//
// @Override
// public void lithium$setRegisteredToWorld(PathNavigation navigation) {
// this.nitori$registeredNavigation = navigation;
// }
//
// @Override
// public PathNavigation lithium$getRegisteredNavigation() {
// return this.nitori$registeredNavigation;
// }
//
// @Inject(method = "startRiding", at = @At("RETURN"))
// private void onNavigationReplacement(Entity entity, boolean force, CallbackInfoReturnable<Boolean> cir) {
// this.lithium$updateNavigationRegistration();
// }
//
// @Override
// @Intrinsic
// public void stopRiding() {
// super.stopRiding();
// }
//
// @SuppressWarnings({"MixinAnnotationTarget", "UnresolvedMixinReference"})
// @Inject(method = "stopRiding()V", at = @At("RETURN"))
// private void updateOnStopRiding(CallbackInfo ci) {
// this.lithium$updateNavigationRegistration();
// }
//
// @Override
// public void lithium$updateNavigationRegistration() {
// if (this.lithium$isRegisteredToWorld()) {
// PathNavigation navigation = this.getNavigation();
// if (this.nitori$registeredNavigation != navigation) {
// ((ServerWorldExtended) this.level()).lithium$setNavigationInactive((Mob) (Object) this);
// this.nitori$registeredNavigation = navigation;
//
// if (navigation.getPath() != null) {
// ((ServerWorldExtended) this.level()).lithium$setNavigationActive((Mob) (Object) this);
// }
// }
// }
// }
//
//}

View File

@@ -1,4 +1,4 @@
package net.gensokyoreimagined.nitori.mixin.entity.inactive_navigations; package net.gensokyoreimagined.nitori.mixin.removed.entity.inactive_navigations;
//import net.gensokyoreimagined.nitori.common.entity.NavigatingEntity; //import net.gensokyoreimagined.nitori.common.entity.NavigatingEntity;
//import net.gensokyoreimagined.nitori.common.world.ServerWorldExtended; //import net.gensokyoreimagined.nitori.common.world.ServerWorldExtended;

View File

@@ -1,4 +1,4 @@
package net.gensokyoreimagined.nitori.mixin.entity.inactive_navigations; package net.gensokyoreimagined.nitori.mixin.removed.entity.inactive_navigations;
//import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; //import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet;
//import net.gensokyoreimagined.nitori.common.entity.NavigatingEntity; //import net.gensokyoreimagined.nitori.common.entity.NavigatingEntity;

View File

@@ -0,0 +1,13 @@
package net.gensokyoreimagined.nitori.mixin.removed.logic.fast_bits_blockpos;
//import net.minecraft.core.SectionPos;
//import org.spongepowered.asm.mixin.Mixin;
//import org.spongepowered.asm.mixin.gen.Invoker;
//
//@Mixin(SectionPos.class)
//public interface ChunkSectionPosAccessor {
// @Invoker("<init>")
// public static SectionPos invokeChunkSectionPos(int i, int j, int k) {
// throw new AssertionError();
// }
//}

View File

@@ -0,0 +1,67 @@
package net.gensokyoreimagined.nitori.mixin.removed.logic.fast_bits_blockpos;
//import net.minecraft.core.BlockPos;
//import org.spongepowered.asm.mixin.Mixin;
//import org.spongepowered.asm.mixin.Overwrite;
//
///**
// * Credit to PaperMC Patch #0421
// */
//@Mixin(BlockPos.class)
//public class OptimizedBlockPosBitsMixin {
//
// /**
// * @author QPCrummer
// * @reason Inline
// */
// @Overwrite
// public static long offset(long value, int x, int y, int z) {
// return asLong((int) (value >> 38) + x, (int) ((value << 52) >> 52) + y, (int) ((value << 26) >> 38) + z);
// }
//
// /**
// * @author QPCrummer
// * @reason Inline
// */
// @Overwrite
// public static int getX(long packedPos) {
// return (int) (packedPos >> 38);
// }
//
// /**
// * @author QPCrummer
// * @reason Inline
// */
// @Overwrite
// public static int getY(long packedPos) {
// return (int) ((packedPos << 52) >> 52);
// }
//
// /**
// * @author QPCrummer
// * @reason Inline
// */
// @Overwrite
// public static int getZ(long packedPos) {
// return (int) ((packedPos << 26) >> 38);
// }
//
// /**
// * @author QPCrummer
// * @reason Inline
// */
// @Overwrite
// public static BlockPos of(long packedPos) {
// return new BlockPos((int) (packedPos >> 38), (int) ((packedPos << 52) >> 52), (int) ((packedPos << 26) >> 38));
// }
//
// /**
// * @author QPCrummer
// * @reason Inline
// */
// @Overwrite
// public static long asLong(int x, int y, int z) {
// return (((long) x & (long) 67108863) << 38) | (((long) y & (long) 4095)) | (((long) z & (long) 67108863) << 12);
// }
//
//}

View File

@@ -1,6 +1,4 @@
package net.gensokyoreimagined.nitori.mixin.logic.fast_bits_blockpos; package net.gensokyoreimagined.nitori.mixin.removed.logic.fast_bits_blockpos;
//TODO: impl this
//import net.minecraft.core.BlockPos; //import net.minecraft.core.BlockPos;
//import net.minecraft.world.level.ChunkPos; //import net.minecraft.world.level.ChunkPos;

View File

@@ -1,4 +1,4 @@
package net.gensokyoreimagined.nitori.mixin.logic.fast_rotations; package net.gensokyoreimagined.nitori.mixin.removed.logic.fast_rotations;
import com.llamalad7.mixinextras.sugar.Local; import com.llamalad7.mixinextras.sugar.Local;
import net.minecraft.nbt.FloatTag; import net.minecraft.nbt.FloatTag;

View File

@@ -1,4 +1,4 @@
package net.gensokyoreimagined.nitori.mixin.logic.recipe_manager; package net.gensokyoreimagined.nitori.mixin.removed.logic.recipe_manager.recipe_manager;
//import net.minecraft.world.Container; //import net.minecraft.world.Container;
//import net.minecraft.world.item.crafting.Recipe; //import net.minecraft.world.item.crafting.Recipe;

View File

@@ -1,4 +1,4 @@
package net.gensokyoreimagined.nitori.mixin.math.random; package net.gensokyoreimagined.nitori.mixin.removed.math.random;
//import net.gensokyoreimagined.nitori.common.math.random.RandomGeneratorRandom; //import net.gensokyoreimagined.nitori.common.math.random.RandomGeneratorRandom;
//import net.minecraft.world.entity.Entity; //import net.minecraft.world.entity.Entity;

View File

@@ -0,0 +1,29 @@
package net.gensokyoreimagined.nitori.mixin.removed.math.random;
//import net.gensokyoreimagined.nitori.common.math.random.RandomGeneratorRandom;
//import io.netty.util.internal.ThreadLocalRandom;
//import net.minecraft.util.RandomSource;
//import net.minecraft.world.level.levelgen.RandomSupport;
//import org.jetbrains.annotations.NotNull;
//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;
//
//@Mixin(RandomSource.class)
//public interface RandomMixin {
// @Inject(method = "create(J)Lnet/minecraft/util/RandomSource;", at = @At(value = "HEAD"), cancellable = true)
// private static void fasterrandom$createInject(long seed, @NotNull CallbackInfoReturnable<RandomSource> cir) {
// cir.setReturnValue(new RandomGeneratorRandom(seed));
// }
//
// @Inject(method = "createNewThreadLocalInstance", at = @At(value = "HEAD"), cancellable = true)
// private static void fasterrandom$createLocalInject(@NotNull CallbackInfoReturnable<RandomSource> cir) {
// cir.setReturnValue(new RandomGeneratorRandom(ThreadLocalRandom.current().nextLong()));
// }
//
// @Inject(method = "createThreadSafe", at = @At(value = "HEAD"), cancellable = true)
// private static void fasterrandom$createThreadSafeInject(@NotNull CallbackInfoReturnable<RandomSource> cir) {
// cir.setReturnValue(new RandomGeneratorRandom(RandomSupport.generateUniqueSeed()));
// }
//}

View File

@@ -1,4 +1,4 @@
package net.gensokyoreimagined.nitori.mixin.math.random.creation; package net.gensokyoreimagined.nitori.mixin.removed.math.random.creation;
//import net.gensokyoreimagined.nitori.mixin.math.random.math.GetRandomInterface; //import net.gensokyoreimagined.nitori.mixin.math.random.math.GetRandomInterface;
//import net.minecraft.server.rcon.thread.QueryThreadGs4; //import net.minecraft.server.rcon.thread.QueryThreadGs4;

View File

@@ -1,4 +1,4 @@
package net.gensokyoreimagined.nitori.mixin.math.random.creation; package net.gensokyoreimagined.nitori.mixin.removed.math.random.creation;
//import net.minecraft.server.level.ServerPlayer; //import net.minecraft.server.level.ServerPlayer;
//import net.minecraft.server.level.ServerLevel; //import net.minecraft.server.level.ServerLevel;

View File

@@ -1,4 +1,4 @@
package net.gensokyoreimagined.nitori.mixin.math.random.math; package net.gensokyoreimagined.nitori.mixin.removed.math.random.math;
//import net.minecraft.util.Mth; //import net.minecraft.util.Mth;
//import net.minecraft.util.RandomSource; //import net.minecraft.util.RandomSource;

View File

@@ -0,0 +1,76 @@
package net.gensokyoreimagined.nitori.mixin.removed.vmp.general.collections;
//import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap;
//import it.unimi.dsi.fastutil.objects.ObjectArrayList;
//import net.gensokyoreimagined.nitori.access.ITypeFilterableList;
//import net.minecraft.util.ClassInstanceMultiMap;
//import org.objectweb.asm.Opcodes;
//import org.spongepowered.asm.mixin.*;
//import org.spongepowered.asm.mixin.injection.At;
//import org.spongepowered.asm.mixin.injection.Redirect;
//
//import java.util.*;
//
//@Mixin(value = ClassInstanceMultiMap.class, priority = 1005) // priority compatibility hack for lithium
//public abstract class MixinTypeFilterableList<T> extends AbstractCollection<T> implements ITypeFilterableList {
//
// @Mutable
// @Shadow @Final private Map<Class<?>, List<T>> byClass;
//
// @Mutable
// @Shadow @Final private List<T> allInstances;
//
// @Shadow @Final private Class<T> baseClass;
//
// @Redirect(method = "<init>", at = @At(value = "FIELD", target = "Lnet/minecraft/util/ClassInstanceMultiMap;byClass:Ljava/util/Map;", opcode = Opcodes.PUTFIELD))
// private void redirectSetElementsByType(ClassInstanceMultiMap<T> instance, Map<Class<?>, List<T>> value) {
// this.byClass = new Object2ObjectLinkedOpenHashMap<>();
// }
//
// @Redirect(method = "<init>", at = @At(value = "FIELD", target = "Lnet/minecraft/util/ClassInstanceMultiMap;allInstances:Ljava/util/List;", opcode = Opcodes.PUTFIELD))
// private void redirectSetAllElements(ClassInstanceMultiMap<T> instance, List<T> value) {
// this.allInstances = new ObjectArrayList<>();
// }
//
// @Redirect(method = "<init>", at = @At(value = "INVOKE", target = "Lcom/google/common/collect/Maps;newHashMap()Ljava/util/HashMap;", remap = false))
// private HashMap<?, ?> redirectNewHashMap() {
// return null; // avoid unnecessary alloc
// }
//
// @Redirect(method = "<init>", at = @At(value = "INVOKE", target = "Lcom/google/common/collect/Lists;newArrayList()Ljava/util/ArrayList;", remap = false))
// private ArrayList<?> redirectNewArrayList() {
// return null;
// }
//
// @Override
// public Object[] getBackingArray() {
// return ((ObjectArrayList<T>) this.allInstances).elements();
// }
//
// /**
// * @author ishland
// * @reason use fastutil array list for faster iteration & use array for filtering iteration
// */
// @Overwrite
// public <S> Collection<S> find(Class<S> type) {
// List<T> cached = this.byClass.get(type);
// if (cached != null) return (Collection<S>) cached;
//
// if (!this.baseClass.isAssignableFrom(type)) {
// throw new IllegalArgumentException("Don't know how to search for " + type);
// } else {
// List<? extends T> list = this.byClass.computeIfAbsent(type,
// typeClass -> {
// ObjectArrayList<T> ts = new ObjectArrayList<>(this.allInstances.size());
// for (Object _allElement : ((ObjectArrayList<T>) this.allInstances).elements()) {
// if (typeClass.isInstance(_allElement)) {
// ts.add((T) _allElement);
// }
// }
// return ts;
// }
// );
// return (Collection<S>) list;
// }
// }
//}

View File

@@ -0,0 +1,22 @@
package net.gensokyoreimagined.nitori.mixin.removed.vmp.playerwatching;
//import net.minecraft.server.level.ChunkTrackingView;
//import org.spongepowered.asm.mixin.Mixin;
//import org.spongepowered.asm.mixin.Overwrite;
//
//@Mixin(ChunkTrackingView.class)
//public interface MixinChunkFilter {
//
// /**
// * @author ishland
// * @reason use chebyshev distance
// */
// @Overwrite
// static boolean isWithinDistance(int centerX, int centerZ, int viewDistance, int x, int z, boolean includeEdge) {
// int actualViewDistance = viewDistance + (includeEdge ? 1 : 0);
// int xDistance = Math.abs(centerX - x);
// int zDistance = Math.abs(centerZ - z);
// return xDistance <= actualViewDistance && zDistance <= actualViewDistance;
// }
//
//}

View File

@@ -0,0 +1,46 @@
package net.gensokyoreimagined.nitori.mixin.removed.vmp.playerwatching;
//import net.gensokyoreimagined.nitori.common.chunkwatching.PlayerClientVDTracking;
//import net.minecraft.server.level.ClientInformation;
//import net.minecraft.server.level.ServerPlayer;
//import org.spongepowered.asm.mixin.Mixin;
//import org.spongepowered.asm.mixin.Unique;
//import org.spongepowered.asm.mixin.injection.At;
//import org.spongepowered.asm.mixin.injection.Inject;
//import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
//
//@Mixin(ServerPlayer.class)
//public class MixinServerPlayerEntity implements PlayerClientVDTracking {
//
// @Unique
// private boolean vdChanged = false;
//
// @Unique
// private int clientVD = 2;
//
// @Inject(method = "updateOptions", at = @At("HEAD"))
// private void onClientSettingsChanged(ClientInformation packet, CallbackInfo ci) {
// final int currentVD = packet.viewDistance();
// if (currentVD != this.clientVD) this.vdChanged = true;
// this.clientVD = Math.max(2, currentVD);
// }
//
// @Inject(method = "restoreFrom", at = @At("RETURN"))
// private void onPlayerCopy(ServerPlayer oldPlayer, boolean alive, CallbackInfo ci) {
// this.clientVD = ((PlayerClientVDTracking) oldPlayer).getClientViewDistance();
// this.vdChanged = true;
// }
//
// @Unique
// @Override
// public boolean isClientViewDistanceChanged() {
// return this.vdChanged;
// }
//
// @Unique
// @Override
// public int getClientViewDistance() {
// this.vdChanged = false;
// return this.clientVD;
// }
//}

View File

@@ -0,0 +1,35 @@
package net.gensokyoreimagined.nitori.mixin.removed.vmp.playerwatching.optimize_nearby_player_lookups;
//import net.minecraft.world.entity.Entity;
//import net.minecraft.world.entity.EntityType;
//import net.minecraft.world.entity.LivingEntity;
//import net.minecraft.world.entity.Mob;
//import net.minecraft.world.entity.player.Player;
//import net.minecraft.world.level.Level;
//import org.spongepowered.asm.mixin.Mixin;
//import org.spongepowered.asm.mixin.injection.At;
//import org.spongepowered.asm.mixin.injection.Redirect;
//
//import java.util.List;
//import java.util.function.Predicate;
//
//@Mixin(Mob.class)
//public abstract class MixinMobEntity extends LivingEntity {
//
// protected MixinMobEntity(EntityType<? extends LivingEntity> entityType, Level world) {
// super(entityType, world);
// }
//
// @Redirect(method = "checkDespawn", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;findNearbyPlayer(Lnet/minecraft/world/entity/Entity;DLjava/util/function/Predicate;)Lnet/minecraft/world/entity/player/Player;"))
// private Player redirectGetClosestPlayer(Level instance, Entity entity, double v, Predicate predicate) {
// final Player closestPlayer = instance.getNearestPlayer(entity, this.getType().getCategory().getDespawnDistance());
// if (closestPlayer != null) {
// return closestPlayer;
// } else {
// final List<? extends Player> players = this.level().players();
// if (players.isEmpty()) return null;
// return players.get(0);
// }
// }
//
//}

View File

@@ -0,0 +1,23 @@
package net.gensokyoreimagined.nitori.mixin.removed.world.portal_checks;
//import net.minecraft.world.entity.Entity;
//import net.minecraft.world.level.portal.PortalShape;
//import net.minecraft.world.phys.Vec3;
//import net.minecraft.server.level.ServerLevel;
//import net.minecraft.world.entity.EntityDimensions;
//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;
//
//@Mixin({PortalShape.class})
//public class DisablePortalChecksMixin {
// @Inject(
// at = {@At("HEAD")},
// method = {"findCollisionFreePosition"},
// cancellable = true
// )
// private static void init(Vec3 fallback, ServerLevel world, Entity entity, EntityDimensions dimensions, CallbackInfoReturnable<Vec3> cir) {
// cir.setReturnValue(fallback);
// }
//}

View File

@@ -1,8 +1,5 @@
package net.gensokyoreimagined.nitori.mixin.removed.world.tick_scheduler; package net.gensokyoreimagined.nitori.mixin.removed.world.tick_scheduler;
//TODO: Make this work with paper
//import it.unimi.dsi.fastutil.ints.IntOpenHashSet; //import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
//import it.unimi.dsi.fastutil.longs.Long2ReferenceAVLTreeMap; //import it.unimi.dsi.fastutil.longs.Long2ReferenceAVLTreeMap;
//import it.unimi.dsi.fastutil.objects.ObjectIterator; //import it.unimi.dsi.fastutil.objects.ObjectIterator;

View File

@@ -1,110 +0,0 @@
package net.gensokyoreimagined.nitori.mixin.shapes.lazy_shape_context;
import net.minecraft.world.phys.shapes.EntityCollisionContext;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.*;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Constant;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyConstant;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.function.Predicate;
@Mixin(EntityCollisionContext.class)
public class EntityShapeContextMixin {
@Mutable
@Shadow
@Final
private ItemStack heldItem;
@Mutable
@Shadow
@Final
private Predicate<FluidState> canStandOnFluid;
@Shadow
@Final
@Nullable
private Entity entity;
/**
* Mixin the instanceof to always return false to avoid the expensive inventory access.
* No need to use Opcodes.INSTANCEOF or similar.
*/
@SuppressWarnings("InvalidInjectorMethodSignature")
@ModifyConstant(
method = "<init>(Lnet/minecraft/world/entity/Entity;)V",
constant = @Constant(classValue = LivingEntity.class, ordinal = 0)
)
private static boolean redirectInstanceOf(Object ignored, Class<?> constant) {
return false;
}
@SuppressWarnings("InvalidInjectorMethodSignature")
@ModifyConstant(
method = "<init>(Lnet/minecraft/world/entity/Entity;)V",
constant = @Constant(classValue = LivingEntity.class, ordinal = 2)
)
private static boolean redirectInstanceOf2(Object ignored, Class<?> constant) {
return false;
}
@Inject(
method = "<init>(Lnet/minecraft/world/entity/Entity;)V",
at = @At("TAIL")
)
private void initFields(Entity entity, CallbackInfo ci) {
this.heldItem = null;
this.canStandOnFluid = null;
}
@Inject(
method = "isHoldingItem",
at = @At("HEAD")
)
public void isHolding(Item item, CallbackInfoReturnable<Boolean> cir) {
this.nitori$initHeldItem();
}
@Intrinsic
public ItemStack getHeldItem() {
return this.heldItem;
}
@SuppressWarnings({"UnresolvedMixinReference", "MixinAnnotationTarget"})
@Inject(
method = "getHeldItem",
at = @At("HEAD")
)
private void nitori$initHeldItem(CallbackInfoReturnable<ItemStack> callbackInfoReturnable) {
this.nitori$initHeldItem();
}
@Unique
private void nitori$initHeldItem() {
if (this.heldItem == null) {
this.heldItem = this.entity instanceof LivingEntity ? ((LivingEntity) this.entity).getMainHandItem() : ItemStack.EMPTY;
}
}
@Inject(
method = "canStandOnFluid",
at = @At("HEAD")
)
public void canWalkOnFluid(FluidState state, FluidState fluidState, CallbackInfoReturnable<Boolean> cir) {
if (this.canStandOnFluid == null) {
if (this.entity instanceof LivingEntity livingEntity) {
this.canStandOnFluid = livingEntity::canStandOnFluid;
} else {
this.canStandOnFluid = (liquid) -> false;
}
}
}
}

View File

@@ -1,33 +0,0 @@
package net.gensokyoreimagined.nitori.mixin.shapes.precompute_shape_arrays;
import net.minecraft.world.phys.shapes.CubePointRange;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
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;
@Mixin(CubePointRange.class)
public class FractionalDoubleListMixin {
@Shadow
@Final
private int parts;
private double scale;
@Inject(method = "<init>(I)V", at = @At("RETURN"))
public void initScale(int sectionCount, CallbackInfo ci) {
this.scale = 1.0D / this.parts;
}
/**
* @author JellySquid
* @reason Replace division with multiplication
*/
@Overwrite
public double getDouble(int position) {
return position * this.scale;
}
}

View File

@@ -0,0 +1,110 @@
package net.gensokyoreimagined.nitori.mixin.unapplied.shapes.lazy_shape_context;
//import net.minecraft.world.phys.shapes.EntityCollisionContext;
//import net.minecraft.world.entity.Entity;
//import net.minecraft.world.entity.LivingEntity;
//import net.minecraft.world.level.material.FluidState;
//import net.minecraft.world.item.Item;
//import net.minecraft.world.item.ItemStack;
//import org.jetbrains.annotations.Nullable;
//import org.spongepowered.asm.mixin.*;
//import org.spongepowered.asm.mixin.injection.At;
//import org.spongepowered.asm.mixin.injection.Constant;
//import org.spongepowered.asm.mixin.injection.Inject;
//import org.spongepowered.asm.mixin.injection.ModifyConstant;
//import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
//import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
//
//import java.util.function.Predicate;
//
//@Mixin(EntityCollisionContext.class)
//public class EntityShapeContextMixin {
// @Mutable
// @Shadow
// @Final
// private ItemStack heldItem;
//
// @Mutable
// @Shadow
// @Final
// private Predicate<FluidState> canStandOnFluid;
//
// @Shadow
// @Final
// @Nullable
// private Entity entity;
//
// /**
// * Mixin the instanceof to always return false to avoid the expensive inventory access.
// * No need to use Opcodes.INSTANCEOF or similar.
// */
// @SuppressWarnings("InvalidInjectorMethodSignature")
// @ModifyConstant(
// method = "<init>(Lnet/minecraft/world/entity/Entity;)V",
// constant = @Constant(classValue = LivingEntity.class, ordinal = 0)
// )
// private static boolean redirectInstanceOf(Object ignored, Class<?> constant) {
// return false;
// }
//
// @SuppressWarnings("InvalidInjectorMethodSignature")
// @ModifyConstant(
// method = "<init>(Lnet/minecraft/world/entity/Entity;)V",
// constant = @Constant(classValue = LivingEntity.class, ordinal = 2)
// )
// private static boolean redirectInstanceOf2(Object ignored, Class<?> constant) {
// return false;
// }
//
// @Inject(
// method = "<init>(Lnet/minecraft/world/entity/Entity;)V",
// at = @At("TAIL")
// )
// private void initFields(Entity entity, CallbackInfo ci) {
// this.heldItem = null;
// this.canStandOnFluid = null;
// }
//
// @Inject(
// method = "isHoldingItem",
// at = @At("HEAD")
// )
// public void isHolding(Item item, CallbackInfoReturnable<Boolean> cir) {
// this.nitori$initHeldItem();
// }
//
// @Intrinsic
// public ItemStack getHeldItem() {
// return this.heldItem;
// }
//
// @SuppressWarnings({"UnresolvedMixinReference", "MixinAnnotationTarget"})
// @Inject(
// method = "getHeldItem",
// at = @At("HEAD")
// )
// private void nitori$initHeldItem(CallbackInfoReturnable<ItemStack> callbackInfoReturnable) {
// this.nitori$initHeldItem();
// }
//
// @Unique
// private void nitori$initHeldItem() {
// if (this.heldItem == null) {
// this.heldItem = this.entity instanceof LivingEntity ? ((LivingEntity) this.entity).getMainHandItem() : ItemStack.EMPTY;
// }
// }
//
// @Inject(
// method = "canStandOnFluid",
// at = @At("HEAD")
// )
// public void canWalkOnFluid(FluidState state, FluidState fluidState, CallbackInfoReturnable<Boolean> cir) {
// if (this.canStandOnFluid == null) {
// if (this.entity instanceof LivingEntity livingEntity) {
// this.canStandOnFluid = livingEntity::canStandOnFluid;
// } else {
// this.canStandOnFluid = (liquid) -> false;
// }
// }
// }
//}

View File

@@ -0,0 +1,33 @@
package net.gensokyoreimagined.nitori.mixin.unapplied.shapes.precompute_shape_arrays;
//import net.minecraft.world.phys.shapes.CubePointRange;
//import org.spongepowered.asm.mixin.Final;
//import org.spongepowered.asm.mixin.Mixin;
//import org.spongepowered.asm.mixin.Overwrite;
//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;
//
//@Mixin(CubePointRange.class)
//public class FractionalDoubleListMixin {
// @Shadow
// @Final
// private int parts;
//
// private double scale;
//
// @Inject(method = "<init>(I)V", at = @At("RETURN"))
// public void initScale(int sectionCount, CallbackInfo ci) {
// this.scale = 1.0D / this.parts;
// }
//
// /**
// * @author JellySquid
// * @reason Replace division with multiplication
// */
// @Overwrite
// public double getDouble(int position) {
// return position * this.scale;
// }
//}

View File

@@ -1,76 +0,0 @@
package net.gensokyoreimagined.nitori.mixin.vmp.general.collections;
import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import net.gensokyoreimagined.nitori.access.ITypeFilterableList;
import net.minecraft.util.ClassInstanceMultiMap;
import org.objectweb.asm.Opcodes;
import org.spongepowered.asm.mixin.*;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import java.util.*;
@Mixin(value = ClassInstanceMultiMap.class, priority = 1005) // priority compatibility hack for lithium
public abstract class MixinTypeFilterableList<T> extends AbstractCollection<T> implements ITypeFilterableList {
@Mutable
@Shadow @Final private Map<Class<?>, List<T>> byClass;
@Mutable
@Shadow @Final private List<T> allInstances;
@Shadow @Final private Class<T> baseClass;
@Redirect(method = "<init>", at = @At(value = "FIELD", target = "Lnet/minecraft/util/ClassInstanceMultiMap;byClass:Ljava/util/Map;", opcode = Opcodes.PUTFIELD))
private void redirectSetElementsByType(ClassInstanceMultiMap<T> instance, Map<Class<?>, List<T>> value) {
this.byClass = new Object2ObjectLinkedOpenHashMap<>();
}
@Redirect(method = "<init>", at = @At(value = "FIELD", target = "Lnet/minecraft/util/ClassInstanceMultiMap;allInstances:Ljava/util/List;", opcode = Opcodes.PUTFIELD))
private void redirectSetAllElements(ClassInstanceMultiMap<T> instance, List<T> value) {
this.allInstances = new ObjectArrayList<>();
}
@Redirect(method = "<init>", at = @At(value = "INVOKE", target = "Lcom/google/common/collect/Maps;newHashMap()Ljava/util/HashMap;", remap = false))
private HashMap<?, ?> redirectNewHashMap() {
return null; // avoid unnecessary alloc
}
@Redirect(method = "<init>", at = @At(value = "INVOKE", target = "Lcom/google/common/collect/Lists;newArrayList()Ljava/util/ArrayList;", remap = false))
private ArrayList<?> redirectNewArrayList() {
return null;
}
@Override
public Object[] getBackingArray() {
return ((ObjectArrayList<T>) this.allInstances).elements();
}
/**
* @author ishland
* @reason use fastutil array list for faster iteration & use array for filtering iteration
*/
@Overwrite
public <S> Collection<S> find(Class<S> type) {
List<T> cached = this.byClass.get(type);
if (cached != null) return (Collection<S>) cached;
if (!this.baseClass.isAssignableFrom(type)) {
throw new IllegalArgumentException("Don't know how to search for " + type);
} else {
List<? extends T> list = this.byClass.computeIfAbsent(type,
typeClass -> {
ObjectArrayList<T> ts = new ObjectArrayList<>(this.allInstances.size());
for (Object _allElement : ((ObjectArrayList<T>) this.allInstances).elements()) {
if (typeClass.isInstance(_allElement)) {
ts.add((T) _allElement);
}
}
return ts;
}
);
return (Collection<S>) list;
}
}
}

View File

@@ -1,22 +0,0 @@
package net.gensokyoreimagined.nitori.mixin.vmp.playerwatching;
import net.minecraft.server.level.ChunkTrackingView;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
@Mixin(ChunkTrackingView.class)
public interface MixinChunkFilter {
/**
* @author ishland
* @reason use chebyshev distance
*/
@Overwrite
static boolean isWithinDistance(int centerX, int centerZ, int viewDistance, int x, int z, boolean includeEdge) {
int actualViewDistance = viewDistance + (includeEdge ? 1 : 0);
int xDistance = Math.abs(centerX - x);
int zDistance = Math.abs(centerZ - z);
return xDistance <= actualViewDistance && zDistance <= actualViewDistance;
}
}

View File

@@ -1,46 +0,0 @@
package net.gensokyoreimagined.nitori.mixin.vmp.playerwatching;
import net.gensokyoreimagined.nitori.common.chunkwatching.PlayerClientVDTracking;
import net.minecraft.server.level.ClientInformation;
import net.minecraft.server.level.ServerPlayer;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(ServerPlayer.class)
public class MixinServerPlayerEntity implements PlayerClientVDTracking {
@Unique
private boolean vdChanged = false;
@Unique
private int clientVD = 2;
@Inject(method = "updateOptions", at = @At("HEAD"))
private void onClientSettingsChanged(ClientInformation packet, CallbackInfo ci) {
final int currentVD = packet.viewDistance();
if (currentVD != this.clientVD) this.vdChanged = true;
this.clientVD = Math.max(2, currentVD);
}
@Inject(method = "restoreFrom", at = @At("RETURN"))
private void onPlayerCopy(ServerPlayer oldPlayer, boolean alive, CallbackInfo ci) {
this.clientVD = ((PlayerClientVDTracking) oldPlayer).getClientViewDistance();
this.vdChanged = true;
}
@Unique
@Override
public boolean isClientViewDistanceChanged() {
return this.vdChanged;
}
@Unique
@Override
public int getClientViewDistance() {
this.vdChanged = false;
return this.clientVD;
}
}

View File

@@ -1,35 +0,0 @@
package net.gensokyoreimagined.nitori.mixin.vmp.playerwatching.optimize_nearby_player_lookups;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import java.util.List;
import java.util.function.Predicate;
@Mixin(Mob.class)
public abstract class MixinMobEntity extends LivingEntity {
protected MixinMobEntity(EntityType<? extends LivingEntity> entityType, Level world) {
super(entityType, world);
}
@Redirect(method = "checkDespawn", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;findNearbyPlayer(Lnet/minecraft/world/entity/Entity;DLjava/util/function/Predicate;)Lnet/minecraft/world/entity/player/Player;"))
private Player redirectGetClosestPlayer(Level instance, Entity entity, double v, Predicate predicate) {
final Player closestPlayer = instance.getNearestPlayer(entity, this.getType().getCategory().getDespawnDistance());
if (closestPlayer != null) {
return closestPlayer;
} else {
final List<? extends Player> players = this.level().players();
if (players.isEmpty()) return null;
return players.get(0);
}
}
}

View File

@@ -0,0 +1,35 @@
package net.gensokyoreimagined.nitori.mixin.world.block_entity_ticking;
import com.google.common.collect.Lists;
import net.gensokyoreimagined.nitori.common.util.collections.HashedReferenceList;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.TickingBlockEntity;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
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 java.util.List;
@Mixin(Level.class)
public class HashedReferenceListMixin {
// Implementation of 0006-lithium-HashedReferenceList.patch
@Mutable
@Final @Shadow
public List<TickingBlockEntity> blockEntityTickers;
// Implementation of 0006-lithium-HashedReferenceList.patch
@Mutable
@Final @Shadow
private List<TickingBlockEntity> pendingBlockEntityTickers;
// Implementation of 0006-lithium-HashedReferenceList.patch
@Inject(method = "<init>", at = @At("RETURN"))
private void onInit(CallbackInfo ci) {
this.blockEntityTickers = new HashedReferenceList<>(Lists.newArrayList());
this.pendingBlockEntityTickers = new HashedReferenceList<>(Lists.newArrayList());
}
}

View File

@@ -0,0 +1,24 @@
package net.gensokyoreimagined.nitori.mixin.world.block_entity_ticking.sleeping;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.block.entity.TickingBlockEntity;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(ServerLevel.class)
public class ServerWorldMixin {
@Redirect(
method = "dumpBlockEntityTickers",
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/entity/TickingBlockEntity;getPos()Lnet/minecraft/core/BlockPos;")
)
private BlockPos getPosOrOrigin(TickingBlockEntity instance) {
BlockPos pos = instance.getPos();
if (pos == null) {
return BlockPos.ZERO;
}
return pos;
}
}

View File

@@ -0,0 +1,41 @@
package net.gensokyoreimagined.nitori.mixin.world.block_entity_ticking.sleeping;
import net.gensokyoreimagined.nitori.common.block.entity.SleepingBlockEntity;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityTicker;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.block.entity.TickingBlockEntity;
import net.minecraft.world.level.chunk.LevelChunk;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Coerce;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
@Mixin(LevelChunk.class)
public class WorldChunkMixin {
@Inject(
method = "lambda$updateBlockEntityTicker$5",
at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;addBlockEntityTicker(Lnet/minecraft/world/level/block/entity/TickingBlockEntity;)V" ),
locals = LocalCapture.CAPTURE_FAILHARD
)
private void setBlockEntityTickingOrder(BlockEntity blockEntity, BlockEntityTicker<?> blockEntityTicker, BlockPos pos, @Coerce Object wrappedBlockEntityTickInvoker, CallbackInfoReturnable<?> cir, TickingBlockEntity blockEntityTickInvoker, @Coerce Object wrappedBlockEntityTickInvoker2) {
if (blockEntity instanceof SleepingBlockEntity sleepingBlockEntity) {
sleepingBlockEntity.lithium$setTickWrapper((WrappedBlockEntityTickInvokerAccessor) wrappedBlockEntityTickInvoker2);
}
}
@Inject(
method = "lambda$updateBlockEntityTicker$5",
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/chunk/LevelChunk$RebindableTickingBlockEntityWrapper;rebind(Lnet/minecraft/world/level/block/entity/TickingBlockEntity;)V" ),
locals = LocalCapture.CAPTURE_FAILHARD
)
private void setBlockEntityTickingOrder(BlockEntity blockEntity, BlockEntityTicker<?> blockEntityTicker, BlockPos pos, @Coerce Object wrappedBlockEntityTickInvoker, CallbackInfoReturnable<?> cir, TickingBlockEntity blockEntityTickInvoker) {
if (blockEntity instanceof SleepingBlockEntity sleepingBlockEntity) {
sleepingBlockEntity.lithium$setTickWrapper((WrappedBlockEntityTickInvokerAccessor) wrappedBlockEntityTickInvoker);
}
}
}

View File

@@ -0,0 +1,22 @@
package net.gensokyoreimagined.nitori.mixin.world.block_entity_ticking.sleeping;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.Level;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(Level.class)
public class WorldMixin {
@Redirect(
method = "tickBlockEntities",
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;shouldTickBlocksAt(Lnet/minecraft/core/BlockPos;)Z" )
)
private boolean shouldTickBlockPosFilterNull(Level instance, BlockPos pos) {
if (pos == null) {
return false;
}
return instance.shouldTickBlocksAt(pos);
}
}

View File

@@ -0,0 +1,90 @@
package net.gensokyoreimagined.nitori.mixin.world.block_entity_ticking.sleeping.brewing_stand;
import net.gensokyoreimagined.nitori.common.block.entity.SleepingBlockEntity;
import net.gensokyoreimagined.nitori.mixin.world.block_entity_ticking.sleeping.WrappedBlockEntityTickInvokerAccessor;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.entity.BrewingStandBlockEntity;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.TickingBlockEntity;
import org.spongepowered.asm.mixin.Intrinsic;
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;
@Mixin(BrewingStandBlockEntity.class)
public class BrewingStandBlockEntityMixin extends BlockEntity implements SleepingBlockEntity {
@Shadow
int brewTime;
private WrappedBlockEntityTickInvokerAccessor tickWrapper = null;
private TickingBlockEntity sleepingTicker = null;
public BrewingStandBlockEntityMixin(BlockEntityType<?> type, BlockPos pos, BlockState state) {
super(type, pos, state);
}
@Override
public WrappedBlockEntityTickInvokerAccessor lithium$getTickWrapper() {
return tickWrapper;
}
@Override
public void lithium$setTickWrapper(WrappedBlockEntityTickInvokerAccessor tickWrapper) {
this.tickWrapper = tickWrapper;
this.lithium$setSleepingTicker(null);
}
@Override
public TickingBlockEntity lithium$getSleepingTicker() {
return sleepingTicker;
}
@Override
public void lithium$setSleepingTicker(TickingBlockEntity sleepingTicker) {
this.sleepingTicker = sleepingTicker;
}
@Inject(method = "serverTick", at = @At("HEAD"))
private static void checkSleep(Level world, BlockPos pos, BlockState state, BrewingStandBlockEntity blockEntity, CallbackInfo ci) {
((BrewingStandBlockEntityMixin) (Object) blockEntity).checkSleep(state);
}
@Inject(method = "serverTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/entity/BrewingStandBlockEntity;setChanged(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;)V"))
private static void wakeUpOnMarkDirty(Level world, BlockPos pos, BlockState state, BrewingStandBlockEntity blockEntity, CallbackInfo ci) {
((BrewingStandBlockEntityMixin) (Object) blockEntity).wakeUpNow();
}
private void checkSleep(BlockState state) {
if (this.brewTime == 0 && state.is(Blocks.BREWING_STAND) && this.level != null) {
this.nitori$startSleeping();
}
}
@Inject(method = "loadAdditional", at = @At("RETURN"))
private void wakeUpAfterFromTag(CallbackInfo ci) {
if (this.isSleeping() && this.level != null && !this.level.isClientSide()) {
this.wakeUpNow();
}
}
@Override
@Intrinsic
public void setChanged() {
super.setChanged();
}
@SuppressWarnings({"MixinAnnotationTarget", "UnresolvedMixinReference"})
@Inject(method = "markDirty()V", at = @At("RETURN"))
private void wakeOnMarkDirty(CallbackInfo ci) {
if (this.isSleeping() && this.level != null && !this.level.isClientSide) {
this.wakeUpNow();
}
}
}

View File

@@ -1,69 +1,69 @@
package net.gensokyoreimagined.nitori.mixin.world.block_entity_ticking.sleeping.campfire; package net.gensokyoreimagined.nitori.mixin.world.block_entity_ticking.sleeping.campfire;
//import net.gensokyoreimagined.nitori.common.block.entity.SleepingBlockEntity; import net.gensokyoreimagined.nitori.common.block.entity.SleepingBlockEntity;
//import net.gensokyoreimagined.nitori.mixin.world.block_entity_ticking.sleeping.WrappedBlockEntityTickInvokerAccessor; import net.gensokyoreimagined.nitori.mixin.world.block_entity_ticking.sleeping.WrappedBlockEntityTickInvokerAccessor;
//import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
//import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
//import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
//import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.entity.BlockEntityType;
//import net.minecraft.world.level.block.entity.CampfireBlockEntity; import net.minecraft.world.level.block.entity.CampfireBlockEntity;
//import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.LivingEntity;
//import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
//import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
//import net.minecraft.core.HolderLookup; import net.minecraft.core.HolderLookup;
//import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
//import net.minecraft.world.level.block.entity.TickingBlockEntity; import net.minecraft.world.level.block.entity.TickingBlockEntity;
//import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
//import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
//import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
//import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
//import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
//
//@Mixin(CampfireBlockEntity.class) @Mixin(CampfireBlockEntity.class)
//public class CampfireBlockEntityMixin extends BlockEntity implements SleepingBlockEntity { public class CampfireBlockEntityMixin extends BlockEntity implements SleepingBlockEntity {
//
// private WrappedBlockEntityTickInvokerAccessor tickWrapper = null; private WrappedBlockEntityTickInvokerAccessor tickWrapper = null;
// private TickingBlockEntity sleepingTicker = null; private TickingBlockEntity sleepingTicker = null;
//
// public CampfireBlockEntityMixin(BlockEntityType<?> type, BlockPos pos, BlockState state) { public CampfireBlockEntityMixin(BlockEntityType<?> type, BlockPos pos, BlockState state) {
// super(type, pos, state); super(type, pos, state);
// } }
//
// @Override @Override
// public WrappedBlockEntityTickInvokerAccessor lithium$getTickWrapper() { public WrappedBlockEntityTickInvokerAccessor lithium$getTickWrapper() {
// return tickWrapper; return tickWrapper;
// } }
//
// @Override @Override
// public void lithium$setTickWrapper(WrappedBlockEntityTickInvokerAccessor tickWrapper) { public void lithium$setTickWrapper(WrappedBlockEntityTickInvokerAccessor tickWrapper) {
// this.tickWrapper = tickWrapper; this.tickWrapper = tickWrapper;
// this.lithium$setSleepingTicker(null); this.lithium$setSleepingTicker(null);
// } }
//
// @Override @Override
// public TickingBlockEntity lithium$getSleepingTicker() { public TickingBlockEntity lithium$getSleepingTicker() {
// return sleepingTicker; return sleepingTicker;
// } }
//
// @Override @Override
// public void lithium$setSleepingTicker(TickingBlockEntity sleepingTicker) { public void lithium$setSleepingTicker(TickingBlockEntity sleepingTicker) {
// this.sleepingTicker = sleepingTicker; this.sleepingTicker = sleepingTicker;
// } }
//
//
// @Inject( @Inject(
// method = "placeFood", method = "placeFood",
// at = @At(value = "INVOKE", target = "Lnet/minecraft/core/NonNullList;set(ILjava/lang/Object;)Ljava/lang/Object;") at = @At(value = "INVOKE", target = "Lnet/minecraft/core/NonNullList;set(ILjava/lang/Object;)Ljava/lang/Object;")
// ) )
// private void wakeUpOnAddItem(LivingEntity user, ItemStack stack, int cookTime, CallbackInfoReturnable<Boolean> cir) { private void wakeUpOnAddItem(LivingEntity user, ItemStack stack, int cookTime, CallbackInfoReturnable<Boolean> cir) {
// this.wakeUpNow(); this.wakeUpNow();
// } }
//
// @Inject( @Inject(
// method = "loadAdditional", method = "loadAdditional",
// at = @At(value = "RETURN") at = @At(value = "RETURN")
// ) )
// private void wakeUpOnReadNbt(CompoundTag nbt, HolderLookup.Provider registryLookup, CallbackInfo ci) { private void wakeUpOnReadNbt(CompoundTag nbt, HolderLookup.Provider registryLookup, CallbackInfo ci) {
// this.wakeUpNow(); this.wakeUpNow();
// } }
//} }

View File

@@ -1,40 +1,34 @@
package net.gensokyoreimagined.nitori.mixin.world.block_entity_ticking.sleeping.campfire.lit; package net.gensokyoreimagined.nitori.mixin.world.block_entity_ticking.sleeping.campfire.lit;
//import net.gensokyoreimagined.nitori.common.block.entity.SleepingBlockEntity; import net.gensokyoreimagined.nitori.common.block.entity.SleepingBlockEntity;
//import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
//import net.minecraft.world.SimpleContainer; import net.minecraft.world.level.Level;
//import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.entity.BlockEntity;
//import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntityType;
//import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.CampfireBlockEntity;
//import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState;
//import net.minecraft.world.level.block.entity.CampfireBlockEntity; import org.spongepowered.asm.mixin.Mixin;
//import net.minecraft.world.level.block.state.BlockState; import org.spongepowered.asm.mixin.injection.At;
//import org.bukkit.craftbukkit.inventory.CraftItemStack; import org.spongepowered.asm.mixin.injection.Inject;
//import org.bukkit.event.block.BlockCookEvent; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
//import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
//import org.spongepowered.asm.mixin.injection.At;
//import org.spongepowered.asm.mixin.injection.Inject; @Mixin(CampfireBlockEntity.class)
//import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; public abstract class CampfireBlockEntityMixin extends BlockEntity implements SleepingBlockEntity {
//import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
// public CampfireBlockEntityMixin(BlockPos pos, BlockState state) {
//import java.util.Optional; super(BlockEntityType.CAMPFIRE, pos, state);
// }
//@Mixin(CampfireBlockEntity.class)
//public abstract class CampfireBlockEntityMixin extends BlockEntity implements SleepingBlockEntity { @Inject(
// method = "cookTick",
// public CampfireBlockEntityMixin(BlockPos pos, BlockState state) { at = @At("RETURN"),
// super(BlockEntityType.CAMPFIRE, pos, state); locals = LocalCapture.CAPTURE_FAILHARD
// } )
// private static void trySleepLit(Level world, BlockPos pos, BlockState state, CampfireBlockEntity campfire, CallbackInfo ci, boolean flag) {
// @Inject( if (!flag) {
// method = "cookTick", CampfireBlockEntityMixin self = (CampfireBlockEntityMixin) (Object) campfire;
// at = @At("RETURN"), self.nitori$startSleeping();
// locals = LocalCapture.CAPTURE_FAILHARD }
// ) }
// private static void trySleepLit(Level world, BlockPos pos, BlockState state, CampfireBlockEntity campfire, CallbackInfo ci, boolean flag) { }
// if (!flag) {
// CampfireBlockEntityMixin self = (CampfireBlockEntityMixin) (Object) campfire;
// self.nitori$startSleeping();
// }
// }
//}

View File

@@ -1,34 +1,34 @@
package net.gensokyoreimagined.nitori.mixin.world.block_entity_ticking.sleeping.campfire.unlit; package net.gensokyoreimagined.nitori.mixin.world.block_entity_ticking.sleeping.campfire.unlit;
//import net.gensokyoreimagined.nitori.common.block.entity.SleepingBlockEntity; import net.gensokyoreimagined.nitori.common.block.entity.SleepingBlockEntity;
//import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
//import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
//import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
//import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.entity.BlockEntityType;
//import net.minecraft.world.level.block.entity.CampfireBlockEntity; import net.minecraft.world.level.block.entity.CampfireBlockEntity;
//import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
//import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
//import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
//import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
//import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
//import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
//
//@Mixin(CampfireBlockEntity.class) @Mixin(CampfireBlockEntity.class)
//public abstract class CampfireBlockEntityMixin extends BlockEntity implements SleepingBlockEntity { public abstract class CampfireBlockEntityMixin extends BlockEntity implements SleepingBlockEntity {
//
// public CampfireBlockEntityMixin(BlockEntityType<?> type, BlockPos pos, BlockState state) { public CampfireBlockEntityMixin(BlockEntityType<?> type, BlockPos pos, BlockState state) {
// super(type, pos, state); super(type, pos, state);
// } }
//
// @Inject( @Inject(
// method = "cooldownTick", method = "cooldownTick",
// at = @At("RETURN"), at = @At("RETURN"),
// locals = LocalCapture.CAPTURE_FAILHARD locals = LocalCapture.CAPTURE_FAILHARD
// ) )
// private static void trySleepLit(Level world, BlockPos pos, BlockState state, CampfireBlockEntity campfire, CallbackInfo ci, boolean flag) { private static void trySleepLit(Level world, BlockPos pos, BlockState state, CampfireBlockEntity campfire, CallbackInfo ci, boolean flag) {
// if (!flag) { if (!flag) {
// CampfireBlockEntityMixin self = (CampfireBlockEntityMixin) (Object) campfire; CampfireBlockEntityMixin self = (CampfireBlockEntityMixin) (Object) campfire;
// self.nitori$startSleeping(); self.nitori$startSleeping();
// } }
// } }
//} }

View File

@@ -0,0 +1,106 @@
package net.gensokyoreimagined.nitori.mixin.world.block_entity_ticking.sleeping.hopper;
//import net.gensokyoreimagined.nitori.common.block.entity.SleepingBlockEntity;
//import net.gensokyoreimagined.nitori.mixin.world.block_entity_ticking.sleeping.WrappedBlockEntityTickInvokerAccessor;
//import net.minecraft.world.level.block.state.BlockState;
//import net.minecraft.world.level.block.HopperBlock;
//import net.minecraft.world.level.block.entity.BlockEntity;
//import net.minecraft.world.level.block.entity.BlockEntityType;
//import net.minecraft.world.level.block.entity.HopperBlockEntity;
//import net.minecraft.core.BlockPos;
//import net.minecraft.world.level.Level;
//import net.minecraft.world.level.block.entity.TickingBlockEntity;
//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 org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
//
//import java.util.function.BooleanSupplier;
//
//@Mixin(HopperBlockEntity.class)
//public class HopperBlockEntityMixin extends BlockEntity implements SleepingBlockEntity {
//
// @Shadow
// private long tickedGameTime;
//
// @Shadow
// private native boolean isOnCooldown();
//
// private WrappedBlockEntityTickInvokerAccessor tickWrapper = null;
// private TickingBlockEntity sleepingTicker = null;
//
// @Inject(
// method = "tryMoveItems",
// at = @At(value = "RETURN", ordinal = 2)
// )
// private static void sleepIfNoCooldownAndLocked(Level world, BlockPos pos, BlockState state, HopperBlockEntity blockEntity, BooleanSupplier booleanSupplier, CallbackInfoReturnable<Boolean> cir) {
// if (!((HopperBlockEntityMixin) (Object) blockEntity).isOnCooldown() &&
// !((HopperBlockEntityMixin) (Object) blockEntity).isSleeping() &&
// !state.get(HopperBlock.ENABLED)) {
// ((HopperBlockEntityMixin) (Object) blockEntity).lithium$startSleeping();
// }
// }
//
// @Override
// public WrappedBlockEntityTickInvokerAccessor lithium$getTickWrapper() {
// return tickWrapper;
// }
//
// @Override
// public void lithium$setTickWrapper(WrappedBlockEntityTickInvokerAccessor tickWrapper) {
// this.tickWrapper = tickWrapper;
// this.lithium$setSleepingTicker(null);
// }
//
// @Override
// public TickingBlockEntity lithium$getSleepingTicker() {
// return sleepingTicker;
// }
//
// public HopperBlockEntityMixin(BlockEntityType<?> type, BlockPos pos, BlockState state) {
// super(type, pos, state);
// }
//
// @Override
// public void lithium$setSleepingTicker(TickingBlockEntity sleepingTicker) {
// this.sleepingTicker = sleepingTicker;
// }
//
// @Override
// public boolean nitori$startSleeping() {
// if (this.isSleeping()) {
// return false;
// }
//
// WrappedBlockEntityTickInvokerAccessor tickWrapper = this.lithium$getTickWrapper();
// if (tickWrapper != null) {
// this.lithium$setSleepingTicker(tickWrapper.getWrapped());
// tickWrapper.callSetWrapped(SleepingBlockEntity.SLEEPING_BLOCK_ENTITY_TICKER);
//
// // Set the last tick time to max value, so other hoppers transferring into this hopper will set it to 7gt
// // cooldown. Then when waking up, we make sure to not tick this hopper in the same gametick.
// // This makes the observable hopper cooldown not be different from vanilla.
// this.tickedGameTime = Long.MAX_VALUE;
// return true;
// }
// return false;
// }
//
// @Inject(
// method = "setTransferCooldown",
// at = @At("HEAD" )
// )
// private void wakeUpOnCooldownSet(int transferCooldown, CallbackInfo ci) {
// if (transferCooldown == 7) {
// if (this.tickedGameTime == Long.MAX_VALUE) {
// this.sleepOnlyCurrentTick();
// } else {
// this.wakeUpNow();
// }
// } else if (transferCooldown > 0 && this.sleepingTicker != null) {
// this.wakeUpNow();
// }
// }
//}

View File

@@ -0,0 +1,67 @@
package net.gensokyoreimagined.nitori.mixin.world.block_entity_ticking.sleeping.shulker_box;
import net.gensokyoreimagined.nitori.common.block.entity.SleepingBlockEntity;
import net.gensokyoreimagined.nitori.mixin.world.block_entity_ticking.sleeping.WrappedBlockEntityTickInvokerAccessor;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.entity.ShulkerBoxBlockEntity;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.TickingBlockEntity;
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 org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(ShulkerBoxBlockEntity.class)
public class ShulkerBoxBlockEntityMixin implements SleepingBlockEntity {
@Shadow
private ShulkerBoxBlockEntity.AnimationStatus animationStatus;
@Shadow
private float progress;
@Shadow
private float progressOld;
private WrappedBlockEntityTickInvokerAccessor tickWrapper = null;
private TickingBlockEntity sleepingTicker = null;
@Override
public WrappedBlockEntityTickInvokerAccessor lithium$getTickWrapper() {
return tickWrapper;
}
@Override
public void lithium$setTickWrapper(WrappedBlockEntityTickInvokerAccessor tickWrapper) {
this.tickWrapper = tickWrapper;
}
@Override
public TickingBlockEntity lithium$getSleepingTicker() {
return sleepingTicker;
}
@Override
public void lithium$setSleepingTicker(TickingBlockEntity sleepingTicker) {
this.sleepingTicker = sleepingTicker;
}
@Inject(
method = "triggerEvent",
at = @At("HEAD")
)
private void wakeUpOnSyncedBlockEvent(int type, int data, CallbackInfoReturnable<Boolean> cir) {
if (this.sleepingTicker != null) {
this.wakeUpNow();
}
}
@Inject(
method = "updateAnimation",
at = @At(value = "RETURN")
)
private void sleepOnAnimationEnd(Level world, BlockPos pos, BlockState state, CallbackInfo ci) {
if (this.animationStatus == animationStatus.CLOSED && this.progressOld == 0.0f && this.progress == 0.0f) {
this.nitori$startSleeping();
}
}
}

View File

@@ -0,0 +1,81 @@
package net.gensokyoreimagined.nitori.mixin.world.block_entity_ticking.world_border;
//import net.gensokyoreimagined.nitori.common.world.listeners.WorldBorderListenerOnce;
//import net.minecraft.server.level.FullChunkStatus;
//import net.minecraft.server.level.ServerLevel;
//import net.minecraft.core.BlockPos;
//import net.minecraft.world.level.ChunkPos;
//import net.minecraft.world.level.Level;
//import net.minecraft.world.level.border.WorldBorder;
//import net.minecraft.world.level.border.BorderStatus;
//import net.minecraft.world.level.chunk.LevelChunk;
//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.Redirect;
//
//@Mixin(targets = "net.minecraft.world.level.chunk.LevelChunk$BoundTickingBlockEntity")
//public abstract class DirectBlockEntityTickInvokerMixin implements WorldBorderListenerOnce {
//
// @Shadow
// @Final
// LevelChunk LevelChunk;
//
// @Shadow
// public abstract BlockPos getPos();
//
// private byte worldBorderState = 0;
//
// @Redirect(
// method = "tick",
// at = @At(
// value = "INVOKE",
// target = "Lnet/minecraft/world/chunk/WorldChunk;canTickBlockEntity(Lnet/minecraft/util/math/BlockPos;)Z"
// )
// )
// private boolean cachedCanTickBlockEntity(LevelChunk instance, BlockPos pos) {
// if (this.isInsideWorldBorder()) {
// Level world = this.LevelChunk.getLevel();
// if (world instanceof ServerLevel serverWorld) {
// return this.LevelChunk.getFullStatus().isOrAfter(FullChunkStatus.BLOCK_TICKING) && serverWorld.areEntitiesLoaded(ChunkPos.asLong(pos));
// }
// return true;
// } else {
// return false;
// }
// }
//
// private boolean isInsideWorldBorder() {
// if (this.worldBorderState == (byte) 0) {
// this.startWorldBorderCaching();
// }
//
// int worldBorderState = this.worldBorderState;
// if ((worldBorderState & 3) == 3) {
// return (worldBorderState & 4) != 0;
// }
// return this.LevelChunk.getLevel().getWorldBorder().isWithinBounds(this.getPos());
// }
//
// private void startWorldBorderCaching() {
// this.worldBorderState = (byte) 1;
// WorldBorder worldBorder = this.LevelChunk.getLevel().getWorldBorder();
// worldBorder.addListener(this);
// boolean isStationary = worldBorder.getStatus() == BorderStatus.STATIONARY;
// if (worldBorder.isWithinBounds(this.getPos())) {
// if (isStationary || worldBorder.getStatus() == BorderStatus.GROWING) {
// this.worldBorderState |= (byte) 6;
// }
// } else {
// if (isStationary || worldBorder.getStatus() == BorderStatus.SHRINKING) {
// this.worldBorderState |= (byte) 2;
// }
// }
// }
//
// @Override
// public void lithium$onWorldBorderShapeChange(WorldBorder worldBorder) {
// this.worldBorderState = (byte) 0;
// }
//}

View File

@@ -1,23 +0,0 @@
package net.gensokyoreimagined.nitori.mixin.world.portal_checks;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.portal.PortalShape;
import net.minecraft.world.phys.Vec3;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.EntityDimensions;
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;
@Mixin({PortalShape.class})
public class DisablePortalChecksMixin {
@Inject(
at = {@At("HEAD")},
method = {"findCollisionFreePosition"},
cancellable = true
)
private static void init(Vec3 fallback, ServerLevel world, Entity entity, EntityDimensions dimensions, CallbackInfoReturnable<Vec3> cir) {
cir.setReturnValue(fallback);
}
}

View File

@@ -1,50 +0,0 @@
// Gale - virtual thread support
package net.gensokyoreimagined.nitori.virtual_thread;
import org.jetbrains.annotations.NotNull;
import java.util.concurrent.ThreadFactory;
/**
* An implementation of {@link VirtualThreadService} that can create virtual threads directly.
*
* @author Martijn Muijsers
*/
final class DirectVirtualThreadService extends VirtualThreadService {
private DirectVirtualThreadService() {
super();
}
@Override
public @NotNull ThreadFactory createFactory() {
// Disabled until Minecraft requires servers to have a Java version that can read class files compiled with functionality from Java 19+ on preview / Java 21+ on stable
throw new UnsupportedOperationException();
// return Thread.ofVirtual().factory();
}
@Override
public @NotNull Thread start(@NotNull Runnable task) {
// Disabled until Minecraft requires servers to have a Java version that can read class files compiled with functionality from Java 19+ on preview / Java 21+ on stable
throw new UnsupportedOperationException();
// Objects.requireNonNull(task, "The task to start a virtual thread cannot be null");
// return Thread.ofVirtual().start(task);
}
/**
* @return A functional {@link DirectVirtualThreadService}.
* @throws Throwable If creating virtual threads directly is not supported by the current runtime.
* This could be any {@link Throwable}, including an {@link Exception} or an {@link Error}.
*/
static @NotNull DirectVirtualThreadService create() throws Throwable {
// Disabled until Minecraft requires servers to have a Java version that can read class files compiled with functionality from Java 19+ on preview / Java 21+ on stable
throw new UnsupportedOperationException();
// var service = new DirectVirtualThreadService();
// // Run some tests to verify
// service.runTest();
// // If we end up here, it works
// return service;
}
}

View File

@@ -1,76 +0,0 @@
// Gale - virtual thread support
package net.gensokyoreimagined.nitori.virtual_thread;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Method;
import java.util.Objects;
import java.util.concurrent.ThreadFactory;
/**
* An implementation of {@link VirtualThreadService} that can create virtual threads using Java reflection.
*
* @author Martijn Muijsers
*/
final class ReflectionVirtualThreadService extends VirtualThreadService {
/**
* The {@link Thread}<code>#ofVirtual()</code> method.
*/
private final @NotNull Method Thread_ofVirtual_method;
/**
* The {@link Thread}<code>.Builder#factory()</code> method.
*/
private final @NotNull Method Thread_Builder_factory_method;
/**
* The {@link Thread}<code>.Builder#start(Runnable)</code> method.
*/
private final @NotNull Method Thread_Builder_start_method;
private ReflectionVirtualThreadService() throws Throwable {
this.Thread_ofVirtual_method = Objects.requireNonNull(Thread.class.getMethod("ofVirtual"));
// The Thread.Builder class
var Thread_Builder_class = Objects.requireNonNull(Class.forName("java.lang.Thread$Builder"));
this.Thread_Builder_factory_method = Objects.requireNonNull(Thread_Builder_class.getMethod("factory"));
this.Thread_Builder_start_method = Objects.requireNonNull(Thread_Builder_class.getMethod("start", Runnable.class));
}
@Override
public @NotNull ThreadFactory createFactory() {
try {
return (ThreadFactory) this.Thread_Builder_factory_method.invoke(this.Thread_ofVirtual_method.invoke(null));
} catch (Exception e) {
// This should not be possible because it was tested in create()
throw new RuntimeException(e);
}
}
@Override
public @NotNull Thread start(@NotNull Runnable task) {
Objects.requireNonNull(task, "The task to start a virtual thread cannot be null");
try {
return (Thread) this.Thread_Builder_start_method.invoke(this.Thread_ofVirtual_method.invoke(null), task);
} catch (Exception e) {
// This should not be possible because it was tested in create()
throw new RuntimeException(e);
}
}
/**
* @return A functional {@link ReflectionVirtualThreadService}.
* @throws Throwable If creating virtual threads via reflection is not supported by the current runtime.
* This could be any {@link Throwable}, including an {@link Exception} or an {@link Error}.
*/
static @NotNull ReflectionVirtualThreadService create() throws Throwable {
// This will already throw something if the reflection fails
var service = new ReflectionVirtualThreadService();
// Run some tests to verify
service.runTest();
// If we end up here, it works
return service;
}
}

View File

@@ -1,101 +0,0 @@
// Gale - virtual thread support
package net.gensokyoreimagined.nitori.virtual_thread;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.concurrent.ThreadFactory;
/**
* An abstract service to create virtual threads.
*
* @author Martijn Muijsers
*/
public sealed abstract class VirtualThreadService permits ReflectionVirtualThreadService, DirectVirtualThreadService {
/**
* @return A {@link ThreadFactory} that produces virtual threads.
*/
public abstract @NotNull ThreadFactory createFactory();
/**
* @param task The runnable for the thread to execute.
* @return A virtual thread that has been started with the given task.
*/
public abstract @NotNull Thread start(Runnable task);
/**
* Runs a test on the {@link #createFactory} and {@link #start} methods,
* which certainly throws some {@link Throwable} if something goes wrong.
*/
protected void runTest() throws Throwable {
// This will definitely throw something if it doesn't work
try {
this.start(() -> {}).join();
} catch (InterruptedException ignored) {} // Except InterruptedException, we don't care about that one
try {
var thread = this.createFactory().newThread(() -> {});
thread.start();
thread.join();
} catch (InterruptedException ignored) {} // Except InterruptedException, we don't care about that one
// If we end up here, it works
}
private static boolean initialized = false;
/**
* The {@link VirtualThreadService} for the current runtime,
* or null if virtual threads are not supported, or if not {@link #initialized} yet.
*/
private static @Nullable VirtualThreadService implementation;
/**
* @return Whether virtual threads are supported on the current runtime.
*/
public static boolean isSupported() {
return get() != null;
}
/**
* @return The {@link VirtualThreadService} for the current runtime,
* or null if virtual threads are not {@linkplain #isSupported() supported}.
*
* This method is thread-safe only after the first time it has been fully run.
*/
public static @Nullable VirtualThreadService get() {
if (!initialized) {
initialized = true;
try {
implementation = DirectVirtualThreadService.create();
} catch (Throwable ignored) {
try {
implementation = ReflectionVirtualThreadService.create();
} catch (Throwable ignored2) {}
}
}
return implementation;
}
/**
* The minimum major version of Java that is known to support using virtual threads
* (although possibly behind a feature preview flag).
*/
public static final int minimumJavaMajorVersionWithFeaturePreview = 19;
/**
* The minimum major version of Java that is known to support using virtual threads
* even without any feature preview flags.
*/
public static final int minimumJavaMajorVersionWithoutFeaturePreview = 21;
public static int getJavaMajorVersion() {
var version = System.getProperty("java.version");
if (version.startsWith("1.")) {
return version.charAt(2) - '0';
}
int dotIndex = version.indexOf(".");
return Integer.parseInt(dotIndex == -1 ? version : version.substring(0, dotIndex));
}
}

View File

@@ -1,6 +0,0 @@
package net.gensokyoreimagined.nitori.virtual_thread;
/*
Original patch:
https://github.com/GaleMC/Gale/blob/ver/1.20.2/patches/server/0145-Virtual-thread-support.patch
*/

View File

@@ -1,6 +1,6 @@
{ {
"id": "Nitori", "id": "Nitori",
"version": "1.5-SNAPSHOT", "version": "1.6-SNAPSHOT",
"mixins": [ "mixins": [
"mixins.core.json" "mixins.core.json"
] ]

View File

@@ -25,7 +25,6 @@
"collections.chunk_tickets.SortedArraySetMixin", "collections.chunk_tickets.SortedArraySetMixin",
"collections.entity_by_type.TypeFilterableListMixin", "collections.entity_by_type.TypeFilterableListMixin",
"collections.entity_filtering.TypeFilterableListMixin", "collections.entity_filtering.TypeFilterableListMixin",
"collections.goals.GoalSelectorMixin",
"collections.mob_spawning.SpawnSettingsMixin", "collections.mob_spawning.SpawnSettingsMixin",
"collections.fluid_submersion.EntityMixin", "collections.fluid_submersion.EntityMixin",
"collections.brain.BrainMixin", "collections.brain.BrainMixin",
@@ -41,13 +40,7 @@
"entity.replace_entitytype_predicates.AbstractDecorationEntityMixin", "entity.replace_entitytype_predicates.AbstractDecorationEntityMixin",
"entity.replace_entitytype_predicates.ItemFrameEntityMixin", "entity.replace_entitytype_predicates.ItemFrameEntityMixin",
"entity.pathfinding.TargetPredicateMixin", "entity.pathfinding.TargetPredicateMixin",
"entity.inactive_navigations.EntityNavigationMixin",
"entity.inactive_navigations.MobEntityMixin",
"logic.fast_bits_blockpos.OptimizedBlockPosBitsMixin",
"logic.fast_rotations.EulerAngleMixin",
"logic.reduce_ray_casting.BlockViewCastingMixin", "logic.reduce_ray_casting.BlockViewCastingMixin",
"math.fast_blockops.BlockPosMixin",
"math.fast_blockops.DirectionMixin",
"math.fast_util.AxisCycleDirectionMixin$BackwardMixin", "math.fast_util.AxisCycleDirectionMixin$BackwardMixin",
"math.fast_util.AxisCycleDirectionMixin$ForwardMixin", "math.fast_util.AxisCycleDirectionMixin$ForwardMixin",
"math.fast_util.DirectionMixin", "math.fast_util.DirectionMixin",
@@ -61,30 +54,29 @@
"math.rounding.FastRoundingSurfaceBuildMixin", "math.rounding.FastRoundingSurfaceBuildMixin",
"math.sine_lut.MixinMth", "math.sine_lut.MixinMth",
"math.vec.FastMathVec3DMixin", "math.vec.FastMathVec3DMixin",
"math.random.RandomMixin",
"network.microopt.VarIntsMixin", "network.microopt.VarIntsMixin",
"network.microopt.StringEncodingMixin", "network.microopt.StringEncodingMixin",
"network.block_breaking.CacheBlockBreakPacketMixin", "network.block_breaking.CacheBlockBreakPacketMixin",
"vmp.playerwatching.MixinChunkFilter", "network.move_zero_velocity.MixinEntity",
"vmp.playerwatching.MixinServerPlayerEntity",
"vmp.playerwatching.optimize_nearby_player_lookups.MixinMobEntity",
"vmp.general.collections.MixinTypeFilterableList",
"vmp.entity.move_zero_velocity.MixinEntity",
"shapes.blockstate_cache.BlockMixin", "shapes.blockstate_cache.BlockMixin",
"shapes.lazy_shape_context.EntityShapeContextMixin",
"shapes.precompute_shape_arrays.FractionalDoubleListMixin",
"shapes.precompute_shape_arrays.SimpleVoxelShapeMixin", "shapes.precompute_shape_arrays.SimpleVoxelShapeMixin",
"shapes.specialized_shapes.VoxelShapeMixin", "shapes.specialized_shapes.VoxelShapeMixin",
"util.MixinLevelBlockEntityRetrieval", "util.MixinLevelBlockEntityRetrieval",
"util.accessors.EntityTrackingSectionAccessor", "util.accessors.EntityTrackingSectionAccessor",
"util.block_tracking.AbstractBlockStateMixin", "util.block_tracking.AbstractBlockStateMixin",
"util.block_entity_retrieval.WorldMixin", "util.block_entity_retrieval.WorldMixin",
"world.block_entity_ticking.sleeping.WrappedBlockEntityTickInvokerAccessor",
"world.block_entity_ticking.sleeping.furnace.AbstractFurnaceBlockEntityMixin", "world.block_entity_ticking.sleeping.furnace.AbstractFurnaceBlockEntityMixin",
"world.block_entity_ticking.sleeping.brewing_stand.BrewingStandBlockEntityMixin",
"world.block_entity_ticking.sleeping.shulker_box.ShulkerBoxBlockEntityMixin",
"world.block_entity_ticking.sleeping.campfire.unlit.CampfireBlockEntityMixin",
"world.block_entity_ticking.sleeping.campfire.lit.CampfireBlockEntityMixin",
"world.block_entity_ticking.sleeping.campfire.CampfireBlockEntityMixin",
"world.block_entity_ticking.sleeping.ServerWorldMixin",
"world.block_entity_ticking.sleeping.WorldMixin",
"world.block_entity_ticking.sleeping.WrappedBlockEntityTickInvokerAccessor",
"world.block_entity_ticking.support_cache.BlockEntityMixin", "world.block_entity_ticking.support_cache.BlockEntityMixin",
"world.block_entity_ticking.support_cache.DirectBlockEntityTickInvokerMixin", "world.block_entity_ticking.support_cache.DirectBlockEntityTickInvokerMixin",
"world.block_entity_ticking.support_cache.WorldChunkMixin", "world.block_entity_ticking.support_cache.WorldChunkMixin",
"world.portal_checks.DisablePortalChecksMixin",
"world.blending.BlendMixin", "world.blending.BlendMixin",
"world.farmland.FarmlandBlockMixin", "world.farmland.FarmlandBlockMixin",
"world.biome_access.BiomeAccessMixin" "world.biome_access.BiomeAccessMixin"