Files
DimensionalRipper/tests/payload/SimulatedHandleRegression.java
T

102 lines
7.7 KiB
Java

package dev.modzuozhi;
import net.minecraft.core.BlockPos;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer;
import net.neoforged.neoforge.network.handling.ServerPayloadContext;
/** Isolated real packet, plot block entity and native constraint lifecycle fixture. */
public final class SimulatedHandleRegression {
public static void run(MinecraftServer server, ServerPayloadContext ctx) throws Exception {
if (!net.neoforged.fml.ModList.get().isLoaded("simulated")) return;
var level=server.overworld();
var handleId=ResourceLocation.parse("simulated:iron_handle");
ModZuozhi.LOGGER.info("Handle fixture block: {}",handleId);
var block=BuiltInRegistries.BLOCK.get(handleId);
var packet=Class.forName("dev.simulated_team.simulated.network.packets.UpdatePlayerUsingHandlePacket");
var ctor=packet.getConstructor(float.class,boolean.class,BlockPos.class);
var veilType=Class.forName("foundry.veil.api.network.handler.ServerPacketContext");
var veil=Class.forName("foundry.veil.forge.network.NeoForgeServerPacketContext")
.getConstructor(net.neoforged.neoforge.network.handling.IPayloadContext.class).newInstance(ctx);
var handle=packet.getMethod("handle",veilType);
var containerType=Class.forName("dev.ryanhcode.sable.api.sublevel.SubLevelContainer");
var subType=Class.forName("dev.ryanhcode.sable.sublevel.SubLevel");
var serverSubType=Class.forName("dev.ryanhcode.sable.sublevel.ServerSubLevel");
var poseType=Class.forName("dev.ryanhcode.sable.companion.math.Pose3d");
var container=call(containerType,null,"getContainer",Class.forName("dev.ryanhcode.sable.api.sublevel.ServerSubLevelContainer"),
new Class<?>[]{net.minecraft.server.level.ServerLevel.class},level);
var sub=call(containerType,container,"allocateNewSubLevel",subType,new Class<?>[]{poseType},poseType.getConstructor().newInstance());
var plot=subType.getMethod("getPlot").invoke(sub);
var plotType=Class.forName("dev.ryanhcode.sable.sublevel.plot.LevelPlot");
var pos=((BlockPos)plotType.getMethod("getCenterBlock").invoke(plot)).atY(115);
plotType.getMethod("newEmptyChunk",net.minecraft.world.level.ChunkPos.class).invoke(plot,new net.minecraft.world.level.ChunkPos(pos));
level.setBlockAndUpdate(pos,block.defaultBlockState());
var be=level.getBlockEntity(pos);
PayloadRegression.check(be!=null && be.getClass().getName().endsWith("HandleBlockEntity"),"real handle plot fixture");
var players=be.getClass().getDeclaredField("players");players.setAccessible(true);
var systemType=Class.forName("dev.ryanhcode.sable.sublevel.system.SubLevelPhysicsSystem");
var system=systemType.getMethod("get",net.minecraft.world.level.Level.class).invoke(null,level);
var body=systemType.getMethod("getPhysicsHandle",serverSubType).invoke(system,sub);
var bodyType=Class.forName("dev.ryanhcode.sable.api.physics.handle.RigidBodyHandle");
var jointType=Class.forName("dev.ryanhcode.sable.api.physics.constraint.PhysicsConstraintHandle");
Object joint=null;
var helper=Class.forName("dev.ryanhcode.sable.Sable").getField("HELPER").get(null);
var global=(net.minecraft.world.phys.Vec3)call(helper.getClass(),helper,"projectOutOfSubLevel",net.minecraft.world.phys.Vec3.class,
new Class<?>[]{net.minecraft.world.level.Level.class,net.minecraft.world.phys.Vec3.class},level,net.minecraft.world.phys.Vec3.atCenterOf(pos));
var player=ctx.player();player.setPos(global.x,global.y-1,global.z);player.getAbilities().flying=true;
level.addNewPlayer(player);
var release=new java.util.concurrent.CountDownLatch(1);
try {
for(boolean remove:new boolean[]{false,false,true}) {
var request=ctor.newInstance(4.0f,remove,pos);
if(remove) {
var entered=new java.util.concurrent.CountDownLatch(1);
var manager=dev.modzuozhi.core.dimthread.DimThreadCore.MANAGER;
manager.getLoop(level).execute(() -> {
server.execute(release::countDown);entered.countDown();
try {PayloadRegression.check(release.await(5,java.util.concurrent.TimeUnit.SECONDS),"native release callback pump");}
catch(InterruptedException e){throw new RuntimeException(e);}
});
manager.setPaused(server,false);
PayloadRegression.check(entered.await(5,java.util.concurrent.TimeUnit.SECONDS),"native release worker start");
// The old unprotected path clears player holding state but leaves the joint.
handle.invoke(request,veil);
PayloadRegression.check((boolean)jointType.getMethod("isValid").invoke(joint),"unprotected release did not reproduce stranded joint");
ModZuozhi.LOGGER.info("SIMULATED NATIVE RED: unprotected release left joint valid while worker owned plot");
}
ctx.enqueueWork(() -> {
try {handle.invoke(request,veil);} catch(ReflectiveOperationException e) {throw new RuntimeException(e);}
}).join();
var map=(java.util.Map<?,?>)players.get(be);
PayloadRegression.check(remove ? map.isEmpty() : map.containsKey(ctx.player().getUUID()),"real handle grab/release state");
if(!remove) {
be.getClass().getMethod("sable$physicsTick",serverSubType,bodyType,double.class).invoke(be,sub,body,0.05d);
var holding=map.get(player.getUUID());
var jointField=holding.getClass().getDeclaredField("constraintHandle");jointField.setAccessible(true);
joint=jointField.get(holding);
PayloadRegression.check(joint!=null && (boolean)jointType.getMethod("isValid").invoke(joint),"native handle joint created");
} else {
PayloadRegression.check(joint!=null && !(boolean)jointType.getMethod("isValid").invoke(joint),"native joint survived release packet");
dev.modzuozhi.core.dimthread.DimThreadCore.MANAGER.setPaused(server,true);
}
}
ModZuozhi.LOGGER.info("SIMULATED HANDLE PACKET PASS: real packet, BE and native joint invalidated on release");
} finally {
release.countDown();
dev.modzuozhi.core.dimthread.DimThreadCore.MANAGER.setPaused(server,true);
level.setBlockAndUpdate(pos,net.minecraft.world.level.block.Blocks.AIR.defaultBlockState());
level.removePlayerImmediately(player,net.minecraft.world.entity.Entity.RemovalReason.DISCARDED);
var reasonType=Class.forName("dev.ryanhcode.sable.sublevel.storage.SubLevelRemovalReason");
call(containerType,container,"removeSubLevel",void.class,new Class<?>[]{subType,reasonType},sub,reasonType.getField("REMOVED").get(null));
}
}
static Object call(Class<?> owner,Object target,String name,Class<?> result,Class<?>[] types,Object...args) throws Exception {
var signature=java.lang.invoke.MethodType.methodType(result,types);
var lookup=java.lang.invoke.MethodHandles.publicLookup();
var method=target==null?lookup.findStatic(owner,name,signature):lookup.findVirtual(owner,name,signature);
var values=new java.util.ArrayList<Object>();if(target!=null)values.add(target);java.util.Collections.addAll(values,args);
try{return method.invokeWithArguments(values);}catch(Throwable failure){throw new RuntimeException(failure);}
}
}