Initial commit
This commit is contained in:
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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user