Polished TrafficLightRace
This commit is contained in:
		| @@ -52,12 +52,13 @@ public abstract class Game extends MineNetInstance implements Spawnable { | ||||
|         try { | ||||
|  | ||||
|             Game game = factory.manufacture(options); | ||||
|             Room.getRoom(owner).orElseThrow().moveMembersToGame(game); | ||||
|             game.load(); | ||||
|             Room.getRoom(owner).orElseThrow().moveMembersToGame(game); | ||||
|  | ||||
|         } catch (Exception e) { | ||||
|             new ChatMessage(Icon.ERROR).appendStatic("Instance crashed:" + e.getMessage()).send(owner); | ||||
|             e.printStackTrace(); | ||||
|             new ChatMessage(Icon.ERROR).appendStatic("Instance crashed: " + e.getMessage()).send(owner); | ||||
|             MinecraftServer.getSchedulerManager().scheduleNextTick(() -> Room.getRoom(owner).orElseThrow().moveMembersToRoomLobby()); | ||||
|             e.printStackTrace(System.err); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -4,6 +4,7 @@ import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame; | ||||
| import eu.mhsl.minenet.minigames.message.type.ActionBarMessage; | ||||
| import eu.mhsl.minenet.minigames.score.FirstWinsScore; | ||||
| import eu.mhsl.minenet.minigames.util.BatchUtil; | ||||
| import eu.mhsl.minenet.minigames.util.CommonProperties; | ||||
| import eu.mhsl.minenet.minigames.util.Intersect; | ||||
| import eu.mhsl.minenet.minigames.instance.Dimension; | ||||
| import eu.mhsl.minenet.minigames.world.generator.BlockPallet; | ||||
| @@ -25,9 +26,9 @@ import java.util.concurrent.CompletableFuture; | ||||
|  | ||||
| class Minerun extends StatelessGame { | ||||
|  | ||||
|     private int minePercentage; | ||||
|     private int width; | ||||
|     private int length; | ||||
|     private final int minePercentage; | ||||
|     private final int width; | ||||
|     private final int length; | ||||
|  | ||||
|     private final int preRun = 5; | ||||
|     private final int afterMines = 2; | ||||
| @@ -35,7 +36,7 @@ class Minerun extends StatelessGame { | ||||
|  | ||||
|     public Minerun(int width, int length, int minePercentage) { | ||||
|         super(Dimension.THE_END.DIMENSION, "Minerun", new FirstWinsScore()); | ||||
|         setGenerator(new SquareTerrainGenerator(width, length + preRun + afterFinishLine, true)); | ||||
|         setGenerator(new SquareTerrainGenerator(width, length + preRun + afterFinishLine).withPlate(50)); | ||||
|  | ||||
|         this.width = width; | ||||
|         this.length = length; | ||||
| @@ -58,17 +59,10 @@ class Minerun extends StatelessGame { | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         Map<String, String> properties = new HashMap<>() { | ||||
|             { | ||||
|                 put("west", "true"); | ||||
|                 put("east", "true"); | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         for(int x = 0; x <= width; x++) { | ||||
|             batch.setBlock(x, 49, spawnToFinishLine, Block.GOLD_BLOCK); | ||||
|             batch.setBlock(x, 49, preRun, Block.GOLD_BLOCK); | ||||
|             batch.setBlock(x, 50, preRun, Block.OAK_FENCE.withProperties(properties)); | ||||
|             batch.setBlock(x, 50, preRun, Block.OAK_FENCE.withProperties(CommonProperties.fenceEastWest)); | ||||
|         } | ||||
|         BatchUtil.loadAndApplyBatch(batch, this, () -> callback.complete(null)); | ||||
|     } | ||||
| @@ -116,6 +110,6 @@ class Minerun extends StatelessGame { | ||||
|  | ||||
|     @Override | ||||
|     public Pos getSpawn() { | ||||
|         return new Pos(width/2, 50, 3); | ||||
|         return new Pos((double) width /2, 50, 3); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -8,8 +8,8 @@ import java.util.Random; | ||||
|  | ||||
| enum LightPhase { | ||||
|     RED(Material.RED_WOOL, 1000, 5000), | ||||
|     YELLOW(Material.YELLOW_WOOL, 1000, 2000), | ||||
|     GREEN(Material.GREEN_WOOL, 1000, 5000); | ||||
|     YELLOW(Material.YELLOW_WOOL, 500, 1500), | ||||
|     GREEN(Material.GREEN_WOOL, 2000, 5000); | ||||
|  | ||||
|     public final ItemStack item; | ||||
|     private final int minDuration; | ||||
|   | ||||
| @@ -1,51 +1,141 @@ | ||||
| package eu.mhsl.minenet.minigames.instance.game.stateless.types.trafficlightrace; | ||||
|  | ||||
| import de.articdive.jnoise.JNoise; | ||||
| import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame; | ||||
| import eu.mhsl.minenet.minigames.score.FirstWinsScore; | ||||
| import eu.mhsl.minenet.minigames.util.BatchUtil; | ||||
| import eu.mhsl.minenet.minigames.instance.Dimension; | ||||
| import eu.mhsl.minenet.minigames.util.CommonProperties; | ||||
| import eu.mhsl.minenet.minigames.world.generator.BlockPallet; | ||||
| import eu.mhsl.minenet.minigames.world.generator.terrain.SquareTerrainGenerator; | ||||
| import net.kyori.adventure.sound.Sound; | ||||
| import net.minestom.server.coordinate.Pos; | ||||
| import net.minestom.server.coordinate.Vec; | ||||
| import net.minestom.server.entity.GameMode; | ||||
| import net.minestom.server.event.player.PlayerMoveEvent; | ||||
| import net.minestom.server.instance.batch.AbsoluteBlockBatch; | ||||
| import net.minestom.server.instance.block.Block; | ||||
| import net.minestom.server.sound.SoundEvent; | ||||
| import net.minestom.server.timer.ExecutionType; | ||||
| import net.minestom.server.timer.TaskSchedule; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| import java.util.concurrent.CompletableFuture; | ||||
| import java.util.function.Consumer; | ||||
|  | ||||
| class TrafficLightRace extends StatelessGame { | ||||
|     private LightPhase phase = LightPhase.RED; | ||||
|     private int phaseCounter = 1; | ||||
|     private int phaseCounter = 0; | ||||
|  | ||||
|     public TrafficLightRace() { | ||||
|     private final int width; | ||||
|     private final int length; | ||||
|     private final int preRun = 10; | ||||
|     private final int afterRun = 10; | ||||
|  | ||||
|     private final List<Pos> trafficLights = new ArrayList<>(); | ||||
|  | ||||
|     public TrafficLightRace(int width, int length) { | ||||
|         super(Dimension.THE_END.DIMENSION, "Ampelrennen", new FirstWinsScore()); | ||||
|         this.width = width; | ||||
|         this.length = length; | ||||
|  | ||||
|         setGenerator( | ||||
|                 new SquareTerrainGenerator(width, length + preRun + afterRun) | ||||
|                         .withPlate(50) | ||||
|                         .withBorders() | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected void onLoad(@NotNull CompletableFuture<Void> callback) { | ||||
|         final JNoise slowBatches = JNoise.newBuilder() | ||||
|                 .fastSimplex() | ||||
|                 .setSeed(rnd.nextLong()) | ||||
|                 .setFrequency(0.1) | ||||
|                 .build(); | ||||
|  | ||||
|         AbsoluteBlockBatch batch = new AbsoluteBlockBatch(); | ||||
|         for (int x = -10; x <= 10; x++) { | ||||
|             for (int z = 0; z <= 100; z++) { | ||||
|                 batch.setBlock(x, 5, z, super.rnd.nextInt(0, 100) > 90 ? Block.SOUL_SAND : Block.BLACK_CONCRETE_POWDER); | ||||
|  | ||||
|         for (int x = 0; x <= width; x++) { | ||||
|             for (int z = 0; z <= preRun; z++) { | ||||
|                 batch.setBlock(x, 50, z, BlockPallet.GROUND.rnd()); | ||||
|             } | ||||
|  | ||||
|             for (int z = preRun; z <= length + preRun; z++) { | ||||
|                 batch.setBlock(x, 50, z, slowBatches.getNoise(x, z) > 0.6 ? Block.SOUL_SAND : BlockPallet.STREET.rnd()); | ||||
|             } | ||||
|  | ||||
|             for (int z = preRun + length; z <= preRun + length + afterRun; z++) { | ||||
|                 batch.setBlock(x, 50, z, BlockPallet.GROUND.rnd()); | ||||
|             } | ||||
|  | ||||
|             batch.setBlock(x, 51, preRun-1, Block.OAK_FENCE.withProperties(CommonProperties.fenceEastWest)); | ||||
|             batch.setBlock(x, 50, preRun + length, Block.GOLD_BLOCK); | ||||
|         } | ||||
|  | ||||
|         record TrafficLightsInput(int x, int z) {} | ||||
|  | ||||
|         Consumer<TrafficLightsInput> generateTrafficLight = (input) -> { | ||||
|             batch.setBlock(input.x, 51, input.z, Block.ANVIL); | ||||
|  | ||||
|             for(int y = 52; y <= 59; y++) { | ||||
|                 batch.setBlock(input.x, y, input.z, Block.ANDESITE_WALL); | ||||
|             } | ||||
|  | ||||
|             for (int x = input.x-3; x <= input.x+3; x++) { | ||||
|                 batch.setBlock(x, 60, input.z, Block.SMOOTH_STONE_SLAB); | ||||
|             } | ||||
|  | ||||
|             batch.setBlock(input.x-2, 59, input.z, Block.STONE_BRICK_WALL); | ||||
|             trafficLights.add(new Pos(input.x-2, 58, input.z)); | ||||
|             trafficLights.add(new Pos(input.x-2, 57, input.z)); | ||||
|  | ||||
|             batch.setBlock(input.x+2, 59, input.z, Block.STONE_BRICK_WALL); | ||||
|             trafficLights.add(new Pos(input.x+2, 58, input.z)); | ||||
|             trafficLights.add(new Pos(input.x+2, 57, input.z)); | ||||
|  | ||||
|             for (Pos trafficLight : trafficLights) { | ||||
|                 batch.setBlock(trafficLight, Block.WHITE_WOOL); | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         for (int count = 0; count <= this.rnd.nextInt(1, 2); count++) { | ||||
|             generateTrafficLight.accept(new TrafficLightsInput(0, this.rnd.nextInt(preRun + 10, length + preRun - 10))); | ||||
|             generateTrafficLight.accept(new TrafficLightsInput(width, this.rnd.nextInt(preRun + 10, length + preRun - 10))); | ||||
|         } | ||||
|  | ||||
|         if(width > 30) { | ||||
|             for (int count = 0; count <= this.rnd.nextInt(1, 2); count++) { | ||||
|                 generateTrafficLight.accept(new TrafficLightsInput(width/2, this.rnd.nextInt(preRun, length + preRun))); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         generateTrafficLight.accept(new TrafficLightsInput(0, length + preRun)); | ||||
|         generateTrafficLight.accept(new TrafficLightsInput(width, length + preRun)); | ||||
|  | ||||
|         BatchUtil.loadAndApplyBatch(batch, this, () -> callback.complete(null)); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected void onStart() { | ||||
|         AbsoluteBlockBatch batch = new AbsoluteBlockBatch(); | ||||
|         for(int x = 0; x <= width; x++) { | ||||
|             batch.setBlock(x, 51, preRun-1, Block.AIR); | ||||
|         } | ||||
|  | ||||
|         BatchUtil.loadAndApplyBatch(batch, this, () -> playSound(Sound.sound(SoundEvent.BLOCK_WOOD_BREAK, Sound.Source.BLOCK, 1f, 1f))); | ||||
|  | ||||
|         scheduler().submitTask(() -> { | ||||
|             if(!super.isRunning) return TaskSchedule.stop(); | ||||
|  | ||||
|             phaseCounter++; | ||||
|             if(phaseCounter >= 4) phaseCounter = 0; | ||||
|             if(phaseCounter >= 3) phaseCounter = 0; | ||||
|  | ||||
|             if(phaseCounter == 0) phase = LightPhase.RED; | ||||
|             if(phaseCounter == 1 || phaseCounter == 3) phase = LightPhase.YELLOW; | ||||
|             if(phaseCounter == 2) phase = LightPhase.GREEN; | ||||
|             if(phaseCounter == 1) phase = LightPhase.GREEN; | ||||
|             if(phaseCounter == 2) phase = LightPhase.YELLOW; | ||||
|  | ||||
|             getPlayers().forEach(player -> { | ||||
|                 for(int i = 0; i < 9; i++) { | ||||
| @@ -53,23 +143,34 @@ class TrafficLightRace extends StatelessGame { | ||||
|                 } | ||||
|             }); | ||||
|  | ||||
|             AbsoluteBlockBatch changeLightsBatch = new AbsoluteBlockBatch(); | ||||
|             for (Pos trafficLight : trafficLights) { | ||||
|                 changeLightsBatch.setBlock(trafficLight, phase.item.material().block()); | ||||
|             } | ||||
|             BatchUtil.loadAndApplyBatch(changeLightsBatch, this, () -> {}); | ||||
|  | ||||
|             return phase.taskScheduleRandomDuration(); | ||||
|         }, ExecutionType.SYNC); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected void onPlayerMove(@NotNull PlayerMoveEvent playerMoveEvent) { | ||||
|         super.onPlayerMove(playerMoveEvent); | ||||
|         if(isBeforeBeginning) return; | ||||
|  | ||||
|         if(playerMoveEvent.getNewPosition().z() > 110) stop(); | ||||
|         if(phase.equals(LightPhase.RED) && playerMoveEvent.getNewPosition().z()-0.01 > playerMoveEvent.getPlayer().getPosition().z()) { | ||||
|             playerMoveEvent.getPlayer().setVelocity(new Vec(0, 8, -15)); | ||||
|             playerMoveEvent.getPlayer().playSound(Sound.sound(SoundEvent.ENTITY_BLAZE_SHOOT, Sound.Source.PLAYER, 1f, 1f)); | ||||
|         } | ||||
|  | ||||
|         if(phase.equals(LightPhase.RED) && playerMoveEvent.getNewPosition().z() > playerMoveEvent.getPlayer().getPosition().z()) { | ||||
|             playerMoveEvent.getPlayer().setVelocity(new Vec(0, 5, -10)); | ||||
|         if(playerMoveEvent.getNewPosition().z() > preRun+length) { | ||||
|             getScore().insertResult(playerMoveEvent.getPlayer()); | ||||
|             playerMoveEvent.getPlayer().getInventory().clear(); | ||||
|             playerMoveEvent.getPlayer().setGameMode(GameMode.SPECTATOR); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Pos getSpawn() { | ||||
|         return new Pos(0, 6, 10); | ||||
|         return new Pos((double) width/2, 51, 3); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -4,6 +4,7 @@ import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame; | ||||
| import eu.mhsl.minenet.minigames.instance.game.stateless.config.GameFactory; | ||||
| import eu.mhsl.minenet.minigames.instance.game.stateless.config.ConfigManager; | ||||
| import eu.mhsl.minenet.minigames.instance.game.stateless.config.Option; | ||||
| import eu.mhsl.minenet.minigames.instance.game.stateless.config.common.NumericOption; | ||||
| import eu.mhsl.minenet.minigames.message.component.TranslatedComponent; | ||||
| import net.minestom.server.item.Material; | ||||
|  | ||||
| @@ -17,12 +18,14 @@ public class TrafficLightRaceFactory implements GameFactory { | ||||
|  | ||||
|     @Override | ||||
|     public ConfigManager configuration() { | ||||
|         return null; | ||||
|         return new ConfigManager() | ||||
|                 .addOption(new NumericOption("width", Material.OAK_FENCE, TranslatedComponent.byId("game_TrafficlightRace#width"), 20, 30, 40)) | ||||
|                 .addOption(new NumericOption("length", Material.BLACK_CONCRETE_POWDER, TranslatedComponent.byId("game_TrafficlightRace#length"), 50, 80, 100, 120, 150)); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public StatelessGame manufacture(Map<String, Option<?>> configuration) { | ||||
|         return new TrafficLightRace(); | ||||
|         return new TrafficLightRace(configuration.get("width").getAsInt(), configuration.get("length").getAsInt()); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|   | ||||
| @@ -123,6 +123,10 @@ public class Room extends MineNetInstance implements Spawnable { | ||||
|         this.getAllMembers().forEach(player -> MoveInstance.move(player, game)); | ||||
|     } | ||||
|  | ||||
|     public void moveMembersToRoomLobby() { | ||||
|         this.getAllMembers().forEach(player -> MoveInstance.move(player, this)); | ||||
|     } | ||||
|  | ||||
|     public Set<Player> getAllMembers() { | ||||
|         return rooms.keySet().stream() | ||||
|                 .filter(player -> getRoom(player).orElse(null) == this) | ||||
|   | ||||
| @@ -30,7 +30,7 @@ public class MinigameSelectInventory extends InteractableInventory { | ||||
|             setClickableItem( | ||||
|                     ItemStack.builder(type.getIcon()) | ||||
|                             .displayName(type.getTitle().getAssembled(p)) | ||||
|                             .lore(type.getDescription().getAssembled(p)) | ||||
|                             .lore(type.getDescription().addWrap().getWrappedAssembled(p)) | ||||
|                             .build(), | ||||
|                     itemAlignment.next().get(), | ||||
|                     itemClick -> drawGames(type) | ||||
| @@ -59,7 +59,7 @@ public class MinigameSelectInventory extends InteractableInventory { | ||||
|             setClickableItem( | ||||
|                     ItemStack.builder(gameFactory.symbol()) | ||||
|                             .displayName(gameFactory.name().getAssembled(p)) | ||||
|                             .lore(gameFactory.description().getAssembled(p)) | ||||
|                             .lore(gameFactory.description().addWrap().getWrappedAssembled(p)) | ||||
|                             .meta(metaBuilder -> metaBuilder.hideFlag(ItemHideFlag.HIDE_ATTRIBUTES)) | ||||
|                             .build(), | ||||
|                     offset + itemAlignment.next().get(), | ||||
|   | ||||
		Reference in New Issue
	
	Block a user