Initial commit
This commit is contained in:
		| @@ -0,0 +1,41 @@ | ||||
| package eu.mhsl.minenet.minigames.instance; | ||||
|  | ||||
| import net.minestom.server.MinecraftServer; | ||||
| import net.minestom.server.utils.NamespaceID; | ||||
| import net.minestom.server.world.DimensionType; | ||||
|  | ||||
| /** | ||||
|  * Prebuilt dimensions | ||||
|  */ | ||||
| public enum Dimension { | ||||
|     OVERWORLD( | ||||
|             DimensionType | ||||
|                     .builder(NamespaceID.from("minenet:fullbright_overworld")) | ||||
|                     .ambientLight(2.0f) | ||||
|                     .build() | ||||
|     ), | ||||
|  | ||||
|     NETHER( | ||||
|             DimensionType | ||||
|                     .builder(NamespaceID.from("minenet:fullbright_nether")) | ||||
|                     .ambientLight(2.0f) | ||||
|                     .effects("minecraft:the_nether") | ||||
|                     .build() | ||||
|     ), | ||||
|  | ||||
|     THE_END( | ||||
|             DimensionType | ||||
|                     .builder(NamespaceID.from("minenet:fullbright_end")) | ||||
|                     .ambientLight(2.0f) | ||||
|                     .effects("minecraft:the_end") | ||||
|                     .build() | ||||
|     ); | ||||
|  | ||||
|     public final DimensionType DIMENSION; | ||||
|     Dimension(DimensionType dimType) { | ||||
|         this.DIMENSION = dimType; | ||||
|  | ||||
|         MinecraftServer.getDimensionTypeManager().addDimension(this.DIMENSION); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,7 @@ | ||||
| package eu.mhsl.minenet.minigames.instance; | ||||
|  | ||||
| import net.minestom.server.coordinate.Pos; | ||||
|  | ||||
| public interface Spawnable { | ||||
|     Pos getSpawn(); | ||||
| } | ||||
							
								
								
									
										136
									
								
								src/main/java/eu/mhsl/minenet/minigames/instance/game/Game.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										136
									
								
								src/main/java/eu/mhsl/minenet/minigames/instance/game/Game.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,136 @@ | ||||
| package eu.mhsl.minenet.minigames.instance.game; | ||||
|  | ||||
| import eu.mhsl.minenet.minigames.util.CommonEventHandles; | ||||
| import eu.mhsl.minenet.minigames.instance.Spawnable; | ||||
| import eu.mhsl.minenet.minigames.instance.room.Room; | ||||
| import io.github.bloepiloepi.pvp.config.PvPConfig; | ||||
| import net.minestom.server.MinecraftServer; | ||||
| import net.minestom.server.coordinate.Pos; | ||||
| import net.minestom.server.event.EventNode; | ||||
| import net.minestom.server.event.instance.AddEntityToInstanceEvent; | ||||
| import net.minestom.server.event.instance.RemoveEntityFromInstanceEvent; | ||||
| import net.minestom.server.event.item.ItemDropEvent; | ||||
| import net.minestom.server.event.player.PlayerBlockBreakEvent; | ||||
| import net.minestom.server.event.player.PlayerBlockPlaceEvent; | ||||
| import net.minestom.server.event.player.PlayerMoveEvent; | ||||
| import net.minestom.server.event.trait.InstanceEvent; | ||||
| import net.minestom.server.instance.InstanceContainer; | ||||
| import net.minestom.server.timer.ExecutionType; | ||||
| import net.minestom.server.timer.TaskSchedule; | ||||
| import net.minestom.server.world.DimensionType; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
|  | ||||
| import java.util.Random; | ||||
| import java.util.UUID; | ||||
| import java.util.concurrent.CompletableFuture; | ||||
|  | ||||
| public abstract class Game extends InstanceContainer implements Spawnable { | ||||
|  | ||||
|     protected boolean isRunning = false; | ||||
|     protected boolean isBeforeBeginning = true; | ||||
|  | ||||
|     protected final Random rnd = new Random(); //TODO better way than ths? | ||||
|  | ||||
|     public Game(DimensionType dimensionType) { | ||||
|         super(UUID.randomUUID(), dimensionType); | ||||
|  | ||||
|         MinecraftServer.getInstanceManager().registerInstance(this); | ||||
|  | ||||
|         eventNode() | ||||
|                 .addListener(PlayerMoveEvent.class, this::onPlayerMove) | ||||
|                 .addListener(PlayerBlockBreakEvent.class, this::onBlockBreak) | ||||
|                 .addListener(PlayerBlockPlaceEvent.class, this::onBlockPlace) | ||||
|                 .addListener(AddEntityToInstanceEvent.class, this::onJoin) | ||||
|                 .addListener(RemoveEntityFromInstanceEvent.class, this::onLeave) | ||||
|                 .addListener(ItemDropEvent.class, this::onItemDrop); | ||||
|     } | ||||
|  | ||||
|     public void enablePvpConfig(PvPConfig config) { | ||||
|         //eventNode().addChild((EventNode<? extends InstanceEvent>) config.createNode()); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Load and start countdown | ||||
|      */ | ||||
|     public void load() { | ||||
|         scheduler().submitTask(() -> { | ||||
|             CompletableFuture<Void> callback = new CompletableFuture<>(); | ||||
|             this.onLoad(callback); | ||||
|             callback.whenComplete((unused, throwable) -> this.start()); | ||||
|             return TaskSchedule.stop(); | ||||
|         }, ExecutionType.ASYNC); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     protected void start() { | ||||
|         isRunning = true; | ||||
|         isBeforeBeginning = false; | ||||
|         this.onStart(); | ||||
|     } | ||||
|  | ||||
|     public void stop() { | ||||
|         isRunning = false; | ||||
|         this.onStop(); | ||||
|         this.unload(); | ||||
|     } | ||||
|  | ||||
|     public void unload() { | ||||
|         this.onUnload(); | ||||
|  | ||||
|         getPlayers().forEach(Room::setOwnRoom); | ||||
|  | ||||
|         scheduler().scheduleTask(() -> { | ||||
|  | ||||
|             System.out.println("stopping game instance " + this.uniqueId); | ||||
|             getPlayers().forEach(player -> player.kick("timeout")); | ||||
|  | ||||
|             MinecraftServer.getInstanceManager().unregisterInstance(this); | ||||
|  | ||||
|         }, TaskSchedule.seconds(10), TaskSchedule.stop()); | ||||
|     } | ||||
|  | ||||
|     protected void onLoad(CompletableFuture<Void> callback) {} | ||||
|     protected void onStart() {} | ||||
|     protected void onStop() {} | ||||
|     protected void onUnload() {} | ||||
|  | ||||
|  | ||||
|     protected void onPlayerMove(@NotNull PlayerMoveEvent playerMoveEvent) { | ||||
|  | ||||
|     } | ||||
|  | ||||
|     protected void onBlockBreak(@NotNull PlayerBlockBreakEvent playerBlockBreakEvent) { | ||||
|         playerBlockBreakEvent.setCancelled(true); | ||||
|     } | ||||
|  | ||||
|     protected void onBlockPlace(@NotNull PlayerBlockPlaceEvent playerBlockPlaceEvent) { | ||||
|         playerBlockPlaceEvent.setCancelled(true); | ||||
|     } | ||||
|  | ||||
|     protected void onJoin(@NotNull AddEntityToInstanceEvent addEntityToInstanceEvent) { | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Make sure when overriding to call checkAbandoned to insure no garbage instances | ||||
|      * @param removeEntityFromInstanceEvent | ||||
|      */ | ||||
|     protected void onLeave(@NotNull RemoveEntityFromInstanceEvent removeEntityFromInstanceEvent) { | ||||
|         this.checkAbandoned(); | ||||
|     } | ||||
|  | ||||
|     protected void onItemDrop(@NotNull ItemDropEvent itemDropEvent) { | ||||
|         CommonEventHandles.cancel(itemDropEvent); | ||||
|     } | ||||
|  | ||||
|     protected void checkAbandoned() { | ||||
|         scheduleNextTick((instance) -> { | ||||
|             if(instance.getPlayers().size() == 0) this.unload(); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     public Pos getSpawn() { | ||||
|         return new Pos(0,50,0); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,108 @@ | ||||
| package eu.mhsl.minenet.minigames.instance.game.minigame; | ||||
|  | ||||
| import eu.mhsl.minenet.minigames.instance.game.Game; | ||||
| import eu.mhsl.minenet.minigames.message.Countdown; | ||||
| import eu.mhsl.minenet.minigames.message.Icon; | ||||
| import eu.mhsl.minenet.minigames.message.type.ChatMessage; | ||||
| import eu.mhsl.minenet.minigames.message.type.TitleMessage; | ||||
| import eu.mhsl.minenet.minigames.score.Score; | ||||
| import net.kyori.adventure.audience.Audience; | ||||
| import net.kyori.adventure.text.Component; | ||||
| import net.kyori.adventure.text.format.NamedTextColor; | ||||
| import net.minestom.server.event.player.PlayerMoveEvent; | ||||
| import net.minestom.server.timer.ExecutionType; | ||||
| import net.minestom.server.timer.TaskSchedule; | ||||
| import net.minestom.server.world.DimensionType; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
|  | ||||
| import java.time.Duration; | ||||
| import java.util.concurrent.CompletableFuture; | ||||
|  | ||||
| public class Minigame extends Game { | ||||
|     private final String name; | ||||
|     private Score score = new Score(this); | ||||
|  | ||||
|     private int timeLimit = 0; | ||||
|     private int timePlayed = 0; | ||||
|     private boolean preventExit = false; | ||||
|     public Minigame(DimensionType dimensionType, String gameName) { | ||||
|         super(dimensionType); | ||||
|  | ||||
|         this.name = gameName; | ||||
|     } | ||||
|  | ||||
|     public Score getScore() { | ||||
|         return this.score; | ||||
|     } | ||||
|  | ||||
|     public String getName() { | ||||
|         return name; | ||||
|     } | ||||
|  | ||||
|     public void setTimeLimit(int limit) { | ||||
|         this.timeLimit = limit; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void load() { | ||||
|         super.load(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Displays countdown and starts the game | ||||
|      * When overriding make sure to call this::start after countdown! | ||||
|      */ | ||||
|     protected CompletableFuture<Void> countdownStart() { | ||||
|         return new Countdown(TitleMessage.class) | ||||
|                 .countdown(Audience.audience(getPlayers()), 5, countdownModifier -> { | ||||
|                     countdownModifier.message = new TitleMessage(Duration.ofMillis(300), Duration.ofMillis(700)) | ||||
|                             .subtitle(subtitleMessage -> { | ||||
|                                 subtitleMessage.appendStatic(Component.text("in ", NamedTextColor.DARK_GREEN)) | ||||
|                                         .appendStatic(Component.text(countdownModifier.timeLeft, NamedTextColor.GREEN)) | ||||
|                                         .appendStatic(Component.text(" seconds", NamedTextColor.DARK_GREEN)); | ||||
|                             }); | ||||
|                 }); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     @Override | ||||
|     protected void start() { | ||||
|         countdownStart().thenRun(() -> { | ||||
|             super.start(); | ||||
|  | ||||
|             if(timeLimit > 0) { | ||||
|                 scheduler().submitTask(() -> { | ||||
|                     System.out.println("Countdown running..."); | ||||
|                     if(!isRunning || timeLimit == 0) return TaskSchedule.stop(); | ||||
|                     if(timeLimit <= timePlayed) { | ||||
|                         stop(); | ||||
|                         return TaskSchedule.stop(); | ||||
|                     } | ||||
|  | ||||
|                     int timeLeft = timeLimit - timePlayed; | ||||
|                     switch (timeLeft) { | ||||
|                         case 60, 30, 10, 5, 4, 3, 2, 1 -> | ||||
|                                 new ChatMessage(Icon.SCIENCE).appendStatic("Noch " + timeLeft + " Sekunden!").send(getPlayers()); | ||||
|                     } | ||||
|  | ||||
|                     timePlayed++; | ||||
|  | ||||
|                     return TaskSchedule.seconds(1); | ||||
|                 }, ExecutionType.SYNC); | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void stop() { | ||||
|         isRunning = false; | ||||
|         this.onStop(); | ||||
|  | ||||
|         countdownUnload(); | ||||
|     } | ||||
|  | ||||
|     protected void countdownUnload() { | ||||
|         new TitleMessage(Duration.ofSeconds(1)).appendStatic("Finish").send(getPlayers()); | ||||
|         scheduler().scheduleTask(this::unload, TaskSchedule.seconds(5), TaskSchedule.stop()); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,22 @@ | ||||
| package eu.mhsl.minenet.minigames.instance.game.minigame; | ||||
|  | ||||
| import eu.mhsl.minenet.minigames.instance.game.minigame.config.GameFactory; | ||||
| import eu.mhsl.minenet.minigames.instance.game.minigame.types.deathcube.DeathcubeFactory; | ||||
| import eu.mhsl.minenet.minigames.instance.game.minigame.types.minerun.MinerunFactory; | ||||
| import eu.mhsl.minenet.minigames.instance.game.minigame.types.stickfight.StickFightFactory; | ||||
| import eu.mhsl.minenet.minigames.instance.game.minigame.types.trafficlightrace.TrafficLightRaceFactory; | ||||
|  | ||||
| public enum MinigameType { | ||||
|     DEATHCUBE(new DeathcubeFactory()), | ||||
|     STICKFIGHT(new StickFightFactory()), | ||||
|     MINERUN(new MinerunFactory()), | ||||
|     TRAFFICLIGHTRACE(new TrafficLightRaceFactory()); | ||||
|  | ||||
|     private GameFactory factory; | ||||
|     MinigameType(GameFactory factory) { | ||||
|         this.factory = factory; | ||||
|     } | ||||
|     public GameFactory getFactory() { | ||||
|         return this.factory; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,16 @@ | ||||
| package eu.mhsl.minenet.minigames.instance.game.minigame.config; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
|  | ||||
| public class ConfigManager { | ||||
|     private final ArrayList<Option<?>> items = new ArrayList<>(); | ||||
|  | ||||
|     public ConfigManager addOption(Option option) { | ||||
|         items.add(option); | ||||
|         return this; | ||||
|     } | ||||
|  | ||||
|     public ArrayList<Option<?>> getAll() { | ||||
|         return items; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,95 @@ | ||||
| package eu.mhsl.minenet.minigames.instance.game.minigame.config; | ||||
|  | ||||
| import eu.mhsl.minenet.minigames.instance.game.Game; | ||||
| import eu.mhsl.minenet.minigames.shared.inventory.InteractableInventory; | ||||
| import eu.mhsl.minenet.minigames.util.TextUtil; | ||||
| import eu.mhsl.minenet.minigames.instance.room.Room; | ||||
| import net.kyori.adventure.text.Component; | ||||
| import net.kyori.adventure.text.format.NamedTextColor; | ||||
| import net.minestom.server.entity.Player; | ||||
| import net.minestom.server.inventory.InventoryType; | ||||
| import net.minestom.server.inventory.click.ClickType; | ||||
| import net.minestom.server.inventory.condition.InventoryConditionResult; | ||||
| import net.minestom.server.item.ItemStack; | ||||
| import net.minestom.server.item.Material; | ||||
|  | ||||
| import java.util.HashMap; | ||||
| import java.util.Map; | ||||
|  | ||||
| public class GameConfigurationInventory extends InteractableInventory { | ||||
|     private final Map<Integer, Option<?>> map = new HashMap<>(); | ||||
|  | ||||
|     public GameConfigurationInventory(GameFactory factory) { | ||||
|         super(InventoryType.CHEST_5_ROW, factory.name()); | ||||
|         ConfigManager config = factory.configuration(); | ||||
|  | ||||
|         setClickableItem( | ||||
|                 ItemStack.builder(Material.RED_WOOL).displayName(Component.text("Abbrechen", NamedTextColor.RED)).build(), | ||||
|                 0, | ||||
|                 itemClick -> itemClick.getPlayer().closeInventory(), | ||||
|                 true | ||||
|         ); | ||||
|  | ||||
|         setDummyItem(Material.BLACK_STAINED_GLASS_PANE,1); | ||||
|  | ||||
|         setDummyItem( | ||||
|                 ItemStack.builder(Material.NAME_TAG).displayName(factory.name()).build(), | ||||
|                 4 | ||||
|         ); | ||||
|  | ||||
|         setDummyItem(Material.BLACK_STAINED_GLASS_PANE,7); | ||||
|  | ||||
|         setClickableItem( | ||||
|                 ItemStack.builder(Material.GREEN_WOOL).displayName(Component.text("Start", NamedTextColor.GREEN)).build(), | ||||
|                 8, | ||||
|                 itemClick -> { | ||||
|                     try { | ||||
|                         Game game = factory.manufacture(config != null ? config.getAll() : null); | ||||
|                         Room.getRoom(itemClick.getPlayer()).moveMembersToGame(game); | ||||
|                         game.load(); | ||||
|                     } catch (Exception e) { | ||||
|                         e.printStackTrace(); | ||||
|                     } | ||||
|                 }, | ||||
|                 true | ||||
|         ); | ||||
|  | ||||
|         for(int i = 9; i <= 17; i++) { | ||||
|             setDummyItem(Material.BLACK_STAINED_GLASS_PANE, i); | ||||
|         } | ||||
|  | ||||
|         if(config == null) { | ||||
|             setDummyItem( | ||||
|                     ItemStack.builder(Material.BARRIER).displayName(Component.text("Keine Optionen")).lore(TextUtil.autoWrap("Für dieses Spiel sind keine Einstellungen verfügbar!")).build(), | ||||
|                     31 | ||||
|             ); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         int pos = 18; | ||||
|         for(Option<?> item : config.getAll()) { | ||||
|             map.put(pos, item); | ||||
|  | ||||
|             setDummyItem( | ||||
|                     item.getCurrent(), | ||||
|                     pos++ | ||||
|             ); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected void onClick(Player player, int slot, ClickType clickType, InventoryConditionResult inventoryConditionResult) { | ||||
|         inventoryConditionResult.setCancel(true); | ||||
|  | ||||
|         if(!map.containsKey(slot)) return; | ||||
|  | ||||
|         Option item = map.get(slot); | ||||
|         setDummyItem( | ||||
|                 item.getNext(), | ||||
|                 slot | ||||
|         ); | ||||
|  | ||||
|         update(); | ||||
|  | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,34 @@ | ||||
| package eu.mhsl.minenet.minigames.instance.game.minigame.config; | ||||
|  | ||||
| import eu.mhsl.minenet.minigames.instance.game.minigame.Minigame; | ||||
| import net.kyori.adventure.text.Component; | ||||
| import net.minestom.server.instance.block.Block; | ||||
| import net.minestom.server.item.Material; | ||||
|  | ||||
| import java.util.HashMap; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
|  | ||||
| public interface GameFactory { | ||||
|     Component name(); | ||||
|     ConfigManager configuration(); | ||||
|  | ||||
|     default Material symbol() { | ||||
|         return Material.GRASS_BLOCK; | ||||
|     }; | ||||
|     default Component description() { | ||||
|         return Component.text("- Keine Beschreibung -"); | ||||
|     }; | ||||
|  | ||||
|     Minigame manufacture(Map<String, Option<?>> configuration); | ||||
|     default Minigame manufacture(List<Option<?>> configuration) { | ||||
|         if(configuration == null) return manufacture(); | ||||
|         Map<String, Option<?>> cnf = new HashMap<>(); | ||||
|         configuration.forEach(option -> cnf.put(option.getId(), option)); | ||||
|         return manufacture(cnf); | ||||
|     } | ||||
|     default Minigame manufacture() { | ||||
|         if(this.configuration() == null) return manufacture(List.of()); | ||||
|         return manufacture(this.configuration().getAll()); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,51 @@ | ||||
| package eu.mhsl.minenet.minigames.instance.game.minigame.config; | ||||
|  | ||||
| import net.kyori.adventure.text.Component; | ||||
| import net.minestom.server.item.ItemStack; | ||||
| import net.minestom.server.item.Material; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| public abstract class Option<T> { | ||||
|     private final Material item; | ||||
|     private final String name; | ||||
|     private final String id; | ||||
|  | ||||
|     protected T currentValue; | ||||
|     private final List<T> options; | ||||
|     private int pointer = 0; | ||||
|  | ||||
|     public Option(String id, Material item, String name, List<T> options) { | ||||
|         this.id = id; | ||||
|         this.item = item; | ||||
|         this.name = name; | ||||
|         this.options = options; | ||||
|  | ||||
|         currentValue = options.get(0); | ||||
|     } | ||||
|  | ||||
|     public ItemStack getNext() { | ||||
|         if(++pointer >= options.size()) pointer = 0; | ||||
|         currentValue = options.get(pointer); | ||||
|         return getCurrent(); | ||||
|     } | ||||
|  | ||||
|     public ItemStack getCurrent() { | ||||
|         int amount = Integer.parseInt(options.get(pointer).toString()); | ||||
|         return ItemStack.builder(item) | ||||
|                 .displayName(Component.text(name).append(Component.text(" - ")).append(Component.text(amount))) | ||||
|                 .build(); | ||||
|     } | ||||
|  | ||||
|     public int getAsInt() { | ||||
|         return Integer.parseInt(getAsString()); | ||||
|     } | ||||
|  | ||||
|     public String getAsString() { | ||||
|         return currentValue.toString(); | ||||
|     } | ||||
|  | ||||
|     public String getId() { | ||||
|         return id; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,12 @@ | ||||
| package eu.mhsl.minenet.minigames.instance.game.minigame.config.options; | ||||
|  | ||||
| import eu.mhsl.minenet.minigames.instance.game.minigame.config.Option; | ||||
| import net.minestom.server.item.Material; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| public class BoolOption extends Option<Boolean> { | ||||
|     public BoolOption(String id, Material item, String name) { | ||||
|         super(id, item, name, List.of(true, false)); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,12 @@ | ||||
| package eu.mhsl.minenet.minigames.instance.game.minigame.config.options; | ||||
|  | ||||
| import eu.mhsl.minenet.minigames.instance.game.minigame.config.Option; | ||||
| import net.minestom.server.item.Material; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| public class NumericOption extends Option<Integer> { | ||||
|     public NumericOption(String id, Material item, String name, Integer... options) { | ||||
|         super(id, item, name, List.of(options)); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,57 @@ | ||||
| package eu.mhsl.minenet.minigames.instance.game.minigame.types.deathcube; | ||||
|  | ||||
| import eu.mhsl.minenet.minigames.instance.game.minigame.Minigame; | ||||
| import eu.mhsl.minenet.minigames.util.BatchUtil; | ||||
| import eu.mhsl.minenet.minigames.instance.Dimension; | ||||
| import eu.mhsl.minenet.minigames.world.generator.BlockPallet; | ||||
| import eu.mhsl.minenet.minigames.world.generator.terrain.CircularTerrainGenerator; | ||||
| import net.minestom.server.coordinate.Pos; | ||||
| import net.minestom.server.event.player.PlayerMoveEvent; | ||||
| import net.minestom.server.instance.batch.AbsoluteBlockBatch; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
|  | ||||
| import java.util.concurrent.CompletableFuture; | ||||
|  | ||||
| class Deathcube extends Minigame { | ||||
|  | ||||
|     int radius, height, percentage; | ||||
|  | ||||
|     public Deathcube(int radius, int height, int percentage) { | ||||
|         super(Dimension.THE_END.DIMENSION, "Deathcube"); | ||||
|         this.radius = radius; | ||||
|         this.height = height; | ||||
|         this.percentage = percentage; | ||||
|         this.setGenerator(new CircularTerrainGenerator(40, true)); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected void onLoad(CompletableFuture<Void> callback) { | ||||
|         AbsoluteBlockBatch batch = new AbsoluteBlockBatch(); | ||||
|  | ||||
|         for(int x = -radius; x <= radius; x++) { | ||||
|             for (int z = -radius; z <= radius; z++) { | ||||
|                 if(new Pos(x, 0, z).distance(new Pos(0, 0, 0)) > radius) continue; | ||||
|  | ||||
|                 for (int y = 49; y < height; y++) { | ||||
|                     if(super.rnd.nextInt(1, 100) <= percentage) { | ||||
|                         batch.setBlock(x, y, z, BlockPallet.WOOD.rnd()); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         BatchUtil.loadAndApplyBatch(batch, this, () -> callback.complete(null)); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected void onPlayerMove(@NotNull PlayerMoveEvent playerMoveEvent) { | ||||
|         super.onPlayerMove(playerMoveEvent); | ||||
|         if(isBeforeBeginning) if(playerMoveEvent.getNewPosition().y() > 51.5) playerMoveEvent.setCancelled(true); | ||||
|         if(playerMoveEvent.getNewPosition().y() > 100) getScore().addResult(playerMoveEvent.getPlayer()); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Pos getSpawn() { | ||||
|         return new Pos(0, 50, 30); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,36 @@ | ||||
| package eu.mhsl.minenet.minigames.instance.game.minigame.types.deathcube; | ||||
|  | ||||
| import eu.mhsl.minenet.minigames.instance.game.minigame.Minigame; | ||||
| import eu.mhsl.minenet.minigames.instance.game.minigame.config.GameFactory; | ||||
| import eu.mhsl.minenet.minigames.instance.game.minigame.config.Option; | ||||
| import eu.mhsl.minenet.minigames.instance.game.minigame.config.ConfigManager; | ||||
| import eu.mhsl.minenet.minigames.instance.game.minigame.config.options.NumericOption; | ||||
| import net.kyori.adventure.text.Component; | ||||
| import net.minestom.server.item.Material; | ||||
|  | ||||
| import java.util.Map; | ||||
|  | ||||
| public class DeathcubeFactory implements GameFactory { | ||||
|     @Override | ||||
|     public Component name() { | ||||
|         return Component.text("Deathcube"); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public ConfigManager configuration() { | ||||
|         return new ConfigManager() | ||||
|                 .addOption(new NumericOption("radius", Material.HEART_OF_THE_SEA, "Radius", 10, 30, 50, 100)) | ||||
|                 .addOption(new NumericOption("height", Material.SCAFFOLDING, "Height", 50, 100, 150, 200)) | ||||
|                 .addOption(new NumericOption("percentage", Material.COBWEB, "Percent of blocks", 5, 7, 9, 11, 13)); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Minigame manufacture(Map<String, Option<?>> configuration) { | ||||
|         return new Deathcube(configuration.get("radius").getAsInt(), configuration.get("height").getAsInt(), configuration.get("percentage").getAsInt()); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Material symbol() { | ||||
|         return Material.OAK_FENCE; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,130 @@ | ||||
| package eu.mhsl.minenet.minigames.instance.game.minigame.types.minerun; | ||||
|  | ||||
| import eu.mhsl.minenet.minigames.instance.game.minigame.Minigame; | ||||
| import eu.mhsl.minenet.minigames.message.type.ActionBarMessage; | ||||
| import eu.mhsl.minenet.minigames.util.BatchUtil; | ||||
| import eu.mhsl.minenet.minigames.util.Intersect; | ||||
| import eu.mhsl.minenet.minigames.instance.Dimension; | ||||
| 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.kyori.adventure.text.Component; | ||||
| import net.kyori.adventure.text.format.NamedTextColor; | ||||
| import net.minestom.server.coordinate.Pos; | ||||
| import net.minestom.server.entity.Entity; | ||||
| import net.minestom.server.entity.Player; | ||||
| 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 org.jetbrains.annotations.NotNull; | ||||
|  | ||||
| import java.util.*; | ||||
| import java.util.concurrent.CompletableFuture; | ||||
|  | ||||
| class Minerun extends Minigame { | ||||
|  | ||||
|     private int minePercentage = 50; | ||||
|     private int width = 100; | ||||
|     private int length = 50; | ||||
|  | ||||
|     private final int backRun = -5; | ||||
|     private final int preRun = 5; | ||||
|     private final int afterMines = 2; | ||||
|     private final int afterFinishLine = 10; | ||||
|  | ||||
|     public Minerun(int width, int length, int minePercentage) { | ||||
|         super(Dimension.THE_END.DIMENSION, "Minerun"); | ||||
|         setGenerator(new SquareTerrainGenerator(width, length + preRun + afterFinishLine, true)); | ||||
|  | ||||
|         this.width = width; | ||||
|         this.length = length; | ||||
|         this.minePercentage = minePercentage; | ||||
|  | ||||
|         System.out.println(width + " " + length + " " + minePercentage); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected void onLoad(CompletableFuture<Void> callback) { | ||||
|         int spawnToFinishLine = preRun + length + afterMines; | ||||
|         int spawnToEnd = spawnToFinishLine + afterFinishLine; | ||||
|  | ||||
|         Random random = new Random(); | ||||
|         AbsoluteBlockBatch batch = new AbsoluteBlockBatch(); | ||||
|  | ||||
|         for(int x = 0; x <= width; x++) { | ||||
|             for(int z = preRun; z <= length + preRun; z++) { | ||||
|  | ||||
|                 if (random.nextInt(0, 100) < minePercentage) { | ||||
|                     batch.setBlock(x, 50, z, BlockPallet.PRESSURE_PLATES.rnd()); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         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)); | ||||
|         } | ||||
|         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, 50, preRun, Block.AIR); | ||||
|         } | ||||
|  | ||||
|         BatchUtil.loadAndApplyBatch(batch, this, () -> { | ||||
|             playSound(Sound.sound(SoundEvent.BLOCK_WOOD_BREAK, Sound.Source.BLOCK, 1f, 1f)); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected void onPlayerMove(@NotNull PlayerMoveEvent playerMoveEvent) { | ||||
|  | ||||
|         Player p = playerMoveEvent.getPlayer(); | ||||
|         Pos middle = playerMoveEvent.getNewPosition(); | ||||
|  | ||||
|         if(middle.x() < 0 || middle.x() > width) { //player cannot go sidewards | ||||
|             playerMoveEvent.setCancelled(true); | ||||
|             new ActionBarMessage().appendStatic(Component.text("Please stay in line!", NamedTextColor.RED)).send(p); | ||||
|         } | ||||
|  | ||||
|         if(!isRunning && middle.z() > preRun+0.5) { //player cannot go forward before game start | ||||
|             playerMoveEvent.setCancelled(true); | ||||
|         } | ||||
|  | ||||
|         if(getScore().hasResult(p) && middle.z() < preRun + length + afterMines) { // player cannot go back | ||||
|             playerMoveEvent.setCancelled(true); | ||||
|             new ActionBarMessage().appendStatic(Component.text("You cannot go back on the Field!", NamedTextColor.RED)).send(p); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if(Intersect.withPressurePlate(this, BlockPallet.PRESSURE_PLATES, middle)) { //Player died | ||||
|             p.setPose(Entity.Pose.DYING); | ||||
|             p.teleport(new Pos(p.getPosition().x(), getSpawn().y(), getSpawn().z())); | ||||
|             p.playSound(Sound.sound(SoundEvent.ENTITY_GENERIC_EXPLODE, Sound.Source.PLAYER, 1f, 1f)); | ||||
|         } | ||||
|  | ||||
|         if(middle.z() > preRun + length + afterMines) { // Player finished | ||||
|             getScore().addResult(p); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Pos getSpawn() { | ||||
|         return new Pos(width/2, 50, 3); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,42 @@ | ||||
| package eu.mhsl.minenet.minigames.instance.game.minigame.types.minerun; | ||||
|  | ||||
| import eu.mhsl.minenet.minigames.instance.game.minigame.Minigame; | ||||
| import eu.mhsl.minenet.minigames.instance.game.minigame.config.ConfigManager; | ||||
| import eu.mhsl.minenet.minigames.instance.game.minigame.config.GameFactory; | ||||
| import eu.mhsl.minenet.minigames.instance.game.minigame.config.Option; | ||||
| import eu.mhsl.minenet.minigames.instance.game.minigame.config.options.NumericOption; | ||||
| import net.kyori.adventure.text.Component; | ||||
| import net.minestom.server.item.Material; | ||||
|  | ||||
| import java.util.Map; | ||||
|  | ||||
| public class MinerunFactory implements GameFactory { | ||||
|     @Override | ||||
|     public Component name() { | ||||
|         return Component.text("Deathcube"); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public ConfigManager configuration() { | ||||
|         return new ConfigManager() | ||||
|                 .addOption(new NumericOption("width", Material.OAK_FENCE, "Width", 10, 30, 50, 100)) | ||||
|                 .addOption(new NumericOption("length", Material.ZOMBIE_HEAD, "Length", 50, 100, 150, 200)) | ||||
|                 .addOption(new NumericOption("percentage", Material.LIGHT_WEIGHTED_PRESSURE_PLATE, "Percent of mines", 30, 40, 50, 60, 70)); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Minigame manufacture(Map<String, Option<?>> configuration) { | ||||
|         System.out.println("Manufacture" + configuration.get("width").getAsInt()); | ||||
|         return new Minerun(configuration.get("width").getAsInt(), configuration.get("length").getAsInt(), configuration.get("percentage").getAsInt()); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Material symbol() { | ||||
|         return Material.LIGHT_WEIGHTED_PRESSURE_PLATE; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Component description() { | ||||
|         return Component.text("Weiche druckplatten aus"); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,32 @@ | ||||
| package eu.mhsl.minenet.minigames.instance.game.minigame.types.stickfight; | ||||
|  | ||||
| import eu.mhsl.minenet.minigames.instance.game.minigame.Minigame; | ||||
| import eu.mhsl.minenet.minigames.instance.game.minigame.config.ConfigManager; | ||||
| import eu.mhsl.minenet.minigames.instance.game.minigame.config.GameFactory; | ||||
| import eu.mhsl.minenet.minigames.instance.game.minigame.config.Option; | ||||
| import net.kyori.adventure.text.Component; | ||||
| import net.minestom.server.item.Material; | ||||
|  | ||||
| import java.util.Map; | ||||
|  | ||||
| public class StickFightFactory implements GameFactory { | ||||
|     @Override | ||||
|     public Component name() { | ||||
|         return Component.text("Stickfight"); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public ConfigManager configuration() { | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Minigame manufacture(Map<String, Option<?>> configuration) { | ||||
|         return new Stickfight(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Material symbol() { | ||||
|         return Material.STICK; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,71 @@ | ||||
| package eu.mhsl.minenet.minigames.instance.game.minigame.types.stickfight; | ||||
|  | ||||
| import eu.mhsl.minenet.minigames.instance.Dimension; | ||||
| import eu.mhsl.minenet.minigames.instance.game.minigame.Minigame; | ||||
| import eu.mhsl.minenet.minigames.util.BatchUtil; | ||||
| import eu.mhsl.minenet.minigames.world.generator.terrain.CircularTerrainGenerator; | ||||
| import eu.mhsl.minenet.minigames.world.generator.terrain.SquareTerrainGenerator; | ||||
| import io.github.bloepiloepi.pvp.PvpExtension; | ||||
| import io.github.bloepiloepi.pvp.config.*; | ||||
| import io.github.bloepiloepi.pvp.events.FinalAttackEvent; | ||||
| import net.minestom.server.coordinate.Pos; | ||||
| import net.minestom.server.entity.Player; | ||||
| import net.minestom.server.event.EventNode; | ||||
| import net.minestom.server.event.instance.AddEntityToInstanceEvent; | ||||
| import net.minestom.server.event.player.PlayerMoveEvent; | ||||
| import net.minestom.server.event.trait.InstanceEvent; | ||||
| import net.minestom.server.instance.batch.AbsoluteBlockBatch; | ||||
| import net.minestom.server.instance.block.Block; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
|  | ||||
| import java.util.concurrent.CompletableFuture; | ||||
|  | ||||
| public class Stickfight extends Minigame { | ||||
|     public Stickfight() { | ||||
|         super(Dimension.OVERWORLD.DIMENSION, "Stickfight"); | ||||
|  | ||||
|         eventNode().addChild( | ||||
|                 PvPConfig.emptyBuilder() | ||||
|                         .damage(DamageConfig.legacyBuilder().fallDamage(false)) | ||||
|                         .attack(AttackConfig.legacyBuilder().attackCooldown(true)) | ||||
|                         .build().createNode() | ||||
|         ); | ||||
|  | ||||
|         eventNode().addListener(FinalAttackEvent.class, finalAttackEvent -> { | ||||
|             finalAttackEvent.setBaseDamage(0); | ||||
|             ((Player) finalAttackEvent.getTarget()).setHealth(20); | ||||
|         }); | ||||
|  | ||||
|         setGenerator(new CircularTerrainGenerator(20, false)); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected void onLoad(CompletableFuture<Void> callback) { | ||||
|         AbsoluteBlockBatch batch = new AbsoluteBlockBatch(); | ||||
|         for (int z = -10; z <= 10; z++) { | ||||
|             batch.setBlock(0, 50, z, Block.SANDSTONE); | ||||
|         } | ||||
|         batch.setBlock(0, 50, 0, Block.GOLD_BLOCK); | ||||
|  | ||||
|         BatchUtil.loadAndApplyBatch(batch, this, () -> callback.complete(null)); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected void onPlayerMove(@NotNull PlayerMoveEvent playerMoveEvent) { | ||||
|         if(isBeforeBeginning) playerMoveEvent.setCancelled(true); | ||||
|  | ||||
|         if(playerMoveEvent.getNewPosition().y() < 40) { | ||||
|             playerMoveEvent.getPlayer().teleport(new Pos(0, 51, 0)); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected void onJoin(@NotNull AddEntityToInstanceEvent addEntityToInstanceEvent) { | ||||
|  | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Pos getSpawn() { | ||||
|         return new Pos(0.5, 51, 0.5); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,29 @@ | ||||
| package eu.mhsl.minenet.minigames.instance.game.minigame.types.trafficlightrace; | ||||
|  | ||||
| import net.minestom.server.item.ItemStack; | ||||
| import net.minestom.server.item.Material; | ||||
| import net.minestom.server.timer.TaskSchedule; | ||||
|  | ||||
| import java.util.Random; | ||||
|  | ||||
| enum LightPhase { | ||||
|     RED(Material.RED_WOOL, 1000, 5000), | ||||
|     YELLOW(Material.YELLOW_WOOL, 1000, 2000), | ||||
|     GREEN(Material.GREEN_WOOL, 1000, 5000); | ||||
|  | ||||
|     public final ItemStack item; | ||||
|     private final int minDuration; | ||||
|     private final int maxDuration; | ||||
|     private static final Random rnd = new Random(); | ||||
|  | ||||
|     LightPhase(Material material, int minDuration, int maxDuration) { | ||||
|         this.item = ItemStack.of(material); | ||||
|         this.minDuration = minDuration; | ||||
|         this.maxDuration = maxDuration; | ||||
|     } | ||||
|  | ||||
|     public TaskSchedule taskScheduleRandomDuration() { | ||||
|         return TaskSchedule.millis(rnd.nextLong(minDuration, maxDuration)); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,69 @@ | ||||
| package eu.mhsl.minenet.minigames.instance.game.minigame.types.trafficlightrace; | ||||
|  | ||||
| import eu.mhsl.minenet.minigames.instance.game.minigame.Minigame; | ||||
| import eu.mhsl.minenet.minigames.util.BatchUtil; | ||||
| import eu.mhsl.minenet.minigames.instance.Dimension; | ||||
| import net.minestom.server.coordinate.Vec; | ||||
| 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.timer.ExecutionType; | ||||
| import net.minestom.server.timer.TaskSchedule; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
|  | ||||
| import java.util.concurrent.CompletableFuture; | ||||
|  | ||||
| class TrafficLightRace extends Minigame { | ||||
|     private LightPhase phase = LightPhase.RED; | ||||
|     private int phaseCounter = 1; | ||||
|  | ||||
|     public TrafficLightRace() { | ||||
|         super(Dimension.THE_END.DIMENSION, "Ampelrennen"); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected void onLoad(CompletableFuture<Void> callback) { | ||||
|         AbsoluteBlockBatch batch = new AbsoluteBlockBatch(); | ||||
|         for (int x = -10; x <= 10; x++) { | ||||
|             for (int z = 5; z <= 100; z++) { | ||||
|                 batch.setBlock(x, 5, z, super.rnd.nextInt(0, 100) > 90 ? Block.SOUL_SAND : Block.BLACK_CONCRETE_POWDER); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         BatchUtil.loadAndApplyBatch(batch, this, () -> callback.complete(null)); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected void onStart() { | ||||
|         scheduler().submitTask(() -> { | ||||
|             if(!super.isRunning) return TaskSchedule.stop(); | ||||
|  | ||||
|             phaseCounter++; | ||||
|             if(phaseCounter >= 4) phaseCounter = 0; | ||||
|  | ||||
|             if(phaseCounter == 0) phase = LightPhase.RED; | ||||
|             if(phaseCounter == 1 || phaseCounter == 3) phase = LightPhase.YELLOW; | ||||
|             if(phaseCounter == 2) phase = LightPhase.GREEN; | ||||
|  | ||||
|             getPlayers().forEach(player -> { | ||||
|                 for(int i = 0; i < 9; i++) { | ||||
|                     player.getInventory().setItemStack(i, phase.item); | ||||
|                 } | ||||
|             }); | ||||
|  | ||||
|             return phase.taskScheduleRandomDuration(); | ||||
|         }, ExecutionType.SYNC); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected void onPlayerMove(@NotNull PlayerMoveEvent playerMoveEvent) { | ||||
|         super.onPlayerMove(playerMoveEvent); | ||||
|  | ||||
|         if(playerMoveEvent.getNewPosition().z() > 110) stop(); | ||||
|  | ||||
|         if(phase.equals(LightPhase.RED) && playerMoveEvent.getNewPosition().z() > playerMoveEvent.getPlayer().getPosition().z()) { | ||||
|             playerMoveEvent.getPlayer().setVelocity(new Vec(0, 5, -10)); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,32 @@ | ||||
| package eu.mhsl.minenet.minigames.instance.game.minigame.types.trafficlightrace; | ||||
|  | ||||
| import eu.mhsl.minenet.minigames.instance.game.minigame.Minigame; | ||||
| import eu.mhsl.minenet.minigames.instance.game.minigame.config.GameFactory; | ||||
| import eu.mhsl.minenet.minigames.instance.game.minigame.config.ConfigManager; | ||||
| import eu.mhsl.minenet.minigames.instance.game.minigame.config.Option; | ||||
| import net.kyori.adventure.text.Component; | ||||
| import net.minestom.server.item.Material; | ||||
|  | ||||
| import java.util.Map; | ||||
|  | ||||
| public class TrafficLightRaceFactory implements GameFactory { | ||||
|     @Override | ||||
|     public Component name() { | ||||
|         return Component.text("TrafficLightRace"); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public ConfigManager configuration() { | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Minigame manufacture(Map<String, Option<?>> configuration) { | ||||
|         return new TrafficLightRace(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Material symbol() { | ||||
|         return Material.YELLOW_WOOL; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,46 @@ | ||||
| package eu.mhsl.minenet.minigames.instance.hub; | ||||
|  | ||||
| import eu.mhsl.minenet.minigames.Resource; | ||||
| import eu.mhsl.minenet.minigames.instance.hub.entity.RoomSelector; | ||||
| import eu.mhsl.minenet.minigames.util.CommonEventHandles; | ||||
| import eu.mhsl.minenet.minigames.instance.Spawnable; | ||||
| import eu.mhsl.minenet.minigames.instance.Dimension; | ||||
| import net.minestom.server.MinecraftServer; | ||||
| import net.minestom.server.coordinate.Pos; | ||||
| import net.minestom.server.event.player.*; | ||||
| import net.minestom.server.instance.AnvilLoader; | ||||
| import net.minestom.server.instance.InstanceContainer; | ||||
|  | ||||
| import java.nio.file.Path; | ||||
| import java.util.UUID; | ||||
|  | ||||
| public class HubInstance extends InstanceContainer implements Spawnable { | ||||
|     public static final HubInstance INSTANCE = new HubInstance(); | ||||
|  | ||||
|     static { | ||||
|         MinecraftServer.getInstanceManager().registerInstance(INSTANCE); | ||||
|  | ||||
|         INSTANCE.setChunkLoader(new AnvilLoader(Resource.HUB_MAP.getPath())); | ||||
|  | ||||
|         INSTANCE.eventNode() | ||||
|                 .addListener(PlayerBlockBreakEvent.class, CommonEventHandles::cancel) | ||||
|                 .addListener(PlayerBlockPlaceEvent.class, CommonEventHandles::cancel) | ||||
|                 .addListener(PlayerBlockInteractEvent.class, CommonEventHandles::cancel); | ||||
|  | ||||
|         new RoomSelector().setInstance(INSTANCE, new Pos(0.5, 11, 4.5)); | ||||
|     } | ||||
|  | ||||
|     private HubInstance() { | ||||
|         super(UUID.randomUUID(), Dimension.THE_END.DIMENSION); | ||||
|         setChunkLoader(new AnvilLoader(Path.of("maps/hub"))); | ||||
|  | ||||
|         setTime(18000); | ||||
|         setTimeRate(0); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Pos getSpawn() { | ||||
|         return new Pos(0.5, 11, 0.5); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,35 @@ | ||||
| package eu.mhsl.minenet.minigames.instance.hub.entity; | ||||
|  | ||||
| import eu.mhsl.minenet.minigames.instance.hub.inventory.HubInventory; | ||||
| import eu.mhsl.minenet.minigames.shared.entity.InteractableEntity; | ||||
| import net.minestom.server.entity.EntityType; | ||||
| import net.minestom.server.entity.metadata.villager.AbstractVillagerMeta; | ||||
| import net.minestom.server.event.entity.EntityAttackEvent; | ||||
| import net.minestom.server.event.instance.AddEntityToInstanceEvent; | ||||
| import net.minestom.server.event.player.PlayerEntityInteractEvent; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
|  | ||||
| public class RoomSelector extends InteractableEntity { | ||||
|     final AbstractVillagerMeta abstractVillagerMeta; | ||||
|     public RoomSelector() { | ||||
|         super(EntityType.VILLAGER); | ||||
|  | ||||
|         abstractVillagerMeta = (AbstractVillagerMeta) this.getEntityMeta(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void onSpawn(@NotNull AddEntityToInstanceEvent addEntityToInstanceEvent) { | ||||
|  | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void onAttack(@NotNull EntityAttackEvent entityAttackEvent) { | ||||
|         super.onAttack(entityAttackEvent); | ||||
|         abstractVillagerMeta.setHeadShakeTimer(20); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void onInteract(@NotNull PlayerEntityInteractEvent playerEntityInteractEvent) { | ||||
|         playerEntityInteractEvent.getPlayer().openInventory(new HubInventory()); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,37 @@ | ||||
| package eu.mhsl.minenet.minigames.instance.hub.inventory; | ||||
|  | ||||
| import eu.mhsl.minenet.minigames.instance.room.Room; | ||||
| import eu.mhsl.minenet.minigames.shared.inventory.InteractableInventory; | ||||
| import net.kyori.adventure.text.Component; | ||||
| import net.minestom.server.inventory.InventoryType; | ||||
| import net.minestom.server.item.ItemHideFlag; | ||||
| import net.minestom.server.item.ItemStack; | ||||
| import net.minestom.server.item.Material; | ||||
|  | ||||
| public class HubInventory extends InteractableInventory { | ||||
|     public HubInventory() { | ||||
|         super(InventoryType.CHEST_3_ROW, Component.text("MineNet Servernetzwerk")); | ||||
|  | ||||
|         setClickableItem( | ||||
|                 ItemStack | ||||
|                         .builder(Material.WRITABLE_BOOK) | ||||
|                         .displayName(Component.text("Create own room")) | ||||
|                         .lore(Component.text("Create new empty room")) | ||||
|                         .meta(metaBuilder -> metaBuilder.hideFlag(ItemHideFlag.HIDE_ATTRIBUTES)) | ||||
|                         .build(), | ||||
|                 12, | ||||
|                 itemClick -> Room.createRoom(itemClick.getPlayer()), | ||||
|                 true | ||||
|         ); | ||||
|  | ||||
|         setClickableItem( | ||||
|                 ItemStack | ||||
|                         .builder(Material.KNOWLEDGE_BOOK) | ||||
|                         .displayName(Component.text("Browse room")) | ||||
|                         .lore(Component.text("Browse existing rooms")) | ||||
|                         .build(), | ||||
|                 14, | ||||
|                 itemClick -> itemClick.getPlayer().openInventory(new JoinInventory()) | ||||
|         ); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,70 @@ | ||||
| package eu.mhsl.minenet.minigames.instance.hub.inventory; | ||||
|  | ||||
| import eu.mhsl.minenet.minigames.instance.room.Room; | ||||
| import eu.mhsl.minenet.minigames.message.Icon; | ||||
| import eu.mhsl.minenet.minigames.message.type.ChatMessage; | ||||
| import eu.mhsl.minenet.minigames.shared.inventory.InteractableInventory; | ||||
| import eu.mhsl.minenet.minigames.instance.hub.HubInstance; | ||||
| import net.kyori.adventure.text.Component; | ||||
| import net.minestom.server.MinecraftServer; | ||||
| import net.minestom.server.entity.Player; | ||||
| import net.minestom.server.event.player.PlayerPacketEvent; | ||||
| import net.minestom.server.inventory.InventoryType; | ||||
| import net.minestom.server.inventory.click.ClickType; | ||||
| import net.minestom.server.inventory.condition.InventoryConditionResult; | ||||
| import net.minestom.server.item.ItemStack; | ||||
| import net.minestom.server.item.Material; | ||||
| import net.minestom.server.item.metadata.PlayerHeadMeta; | ||||
| import net.minestom.server.network.packet.client.play.ClientNameItemPacket; | ||||
|  | ||||
| import java.util.Locale; | ||||
|  | ||||
| public class JoinInventory extends InteractableInventory { | ||||
|     private String typedText = ""; | ||||
|     private final String prefix = "name:"; | ||||
|  | ||||
|     public JoinInventory() { | ||||
|         super(InventoryType.ANVIL, Component.text("Enter username")); | ||||
|  | ||||
|         setClickableItem( | ||||
|                 ItemStack.builder(Material.PLAYER_HEAD) | ||||
|                         .displayName(Component.text(prefix)) | ||||
|                         .meta(PlayerHeadMeta.class, builder -> { | ||||
|  | ||||
|                         }) | ||||
|                         .build(), | ||||
|                 0, | ||||
|                 itemClick -> {} | ||||
|         ); | ||||
|  | ||||
|         HubInstance.INSTANCE.eventNode().addListener(PlayerPacketEvent.class, event -> { | ||||
|             if (event.getPacket() instanceof ClientNameItemPacket packet) { | ||||
|                 typedText = packet.itemName(); | ||||
|             } | ||||
|         }); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected void onClick(Player player, int slot, ClickType clickType, InventoryConditionResult inventoryConditionResult) { | ||||
|         if(slot != 2) return; | ||||
|         inventoryConditionResult.setCancel(true); | ||||
|         player.closeInventory(); | ||||
|  | ||||
|         typedText = formatInput(typedText); | ||||
|  | ||||
|         Room target = Room.getRoom(MinecraftServer.getConnectionManager().findPlayer(typedText)); | ||||
|         if(target != null) | ||||
|             Room.setRoom(player, target); | ||||
|         else | ||||
|             new ChatMessage(Icon.ERROR).appendStatic("The room").quote(typedText).appendStatic("could not be found!").send(player); | ||||
|     } | ||||
|  | ||||
|     private String formatInput(String raw) { | ||||
|         if(raw.startsWith(prefix)) { | ||||
|             raw = raw.split(prefix)[1]; | ||||
|         } | ||||
|  | ||||
|         return raw.toLowerCase(Locale.ROOT).trim(); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										123
									
								
								src/main/java/eu/mhsl/minenet/minigames/instance/room/Room.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										123
									
								
								src/main/java/eu/mhsl/minenet/minigames/instance/room/Room.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,123 @@ | ||||
| package eu.mhsl.minenet.minigames.instance.room; | ||||
|  | ||||
| import eu.mhsl.minenet.minigames.Resource; | ||||
| import eu.mhsl.minenet.minigames.instance.game.Game; | ||||
| import eu.mhsl.minenet.minigames.message.Icon; | ||||
| import eu.mhsl.minenet.minigames.message.type.ChatMessage; | ||||
| import eu.mhsl.minenet.minigames.util.CommonEventHandles; | ||||
| import eu.mhsl.minenet.minigames.util.MoveInstance; | ||||
| import eu.mhsl.minenet.minigames.instance.Spawnable; | ||||
| import eu.mhsl.minenet.minigames.instance.Dimension; | ||||
| import eu.mhsl.minenet.minigames.instance.hub.HubInstance; | ||||
| import eu.mhsl.minenet.minigames.instance.room.entity.GameSelector; | ||||
| import net.minestom.server.MinecraftServer; | ||||
| import net.minestom.server.coordinate.Pos; | ||||
| import net.minestom.server.entity.Player; | ||||
| import net.minestom.server.event.player.PlayerBlockBreakEvent; | ||||
| import net.minestom.server.event.player.PlayerDisconnectEvent; | ||||
| import net.minestom.server.instance.AnvilLoader; | ||||
| import net.minestom.server.instance.InstanceContainer; | ||||
|  | ||||
| import java.util.*; | ||||
| import java.util.stream.Collectors; | ||||
|  | ||||
| public class Room extends InstanceContainer implements Spawnable { | ||||
|     private static final Map<Player, Room> rooms = new WeakHashMap<>(); | ||||
|  | ||||
|     public static Room createRoom(Player owner) { | ||||
|         System.out.println("Room created by " + owner.getUsername()); | ||||
|         setRoom(owner, new Room(owner)); | ||||
|         return getRoom(owner); | ||||
|     } | ||||
|  | ||||
|     public static void deleteRoom(Room room) { | ||||
|         System.out.println("Room deleted"); | ||||
|         rooms.values().removeAll(Collections.singleton(room)); // remove(room) would only remove the first one | ||||
|         room.getAllMembers().forEach(player -> MoveInstance.move(player, HubInstance.INSTANCE)); | ||||
|         MoveInstance.forceCloseInstance(room); | ||||
|     } | ||||
|  | ||||
|     public static Room getRoom(Player p) { | ||||
|         return rooms.get(p); | ||||
|     } | ||||
|  | ||||
|     public static void setOwnRoom(Player p) { | ||||
|         setRoom(p, getRoom(p)); | ||||
|     } | ||||
|  | ||||
|     public static void setRoom(Player p, Room room) { | ||||
|         p.clearEffects(); | ||||
|         p.clearTitle(); | ||||
|         p.getInventory().clear(); | ||||
|         rooms.put(p, room); | ||||
|         MoveInstance.move(p, room); | ||||
|     } | ||||
|  | ||||
|     public static void unsetRoom(Player p) { | ||||
|         rooms.remove(p); | ||||
|     } | ||||
|  | ||||
|     public static Set<Room> getAllRooms() { | ||||
|         return new HashSet<>(rooms.values()); | ||||
|     } | ||||
|  | ||||
|     private Player owner; | ||||
|     private Room(Player owner) { | ||||
|         super(UUID.randomUUID(), Dimension.THE_END.DIMENSION); | ||||
|         MinecraftServer.getInstanceManager().registerInstance(this); | ||||
|         setChunkLoader(new AnvilLoader(Resource.LOBBY_MAP.getPath())); | ||||
|  | ||||
|         eventNode().addListener(PlayerBlockBreakEvent.class, CommonEventHandles::cancel); | ||||
|  | ||||
|         setOwner(owner); | ||||
|  | ||||
|         new GameSelector().setInstance(this, new Pos(0.5, 16, 9.5)); | ||||
|     } | ||||
|  | ||||
|     public Player getOwner() { | ||||
|         return owner; | ||||
|     } | ||||
|  | ||||
|     private void setOwner(Player newOwner) { | ||||
|         this.owner = newOwner; | ||||
|  | ||||
|         this.owner.eventNode().addListener(PlayerDisconnectEvent.class, playerDisconnectEvent -> { | ||||
|             System.out.println("Room Leader left room"); | ||||
|             Player p = playerDisconnectEvent.getPlayer(); | ||||
|  | ||||
|             if(p != this.owner) return; // return if the current handling player is really the current owner | ||||
|  | ||||
|             getAllMembers().stream() | ||||
|                     .filter(player -> player != p) // exclude the current leaving owner | ||||
|                     .findFirst() // find first user meeting the requirement | ||||
|                     .ifPresentOrElse( | ||||
|                             this::setOwner, // set the new owner | ||||
|                             () -> Room.deleteRoom(Room.getRoom(p)) // or else delete the room (no players in the room) | ||||
|                     ); | ||||
|  | ||||
|             Room.unsetRoom(p); // remove the player itself from the room | ||||
|  | ||||
|             new ChatMessage(Icon.ERROR).appendStatic("The room leader left!").send(getAllMembers()); | ||||
|             new ChatMessage(Icon.SCIENCE).appendStatic(this.owner.getUsername()).appendStatic(" is the new Leader!").send(getAllMembers().stream().filter(player -> player != this.owner).collect(Collectors.toSet())); | ||||
|             new ChatMessage(Icon.SUCCESS).appendStatic("You are now the leader.").send(this.owner); | ||||
|         }); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     public void moveMembersToGame(Game game) { | ||||
|         this.getAllMembers().forEach(player -> { | ||||
|             MoveInstance.move(player, game); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     public Set<Player> getAllMembers() { | ||||
|         return rooms.keySet().stream() | ||||
|                 .filter(player -> getRoom(player) == this) | ||||
|                 .collect(Collectors.toSet()); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Pos getSpawn() { | ||||
|         return new Pos(0.5, 16, 0.5); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,49 @@ | ||||
| package eu.mhsl.minenet.minigames.instance.room.entity; | ||||
|  | ||||
| import eu.mhsl.minenet.minigames.instance.room.Room; | ||||
| import eu.mhsl.minenet.minigames.instance.room.inventory.MinigameTypeSelectInventory; | ||||
| import eu.mhsl.minenet.minigames.message.Icon; | ||||
| import eu.mhsl.minenet.minigames.message.type.ChatMessage; | ||||
| import eu.mhsl.minenet.minigames.shared.entity.InteractableEntity; | ||||
| import net.minestom.server.entity.EntityType; | ||||
| import net.minestom.server.entity.metadata.villager.AbstractVillagerMeta; | ||||
| import net.minestom.server.event.entity.EntityAttackEvent; | ||||
| import net.minestom.server.event.instance.AddEntityToInstanceEvent; | ||||
| import net.minestom.server.event.player.PlayerEntityInteractEvent; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
|  | ||||
| public class GameSelector extends InteractableEntity { | ||||
|     final AbstractVillagerMeta abstractVillagerMeta; | ||||
|     public GameSelector() { | ||||
|         super(EntityType.VILLAGER); | ||||
|  | ||||
|         abstractVillagerMeta = (AbstractVillagerMeta) this.getEntityMeta(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void onSpawn(@NotNull AddEntityToInstanceEvent addEntityToInstanceEvent) { | ||||
|  | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void onAttack(@NotNull EntityAttackEvent entityAttackEvent) { | ||||
|         super.onAttack(entityAttackEvent); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void onInteract(@NotNull PlayerEntityInteractEvent playerEntityInteractEvent) { | ||||
|         Room room = (Room) instance; | ||||
|  | ||||
|         if(playerEntityInteractEvent.getPlayer() != room.getOwner()) { | ||||
|             abstractVillagerMeta.setHeadShakeTimer(20); | ||||
|  | ||||
|             new ChatMessage(Icon.ERROR).appendStatic("Only the room leader can start games!").indent(1).newLine() | ||||
|                     .appendStatic("current leader: ").appendStatic(room.getOwner().getUsername()) | ||||
|                     .send(playerEntityInteractEvent.getPlayer()); | ||||
|  | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         playerEntityInteractEvent.getPlayer().openInventory(new MinigameTypeSelectInventory()); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,11 @@ | ||||
| package eu.mhsl.minenet.minigames.instance.room.inventory; | ||||
|  | ||||
| import eu.mhsl.minenet.minigames.shared.inventory.InteractableInventory; | ||||
| import net.kyori.adventure.text.Component; | ||||
| import net.minestom.server.inventory.InventoryType; | ||||
|  | ||||
| public class BoardInventory extends InteractableInventory { | ||||
|     public BoardInventory() { | ||||
|         super(InventoryType.CHEST_3_ROW, Component.text("Brettspiele")); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,64 @@ | ||||
| package eu.mhsl.minenet.minigames.instance.room.inventory; | ||||
|  | ||||
| import eu.mhsl.minenet.minigames.instance.game.minigame.MinigameType; | ||||
| import eu.mhsl.minenet.minigames.instance.game.minigame.config.GameConfigurationInventory; | ||||
| import eu.mhsl.minenet.minigames.instance.game.minigame.config.GameFactory; | ||||
| import eu.mhsl.minenet.minigames.shared.inventory.InteractableInventory; | ||||
| import net.kyori.adventure.text.Component; | ||||
| import net.minestom.server.inventory.InventoryType; | ||||
| import net.minestom.server.item.ItemHideFlag; | ||||
| import net.minestom.server.item.ItemStack; | ||||
| import net.minestom.server.item.Material; | ||||
|  | ||||
| public class MinigameTypeSelectInventory extends InteractableInventory { | ||||
|     public MinigameTypeSelectInventory() { | ||||
|         super(InventoryType.CHEST_3_ROW, Component.text("MineNet Servernetzwerk")); | ||||
|  | ||||
|         int i = 0; | ||||
|         for (MinigameType minigameType : MinigameType.values()) { | ||||
|             GameFactory gameFactory = minigameType.getFactory(); | ||||
|  | ||||
|             setClickableItem( | ||||
|                     ItemStack.builder(gameFactory.symbol()) | ||||
|                             .displayName(gameFactory.name()) | ||||
|                             .lore(gameFactory.description()) | ||||
|                             .meta(metaBuilder -> metaBuilder.hideFlag(ItemHideFlag.HIDE_ATTRIBUTES)) | ||||
|                             .build(), | ||||
|                     i, | ||||
|                     itemClick -> itemClick.getPlayer().openInventory(new GameConfigurationInventory(gameFactory)) | ||||
|             ); | ||||
|             i++; | ||||
|         } | ||||
|  | ||||
| //        setClickableItem( | ||||
| //                ItemStack | ||||
| //                        .builder(Material.IRON_SWORD) | ||||
| //                        .displayName(Component.text("PVP Spiele")) | ||||
| //                        .lore(Component.text("Player versus Player")) | ||||
| //                        .meta(metaBuilder -> metaBuilder.hideFlag(ItemHideFlag.HIDE_ATTRIBUTES)) | ||||
| //                        .build(), | ||||
| //                11, | ||||
| //                itemClick -> itemClick.getPlayer().openInventory(new PvpInventory()) | ||||
| //        ); | ||||
| // | ||||
| //        setClickableItem( | ||||
| //                ItemStack | ||||
| //                        .builder(Material.ZOMBIE_HEAD) | ||||
| //                        .displayName(Component.text("PVE Arenen")) | ||||
| //                        .lore(Component.text("Player versus Entity")) | ||||
| //                        .build(), | ||||
| //                13, | ||||
| //                itemClick -> itemClick.getPlayer().openInventory(new PveInventory()) | ||||
| //        ); | ||||
| // | ||||
| //        setClickableItem( | ||||
| //                ItemStack | ||||
| //                        .builder(Material.BRICK_SLAB) | ||||
| //                        .displayName(Component.text("Brettspiele")) | ||||
| //                        .lore(Component.text("Bekannte Brettspieler aller Art")) | ||||
| //                        .build(), | ||||
| //                15, | ||||
| //                itemClick -> itemClick.getPlayer().openInventory(new BoardInventory()) | ||||
| //        ); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,41 @@ | ||||
| package eu.mhsl.minenet.minigames.instance.room.inventory; | ||||
|  | ||||
| import eu.mhsl.minenet.minigames.instance.game.minigame.config.GameConfigurationInventory; | ||||
| import eu.mhsl.minenet.minigames.instance.game.minigame.types.minerun.MinerunFactory; | ||||
| import eu.mhsl.minenet.minigames.shared.inventory.InteractableInventory; | ||||
| import eu.mhsl.minenet.minigames.instance.game.minigame.types.deathcube.DeathcubeFactory; | ||||
| import eu.mhsl.minenet.minigames.instance.game.minigame.types.trafficlightrace.TrafficLightRaceFactory; | ||||
| import net.kyori.adventure.text.Component; | ||||
| import net.minestom.server.inventory.InventoryType; | ||||
| import net.minestom.server.item.ItemStack; | ||||
| import net.minestom.server.item.Material; | ||||
|  | ||||
| public class PveInventory extends InteractableInventory { | ||||
|     public PveInventory() { | ||||
|         super(InventoryType.CHEST_3_ROW, Component.text("PVE")); | ||||
|  | ||||
|         setClickableItem( | ||||
|                 ItemStack.builder(Material.LIGHT_WEIGHTED_PRESSURE_PLATE).displayName(Component.text("Minerun")).lore(Component.text("Jump between ground mines to the finish")).build(), | ||||
|                 0, | ||||
|                 itemClick -> { | ||||
|                     itemClick.getPlayer().openInventory(new GameConfigurationInventory(new MinerunFactory())); | ||||
|                 } | ||||
|         ); | ||||
|  | ||||
|         setClickableItem( | ||||
|                 ItemStack.builder(Material.YELLOW_WOOL).displayName(Component.text("Ampelrennen")).build(), | ||||
|                 1, | ||||
|                 itemClick -> { | ||||
|                     itemClick.getPlayer().openInventory(new GameConfigurationInventory(new TrafficLightRaceFactory())); | ||||
|                 } | ||||
|         ); | ||||
|  | ||||
|         setClickableItem( | ||||
|                 ItemStack.builder(Material.RED_WOOL).displayName(Component.text("Deathcube")).build(), | ||||
|                 2, | ||||
|                 itemClick -> { | ||||
|                     itemClick.getPlayer().openInventory(new GameConfigurationInventory(new DeathcubeFactory())); | ||||
|                 } | ||||
|         ); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,27 @@ | ||||
| package eu.mhsl.minenet.minigames.instance.room.inventory; | ||||
|  | ||||
| import eu.mhsl.minenet.minigames.instance.game.minigame.config.GameConfigurationInventory; | ||||
| import eu.mhsl.minenet.minigames.instance.game.minigame.types.stickfight.StickFightFactory; | ||||
| import eu.mhsl.minenet.minigames.shared.inventory.InteractableInventory; | ||||
| import net.kyori.adventure.text.Component; | ||||
| import net.minestom.server.entity.Player; | ||||
| import net.minestom.server.inventory.InventoryType; | ||||
| import net.minestom.server.inventory.click.ClickType; | ||||
| import net.minestom.server.inventory.condition.InventoryConditionResult; | ||||
| import net.minestom.server.item.ItemStack; | ||||
| import net.minestom.server.item.Material; | ||||
|  | ||||
| public class PvpInventory extends InteractableInventory { | ||||
|     public PvpInventory() { | ||||
|         super(InventoryType.CHEST_6_ROW, Component.text("PVP")); | ||||
|  | ||||
|         setClickableItem(ItemStack.of(Material.GOLD_INGOT), 4, itemClick -> { | ||||
|             itemClick.getPlayer().openInventory(new GameConfigurationInventory(new StickFightFactory())); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected void onClick(Player player, int slot, ClickType clickType, InventoryConditionResult inventoryConditionResult) { | ||||
|         super.onClick(player, slot, clickType, inventoryConditionResult); | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user