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();if(target!=null)values.add(target);java.util.Collections.addAll(values,args); try{return method.invokeWithArguments(values);}catch(Throwable failure){throw new RuntimeException(failure);} } }