mirror of
				https://github.com/SquidDev-CC/CC-Tweaked
				synced 2025-10-31 05:33:00 +00:00 
			
		
		
		
	Move some Forge hooks into a separate class
This commit is contained in:
		| @@ -90,7 +90,6 @@ public final class NetworkHandler | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * /** | ||||
|      * Register packet, and a thread-unsafe handler for it. | ||||
|      * | ||||
|      * @param <T>       The type of the packet to send. | ||||
|   | ||||
| @@ -7,12 +7,18 @@ package dan200.computercraft.ingame.mod; | ||||
| 
 | ||||
| import com.mojang.brigadier.CommandDispatcher; | ||||
| import net.minecraft.command.CommandSource; | ||||
| import net.minecraft.data.NBTToSNBTConverter; | ||||
| import net.minecraft.server.MinecraftServer; | ||||
| import net.minecraft.test.TestFunctionInfo; | ||||
| import net.minecraft.test.TestRegistry; | ||||
| import net.minecraft.test.*; | ||||
| import net.minecraft.util.ResourceLocation; | ||||
| import net.minecraft.util.text.StringTextComponent; | ||||
| import net.minecraft.util.text.TextFormatting; | ||||
| 
 | ||||
| import javax.annotation.Nonnull; | ||||
| import java.io.IOException; | ||||
| import java.io.UncheckedIOException; | ||||
| import java.nio.file.Path; | ||||
| import java.nio.file.Paths; | ||||
| 
 | ||||
| import static dan200.computercraft.shared.command.builder.HelpingArgumentBuilder.choice; | ||||
| import static net.minecraft.command.Commands.literal; | ||||
| @@ -32,14 +38,24 @@ class CCTestCommand | ||||
|             .then( literal( "export" ).executes( context -> { | ||||
|                 exportFiles( context.getSource().getServer() ); | ||||
| 
 | ||||
|                 Path path = Paths.get( StructureHelper.testStructuresDir ); | ||||
|                 int total = 0; | ||||
|                 for( TestFunctionInfo function : TestRegistry.getAllTestFunctions() ) | ||||
|                 { | ||||
|                     total += dispatcher.execute( "test import " + function.getTestName(), context.getSource() ); | ||||
|                     total += dispatcher.execute( "test export " + function.getTestName(), context.getSource() ); | ||||
|                     ResourceLocation resourcelocation = new ResourceLocation( "minecraft", function.getStructureName() ); | ||||
|                     Path input = context.getSource().getLevel().getStructureManager().createPathToStructure( resourcelocation, ".nbt" ); | ||||
|                     Path output = NBTToSNBTConverter.convertStructure( input, function.getStructureName(), path ); | ||||
|                     if( output != null ) total++; | ||||
|                 } | ||||
|                 return total; | ||||
|             } ) ) | ||||
|             .then( literal( "runall" ).executes( context -> { | ||||
|                 TestRegistry.forgetFailedTests(); | ||||
|                 TestResultList result = TestHooks.runTests(); | ||||
|                 result.addListener( new Callback( context.getSource(), result ) ); | ||||
|                 result.addFailureListener( x -> TestRegistry.rememberFailedTest( x.getTestFunction() ) ); | ||||
|                 return 0; | ||||
|             } ) ) | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
| @@ -66,4 +82,29 @@ class CCTestCommand | ||||
|             throw new UncheckedIOException( e ); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private static class Callback implements ITestCallback | ||||
|     { | ||||
|         private final CommandSource source; | ||||
|         private final TestResultList result; | ||||
| 
 | ||||
|         public Callback( CommandSource source, TestResultList result ) | ||||
|         { | ||||
|             this.source = source; | ||||
|             this.result = result; | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public void testStructureLoaded( @Nonnull TestTracker tracker ) | ||||
|         { | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public void testFailed( @Nonnull TestTracker tracker ) | ||||
|         { | ||||
|             if( !tracker.isDone() ) return; | ||||
| 
 | ||||
|             source.sendFailure( new StringTextComponent( result.getFailedRequiredCount() + " required tests failed" ).withStyle( TextFormatting.RED ) ); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
							
								
								
									
										139
									
								
								src/testMod/java/dan200/computercraft/ingame/mod/TestHooks.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										139
									
								
								src/testMod/java/dan200/computercraft/ingame/mod/TestHooks.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,139 @@ | ||||
| package dan200.computercraft.ingame.mod; | ||||
| 
 | ||||
| import net.minecraft.client.Minecraft; | ||||
| import net.minecraft.command.CommandSource; | ||||
| import net.minecraft.server.MinecraftServer; | ||||
| import net.minecraft.test.*; | ||||
| import net.minecraft.util.Rotation; | ||||
| import net.minecraft.util.math.BlockPos; | ||||
| import net.minecraft.world.GameRules; | ||||
| import net.minecraft.world.World; | ||||
| import net.minecraft.world.gen.Heightmap; | ||||
| import net.minecraft.world.server.ServerWorld; | ||||
| import net.minecraftforge.event.RegisterCommandsEvent; | ||||
| import net.minecraftforge.event.TickEvent; | ||||
| import net.minecraftforge.eventbus.api.SubscribeEvent; | ||||
| import net.minecraftforge.fml.common.Mod; | ||||
| import net.minecraftforge.fml.event.server.FMLServerStartedEvent; | ||||
| import net.minecraftforge.fml.loading.FMLLoader; | ||||
| import net.minecraftforge.fml.server.ServerLifecycleHooks; | ||||
| import org.apache.logging.log4j.LogManager; | ||||
| import org.apache.logging.log4j.Logger; | ||||
| 
 | ||||
| import java.util.Collection; | ||||
| import java.util.stream.Collectors; | ||||
| 
 | ||||
| @Mod.EventBusSubscriber( modid = TestMod.MOD_ID ) | ||||
| public class TestHooks | ||||
| { | ||||
|     private static final Logger log = LogManager.getLogger( TestHooks.class ); | ||||
| 
 | ||||
|     private static TestResultList runningTests = null; | ||||
|     private static int countdown = 20; | ||||
| 
 | ||||
|     @SubscribeEvent | ||||
|     public static void onRegisterCommands( RegisterCommandsEvent event ) | ||||
|     { | ||||
|         log.info( "Starting server, registering command helpers." ); | ||||
|         TestCommand.register( event.getDispatcher() ); | ||||
|         CCTestCommand.register( event.getDispatcher() ); | ||||
|     } | ||||
| 
 | ||||
|     @SubscribeEvent | ||||
|     public static void onServerStarted( FMLServerStartedEvent event ) | ||||
|     { | ||||
|         MinecraftServer server = event.getServer(); | ||||
|         GameRules rules = server.getGameRules(); | ||||
|         rules.getRule( GameRules.RULE_DAYLIGHT ).set( false, server ); | ||||
|         rules.getRule( GameRules.RULE_WEATHER_CYCLE ).set( false, server ); | ||||
|         rules.getRule( GameRules.RULE_DOMOBSPAWNING ).set( false, server ); | ||||
| 
 | ||||
|         ServerWorld world = event.getServer().getLevel( World.OVERWORLD ); | ||||
|         if( world != null ) world.setDayTime( 6000 ); | ||||
| 
 | ||||
|         log.info( "Cleaning up after last run" ); | ||||
|         CommandSource source = server.createCommandSourceStack(); | ||||
|         TestUtils.clearAllTests( source.getLevel(), getStart( source ), TestCollection.singleton, 200 ); | ||||
| 
 | ||||
|         log.info( "Importing files" ); | ||||
|         CCTestCommand.importFiles( server ); | ||||
|     } | ||||
| 
 | ||||
|     @SubscribeEvent | ||||
|     public static void onServerTick( TickEvent.ServerTickEvent event ) | ||||
|     { | ||||
|         if( event.phase != TickEvent.Phase.START ) return; | ||||
| 
 | ||||
|         // Let the world settle a bit before starting tests. | ||||
|         countdown--; | ||||
|         if( countdown == 0 && System.getProperty( "cctest.run", "false" ).equals( "true" ) ) startTests(); | ||||
| 
 | ||||
|         TestCollection.singleton.tick(); | ||||
|         MainThread.INSTANCE.tick(); | ||||
| 
 | ||||
|         if( runningTests != null && runningTests.isDone() ) finishTests(); | ||||
|     } | ||||
| 
 | ||||
|     public static TestResultList runTests() | ||||
|     { | ||||
|         MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); | ||||
|         CommandSource source = server.createCommandSourceStack(); | ||||
|         Collection<TestFunctionInfo> tests = TestRegistry.getAllTestFunctions() | ||||
|             .stream() | ||||
|             .filter( x -> FMLLoader.getDist().isClient() | !x.batchName.startsWith( "client" ) ) | ||||
|             .collect( Collectors.toList() ); | ||||
| 
 | ||||
|         log.info( "Running {} tests...", tests.size() ); | ||||
| 
 | ||||
|         Collection<TestBatch> batches = TestUtils.groupTestsIntoBatches( tests ); | ||||
|         return new TestResultList( TestUtils.runTestBatches( | ||||
|             batches, getStart( source ), Rotation.NONE, source.getLevel(), TestCollection.singleton, 8 | ||||
|         ) ); | ||||
|     } | ||||
| 
 | ||||
|     private static void startTests() | ||||
|     { | ||||
|         runningTests = runTests(); | ||||
|     } | ||||
| 
 | ||||
|     private static void finishTests() | ||||
|     { | ||||
|         log.info( "Finished tests - {} were run", runningTests.getTotalCount() ); | ||||
|         if( runningTests.hasFailedRequired() ) | ||||
|         { | ||||
|             log.error( "{} required tests failed", runningTests.getFailedRequiredCount() ); | ||||
|         } | ||||
|         if( runningTests.hasFailedOptional() ) | ||||
|         { | ||||
|             log.warn( "{} optional tests failed", runningTests.getFailedOptionalCount() ); | ||||
|         } | ||||
| 
 | ||||
|         if( ServerLifecycleHooks.getCurrentServer().isDedicatedServer() ) | ||||
|         { | ||||
|             log.info( "Stopping server." ); | ||||
| 
 | ||||
|             // We can't exit in the main thread, as Minecraft registers a shutdown hook which results | ||||
|             // in a deadlock. So we do this weird janky thing! | ||||
|             Thread thread = new Thread( () -> System.exit( runningTests.hasFailedRequired() ? 1 : 0 ) ); | ||||
|             thread.setDaemon( true ); | ||||
|             thread.start(); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             shutdownClient(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private static BlockPos getStart( CommandSource source ) | ||||
|     { | ||||
|         BlockPos pos = new BlockPos( source.getPosition() ); | ||||
|         return new BlockPos( pos.getX(), source.getLevel().getHeightmapPos( Heightmap.Type.WORLD_SURFACE, pos ).getY(), pos.getZ() + 3 ); | ||||
|     } | ||||
| 
 | ||||
|     private static void shutdownClient() | ||||
|     { | ||||
|         Minecraft.getInstance().clearLevel(); | ||||
|         Minecraft.getInstance().stop(); | ||||
|         if( runningTests.hasFailedOptional() ) System.exit( 1 ); | ||||
|     } | ||||
| } | ||||
| @@ -6,38 +6,23 @@ | ||||
| package dan200.computercraft.ingame.mod; | ||||
| 
 | ||||
| import dan200.computercraft.api.ComputerCraftAPI; | ||||
| import net.minecraft.command.CommandSource; | ||||
| import net.minecraft.server.MinecraftServer; | ||||
| import net.minecraft.test.*; | ||||
| import net.minecraft.util.Rotation; | ||||
| import net.minecraft.util.math.BlockPos; | ||||
| import net.minecraft.world.GameRules; | ||||
| import net.minecraft.world.gen.Heightmap; | ||||
| import net.minecraftforge.common.MinecraftForge; | ||||
| import net.minecraftforge.event.RegisterCommandsEvent; | ||||
| import net.minecraftforge.event.TickEvent; | ||||
| import net.minecraft.test.StructureHelper; | ||||
| import net.minecraftforge.fml.common.Mod; | ||||
| import net.minecraftforge.fml.event.server.FMLServerStartedEvent; | ||||
| import net.minecraftforge.fml.server.ServerLifecycleHooks; | ||||
| import org.apache.logging.log4j.LogManager; | ||||
| import org.apache.logging.log4j.Logger; | ||||
| 
 | ||||
| import java.nio.file.Path; | ||||
| import java.nio.file.Paths; | ||||
| import java.util.Collection; | ||||
| 
 | ||||
| @Mod( TestMod.MOD_ID ) | ||||
| public class TestMod | ||||
| { | ||||
|     public static final Path sourceDir = Paths.get( "../../src/testMod/server-files/" ).toAbsolutePath(); | ||||
|     public static final Path sourceDir = Paths.get( "../../src/testMod/server-files" ).normalize().toAbsolutePath(); | ||||
| 
 | ||||
|     public static final String MOD_ID = "cctest"; | ||||
| 
 | ||||
|     public static final Logger log = LogManager.getLogger( MOD_ID ); | ||||
| 
 | ||||
|     private TestResultList runningTests = null; | ||||
|     private int countdown = 20; | ||||
| 
 | ||||
|     public TestMod() | ||||
|     { | ||||
|         log.info( "CC: Test initialised" ); | ||||
| @@ -45,81 +30,5 @@ public class TestMod | ||||
|         TestLoader.setup(); | ||||
| 
 | ||||
|         StructureHelper.testStructuresDir = sourceDir.resolve( "structures" ).toString(); | ||||
| 
 | ||||
|         MinecraftForge.EVENT_BUS.addListener( ( RegisterCommandsEvent event ) -> { | ||||
|             log.info( "Starting server, registering command helpers." ); | ||||
|             TestCommand.register( event.getDispatcher() ); | ||||
|             CCTestCommand.register( event.getDispatcher() ); | ||||
|         } ); | ||||
| 
 | ||||
|         MinecraftForge.EVENT_BUS.addListener( ( FMLServerStartedEvent event ) -> { | ||||
|             MinecraftServer server = event.getServer(); | ||||
|             GameRules rules = server.getGameRules(); | ||||
|             rules.getRule( GameRules.RULE_DAYLIGHT ).set( false, server ); | ||||
|             rules.getRule( GameRules.RULE_WEATHER_CYCLE ).set( false, server ); | ||||
|             rules.getRule( GameRules.RULE_DOMOBSPAWNING ).set( false, server ); | ||||
| 
 | ||||
|             log.info( "Cleaning up after last run" ); | ||||
|             CommandSource source = server.createCommandSourceStack(); | ||||
|             TestUtils.clearAllTests( source.getLevel(), getStart( source ), TestCollection.singleton, 200 ); | ||||
| 
 | ||||
|             log.info( "Importing files" ); | ||||
|             CCTestCommand.importFiles( server ); | ||||
|         } ); | ||||
| 
 | ||||
|         MinecraftForge.EVENT_BUS.addListener( ( TickEvent.ServerTickEvent event ) -> { | ||||
|             if( event.phase != TickEvent.Phase.START ) return; | ||||
| 
 | ||||
|             // Let the world settle a bit before starting tests. | ||||
|             countdown--; | ||||
|             if( countdown == 0 && System.getProperty( "cctest.run", "false" ).equals( "true" ) ) startTests(); | ||||
| 
 | ||||
|             TestCollection.singleton.tick(); | ||||
|             MainThread.INSTANCE.tick(); | ||||
| 
 | ||||
|             if( runningTests != null && runningTests.isDone() ) finishTests(); | ||||
|         } ); | ||||
|     } | ||||
| 
 | ||||
|     private void startTests() | ||||
|     { | ||||
|         MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); | ||||
|         CommandSource source = server.createCommandSourceStack(); | ||||
|         Collection<TestFunctionInfo> tests = TestRegistry.getAllTestFunctions(); | ||||
| 
 | ||||
|         log.info( "Running {} tests...", tests.size() ); | ||||
|         runningTests = new TestResultList( TestUtils.runTests( | ||||
|             tests, getStart( source ), Rotation.NONE, source.getLevel(), TestCollection.singleton, 8 | ||||
|         ) ); | ||||
|     } | ||||
| 
 | ||||
|     private void finishTests() | ||||
|     { | ||||
|         log.info( "Finished tests - {} were run", runningTests.getTotalCount() ); | ||||
|         if( runningTests.hasFailedRequired() ) | ||||
|         { | ||||
|             log.error( "{} required tests failed", runningTests.getFailedRequiredCount() ); | ||||
|         } | ||||
|         if( runningTests.hasFailedOptional() ) | ||||
|         { | ||||
|             log.warn( "{} optional tests failed", runningTests.getFailedOptionalCount() ); | ||||
|         } | ||||
| 
 | ||||
|         if( ServerLifecycleHooks.getCurrentServer().isDedicatedServer() ) | ||||
|         { | ||||
|             log.info( "Stopping server." ); | ||||
| 
 | ||||
|             // We can't exit in the main thread, as Minecraft registers a shutdown hook which results | ||||
|             // in a deadlock. So we do this weird janky thing! | ||||
|             Thread thread = new Thread( () -> System.exit( runningTests.hasFailedRequired() ? 1 : 0 ) ); | ||||
|             thread.setDaemon( true ); | ||||
|             thread.start(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private BlockPos getStart( CommandSource source ) | ||||
|     { | ||||
|         BlockPos pos = new BlockPos( source.getPosition() ); | ||||
|         return new BlockPos( pos.getX(), source.getLevel().getHeightmapPos( Heightmap.Type.WORLD_SURFACE, pos ).getY(), pos.getZ() + 3 ); | ||||
|     } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Jonathan Coates
					Jonathan Coates