Compare commits
21 Commits
develop-fa
...
develop-tu
Author | SHA1 | Date | |
---|---|---|---|
d5910b4b54 | |||
ec76dd5c85 | |||
84de61388e | |||
dece9c13b7 | |||
39fb7f4956 | |||
75314748da | |||
61aa7543be | |||
2fac287e1e | |||
2a6f2f2a44 | |||
382d850605 | |||
a49b3b20cc | |||
abf907af24 | |||
8bd0ab1974 | |||
2c92553a8a | |||
f26c3a9e6d | |||
81524cfecf | |||
f2fc4835c3 | |||
abcb23d96a | |||
eabbb312b9 | |||
d98cebd86f | |||
c87d318421 |
@@ -2,7 +2,6 @@ package eu.mhsl.minenet.minigames.instance.game;
|
|||||||
|
|
||||||
import eu.mhsl.minenet.minigames.instance.game.stateless.config.GameFactory;
|
import eu.mhsl.minenet.minigames.instance.game.stateless.config.GameFactory;
|
||||||
import eu.mhsl.minenet.minigames.instance.game.stateless.types.anvilRun.AnvilRunFactory;
|
import eu.mhsl.minenet.minigames.instance.game.stateless.types.anvilRun.AnvilRunFactory;
|
||||||
import eu.mhsl.minenet.minigames.instance.game.stateless.types.blockBreakRace.BlockBreakRaceFactory;
|
|
||||||
import eu.mhsl.minenet.minigames.instance.game.stateless.types.bowSpleef.BowSpleefFactory;
|
import eu.mhsl.minenet.minigames.instance.game.stateless.types.bowSpleef.BowSpleefFactory;
|
||||||
import eu.mhsl.minenet.minigames.instance.game.stateless.types.elytraRace.ElytraRaceFactory;
|
import eu.mhsl.minenet.minigames.instance.game.stateless.types.elytraRace.ElytraRaceFactory;
|
||||||
import eu.mhsl.minenet.minigames.instance.game.stateless.types.backrooms.BackroomsFactory;
|
import eu.mhsl.minenet.minigames.instance.game.stateless.types.backrooms.BackroomsFactory;
|
||||||
@@ -20,6 +19,7 @@ import eu.mhsl.minenet.minigames.instance.game.stateless.types.sumo.SumoFactory;
|
|||||||
import eu.mhsl.minenet.minigames.instance.game.stateless.types.tntrun.TntRunFactory;
|
import eu.mhsl.minenet.minigames.instance.game.stateless.types.tntrun.TntRunFactory;
|
||||||
import eu.mhsl.minenet.minigames.instance.game.stateless.types.towerdefense.TowerdefenseFactory;
|
import eu.mhsl.minenet.minigames.instance.game.stateless.types.towerdefense.TowerdefenseFactory;
|
||||||
import eu.mhsl.minenet.minigames.instance.game.stateless.types.trafficlightrace.TrafficLightRaceFactory;
|
import eu.mhsl.minenet.minigames.instance.game.stateless.types.trafficlightrace.TrafficLightRaceFactory;
|
||||||
|
import eu.mhsl.minenet.minigames.instance.game.stateless.types.turtleGame.TurtleGameFactory;
|
||||||
|
|
||||||
public enum GameList {
|
public enum GameList {
|
||||||
DEATHCUBE(new DeathcubeFactory(), GameType.JUMPNRUN),
|
DEATHCUBE(new DeathcubeFactory(), GameType.JUMPNRUN),
|
||||||
@@ -30,6 +30,7 @@ public enum GameList {
|
|||||||
BEDWARS(new BedwarsFactory(), GameType.PROTOTYPE),
|
BEDWARS(new BedwarsFactory(), GameType.PROTOTYPE),
|
||||||
BACKROOMS(new BackroomsFactory(), GameType.PROTOTYPE),
|
BACKROOMS(new BackroomsFactory(), GameType.PROTOTYPE),
|
||||||
BOWSPLEEF(new BowSpleefFactory(), GameType.PROTOTYPE),
|
BOWSPLEEF(new BowSpleefFactory(), GameType.PROTOTYPE),
|
||||||
|
TURTLEGAME(new TurtleGameFactory(), GameType.PROTOTYPE),
|
||||||
TETRIS(new TetrisFactory(), GameType.OTHER),
|
TETRIS(new TetrisFactory(), GameType.OTHER),
|
||||||
TNTRUN(new TntRunFactory(), GameType.OTHER),
|
TNTRUN(new TntRunFactory(), GameType.OTHER),
|
||||||
ANVILRUN(new AnvilRunFactory(), GameType.PVE),
|
ANVILRUN(new AnvilRunFactory(), GameType.PVE),
|
||||||
@@ -39,8 +40,7 @@ public enum GameList {
|
|||||||
JUMPDIVE(new JumpDiveFactory(), GameType.JUMPNRUN),
|
JUMPDIVE(new JumpDiveFactory(), GameType.JUMPNRUN),
|
||||||
SUMO(new SumoFactory(), GameType.PVP),
|
SUMO(new SumoFactory(), GameType.PVP),
|
||||||
HIGHGROUND(new HighGroundFactory(), GameType.PVP),
|
HIGHGROUND(new HighGroundFactory(), GameType.PVP),
|
||||||
FASTBRIDGE(new FastbridgeFactory(), GameType.OTHER),
|
FASTBRIDGE(new FastbridgeFactory(), GameType.OTHER);
|
||||||
BLOCKBREAKRACE(new BlockBreakRaceFactory(), GameType.OTHER);
|
|
||||||
|
|
||||||
private final GameFactory factory;
|
private final GameFactory factory;
|
||||||
private final GameType type;
|
private final GameType type;
|
||||||
|
@@ -1,79 +0,0 @@
|
|||||||
package eu.mhsl.minenet.minigames.instance.game.stateless.types.blockBreakRace;
|
|
||||||
|
|
||||||
import eu.mhsl.minenet.minigames.instance.Dimension;
|
|
||||||
import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame;
|
|
||||||
import eu.mhsl.minenet.minigames.score.FirstWinsScore;
|
|
||||||
import net.minestom.server.coordinate.Pos;
|
|
||||||
import net.minestom.server.entity.GameMode;
|
|
||||||
import net.minestom.server.entity.Player;
|
|
||||||
import net.minestom.server.event.player.PlayerBlockBreakEvent;
|
|
||||||
import net.minestom.server.event.player.PlayerMoveEvent;
|
|
||||||
import net.minestom.server.inventory.PlayerInventory;
|
|
||||||
import net.minestom.server.item.ItemStack;
|
|
||||||
import net.minestom.server.item.Material;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class BlockBreakRace extends StatelessGame {
|
|
||||||
private int spawnCount = 0;
|
|
||||||
private final int height;
|
|
||||||
|
|
||||||
public BlockBreakRace(int height) {
|
|
||||||
super(Dimension.OVERWORLD.key, "blockBreakRace", new FirstWinsScore());
|
|
||||||
this.height = height;
|
|
||||||
this.setGenerator(new BlockBreakRaceGenerator(height));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean onPlayerJoin(Player p) {
|
|
||||||
PlayerInventory inv = p.getInventory();
|
|
||||||
inv.addItemStack(ItemStack.of(Material.DIAMOND_PICKAXE));
|
|
||||||
inv.addItemStack(ItemStack.of(Material.DIAMOND_AXE));
|
|
||||||
inv.addItemStack(ItemStack.of(Material.DIAMOND_SHOVEL));
|
|
||||||
return super.onPlayerJoin(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onStart() {
|
|
||||||
this.getPlayers().forEach(player -> player.setGameMode(GameMode.SURVIVAL));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onBlockBreak(@NotNull PlayerBlockBreakEvent event) {
|
|
||||||
List<Material> allowedMaterials = List.of(Material.STONE, Material.OAK_PLANKS, Material.DIRT);
|
|
||||||
if(!allowedMaterials.contains(event.getBlock().registry().material())) event.setCancelled(true);
|
|
||||||
if(this.isBeforeBeginning) event.setCancelled(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPlayerMove(@NotNull PlayerMoveEvent playerMoveEvent) {
|
|
||||||
if(this.isBeforeBeginning) return;
|
|
||||||
if(playerMoveEvent.getNewPosition().y() < BlockBreakRaceGenerator.BOTTOM_Y) {
|
|
||||||
Player player = playerMoveEvent.getPlayer();
|
|
||||||
this.getScore().insertResult(player);
|
|
||||||
player.setGameMode(GameMode.SPECTATOR);
|
|
||||||
player.getInventory().clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Pos getSpawn() {
|
|
||||||
int idx = this.spawnCount++;
|
|
||||||
|
|
||||||
int cols = BlockBreakRaceGenerator.ROW_OFFSETS_X.length;
|
|
||||||
int rows = BlockBreakRaceGenerator.ROW_OFFSETS_Z.length;
|
|
||||||
int perChunk = cols * rows;
|
|
||||||
int zChunk = idx / perChunk;
|
|
||||||
|
|
||||||
int gridIndex = idx % perChunk;
|
|
||||||
int xIndex = gridIndex % cols;
|
|
||||||
int zIndex = gridIndex / cols;
|
|
||||||
|
|
||||||
int localX = BlockBreakRaceGenerator.ROW_OFFSETS_X[xIndex];
|
|
||||||
int localZ = BlockBreakRaceGenerator.ROW_OFFSETS_Z[zIndex];
|
|
||||||
|
|
||||||
int absZ = (zChunk * 16) + localZ;
|
|
||||||
return new Pos(localX, BlockBreakRaceGenerator.BOTTOM_Y + this.height + 1, absZ).add(0.5);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,67 +0,0 @@
|
|||||||
package eu.mhsl.minenet.minigames.instance.game.stateless.types.blockBreakRace;
|
|
||||||
|
|
||||||
import eu.mhsl.minenet.minigames.world.generator.featureEnriched.ValeGenerator;
|
|
||||||
import eu.mhsl.minenet.minigames.world.generator.terrain.BaseGenerator;
|
|
||||||
import net.minestom.server.coordinate.Pos;
|
|
||||||
import net.minestom.server.instance.block.Block;
|
|
||||||
import net.minestom.server.instance.generator.GenerationUnit;
|
|
||||||
|
|
||||||
import java.util.Random;
|
|
||||||
import java.util.concurrent.ThreadLocalRandom;
|
|
||||||
|
|
||||||
public class BlockBreakRaceGenerator extends BaseGenerator {
|
|
||||||
public static final int BOTTOM_Y = 50;
|
|
||||||
public final int TOP_Y;
|
|
||||||
public static final int[] ROW_OFFSETS_X = {4, 8, 12};
|
|
||||||
public static final int[] ROW_OFFSETS_Z = {4, 8, 12};
|
|
||||||
|
|
||||||
private static final Block[] FILL_BLOCKS = {
|
|
||||||
Block.STONE,
|
|
||||||
Block.DIRT,
|
|
||||||
Block.OAK_PLANKS
|
|
||||||
};
|
|
||||||
|
|
||||||
private final Random random = ThreadLocalRandom.current();
|
|
||||||
|
|
||||||
public BlockBreakRaceGenerator(int height) {
|
|
||||||
this.TOP_Y = BOTTOM_Y + height;
|
|
||||||
ValeGenerator vale = new ValeGenerator();
|
|
||||||
vale.setXShiftMultiplier(i -> 0.5d);
|
|
||||||
vale.setHeightNoiseMultiplier(i -> 2);
|
|
||||||
vale.setXShiftOffset(i -> 40d);
|
|
||||||
this.addMixIn(vale);
|
|
||||||
|
|
||||||
this.addMixIn(unit -> {
|
|
||||||
if(unit.absoluteStart().chunkX() != 0) return;
|
|
||||||
|
|
||||||
for (int localX : ROW_OFFSETS_X) {
|
|
||||||
for (int localZ : ROW_OFFSETS_Z) {
|
|
||||||
final int absZ = unit.absoluteStart().blockZ() + localZ;
|
|
||||||
this.placeTube(unit, localX, absZ);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void placeTube(GenerationUnit unit, int x, int z) {
|
|
||||||
for (int y = BOTTOM_Y; y < this.TOP_Y; y++) {
|
|
||||||
Block fill = FILL_BLOCKS[this.random.nextInt(FILL_BLOCKS.length)];
|
|
||||||
unit.modifier().fill(
|
|
||||||
new Pos(x, y, z),
|
|
||||||
new Pos(x, y, z).add(1),
|
|
||||||
fill
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int dx = -1; dx <= 1; dx++) {
|
|
||||||
for (int dz = -1; dz <= 1; dz++) {
|
|
||||||
if (dx == 0 && dz == 0) continue; // Zentrum überspringen
|
|
||||||
unit.modifier().fill(
|
|
||||||
new Pos(x + dx, BOTTOM_Y, z + dz),
|
|
||||||
new Pos(x + dx, this.TOP_Y + 3, z + dz).add(1),
|
|
||||||
Block.BARRIER
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -3,8 +3,6 @@ package eu.mhsl.minenet.minigames.instance.game.stateless.types.bowSpleef;
|
|||||||
import eu.mhsl.minenet.minigames.instance.game.Game;
|
import eu.mhsl.minenet.minigames.instance.game.Game;
|
||||||
import eu.mhsl.minenet.minigames.instance.game.stateless.config.GameFactory;
|
import eu.mhsl.minenet.minigames.instance.game.stateless.config.GameFactory;
|
||||||
import eu.mhsl.minenet.minigames.instance.game.stateless.config.Option;
|
import eu.mhsl.minenet.minigames.instance.game.stateless.config.Option;
|
||||||
import eu.mhsl.minenet.minigames.instance.game.stateless.config.restriction.RestrictionHandler;
|
|
||||||
import eu.mhsl.minenet.minigames.instance.game.stateless.config.restriction.common.MinimalPlayeramountGameRestriction;
|
|
||||||
import eu.mhsl.minenet.minigames.instance.room.Room;
|
import eu.mhsl.minenet.minigames.instance.room.Room;
|
||||||
import eu.mhsl.minenet.minigames.message.component.TranslatedComponent;
|
import eu.mhsl.minenet.minigames.message.component.TranslatedComponent;
|
||||||
import net.minestom.server.item.Material;
|
import net.minestom.server.item.Material;
|
||||||
@@ -31,10 +29,4 @@ public class BowSpleefFactory implements GameFactory {
|
|||||||
public Game manufacture(Room parent, Map<String, Option<?>> configuration) throws Exception {
|
public Game manufacture(Room parent, Map<String, Option<?>> configuration) throws Exception {
|
||||||
return new BowSpleef().setParent(parent);
|
return new BowSpleef().setParent(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public RestrictionHandler globalRestrictions() {
|
|
||||||
return new RestrictionHandler()
|
|
||||||
.addRestriction(new MinimalPlayeramountGameRestriction(2));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -8,7 +8,7 @@ import eu.mhsl.minenet.minigames.world.BlockPallet;
|
|||||||
import eu.mhsl.minenet.minigames.world.generator.terrain.CircularPlateTerrainGenerator;
|
import eu.mhsl.minenet.minigames.world.generator.terrain.CircularPlateTerrainGenerator;
|
||||||
import io.github.togar2.pvp.feature.CombatFeatures;
|
import io.github.togar2.pvp.feature.CombatFeatures;
|
||||||
import net.minestom.server.coordinate.Pos;
|
import net.minestom.server.coordinate.Pos;
|
||||||
import net.minestom.server.entity.GameMode;
|
import net.minestom.server.entity.Player;
|
||||||
import net.minestom.server.event.player.PlayerMoveEvent;
|
import net.minestom.server.event.player.PlayerMoveEvent;
|
||||||
import net.minestom.server.instance.batch.AbsoluteBlockBatch;
|
import net.minestom.server.instance.batch.AbsoluteBlockBatch;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@@ -69,9 +69,7 @@ class Deathcube extends StatelessGame {
|
|||||||
playerMoveEvent.setCancelled(true);
|
playerMoveEvent.setCancelled(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(playerMoveEvent.getNewPosition().y() <= height) return;
|
if(playerMoveEvent.getNewPosition().y() > height) getScore().insertResult(playerMoveEvent.getPlayer());
|
||||||
getScore().insertResult(playerMoveEvent.getPlayer());
|
|
||||||
playerMoveEvent.getPlayer().setGameMode(GameMode.SPECTATOR);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -33,7 +33,6 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Random;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
|
||||||
@@ -184,8 +183,7 @@ public class ElytraRace extends StatelessGame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Point getRingPositionAtZ(int z) {
|
private Point getRingPositionAtZ(int z) {
|
||||||
Random random = new Random(this.hashCode() + z);
|
return new Pos(vale.getXShiftAtZ(z), -45, z);
|
||||||
return new Pos(vale.getXShiftAtZ(z), -45 + random.nextInt(-5, 15), z);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private CompletableFuture<Void> generateRing(int zPos) {
|
private CompletableFuture<Void> generateRing(int zPos) {
|
||||||
|
@@ -5,8 +5,6 @@ import eu.mhsl.minenet.minigames.instance.game.stateless.config.ConfigManager;
|
|||||||
import eu.mhsl.minenet.minigames.instance.game.stateless.config.GameFactory;
|
import eu.mhsl.minenet.minigames.instance.game.stateless.config.GameFactory;
|
||||||
import eu.mhsl.minenet.minigames.instance.game.stateless.config.Option;
|
import eu.mhsl.minenet.minigames.instance.game.stateless.config.Option;
|
||||||
import eu.mhsl.minenet.minigames.instance.game.stateless.config.common.NumericOption;
|
import eu.mhsl.minenet.minigames.instance.game.stateless.config.common.NumericOption;
|
||||||
import eu.mhsl.minenet.minigames.instance.game.stateless.config.restriction.RestrictionHandler;
|
|
||||||
import eu.mhsl.minenet.minigames.instance.game.stateless.config.restriction.common.MinimalPlayeramountGameRestriction;
|
|
||||||
import eu.mhsl.minenet.minigames.instance.room.Room;
|
import eu.mhsl.minenet.minigames.instance.room.Room;
|
||||||
import eu.mhsl.minenet.minigames.message.component.TranslatedComponent;
|
import eu.mhsl.minenet.minigames.message.component.TranslatedComponent;
|
||||||
import net.minestom.server.item.Material;
|
import net.minestom.server.item.Material;
|
||||||
@@ -40,10 +38,4 @@ public class HighGroundFactory implements GameFactory {
|
|||||||
public Game manufacture(Room parent, Map<String, Option<?>> configuration) throws Exception {
|
public Game manufacture(Room parent, Map<String, Option<?>> configuration) throws Exception {
|
||||||
return new HighGround(configuration.get("radius").getAsInt(), configuration.get("seconds").getAsInt()).setParent(parent);
|
return new HighGround(configuration.get("radius").getAsInt(), configuration.get("seconds").getAsInt()).setParent(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public RestrictionHandler globalRestrictions() {
|
|
||||||
return new RestrictionHandler()
|
|
||||||
.addRestriction(new MinimalPlayeramountGameRestriction(2));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -9,7 +9,6 @@ import eu.mhsl.minenet.minigames.world.BlockPallet;
|
|||||||
import eu.mhsl.minenet.minigames.world.generator.terrain.CircularPlateTerrainGenerator;
|
import eu.mhsl.minenet.minigames.world.generator.terrain.CircularPlateTerrainGenerator;
|
||||||
import net.minestom.server.coordinate.Pos;
|
import net.minestom.server.coordinate.Pos;
|
||||||
import net.minestom.server.entity.GameMode;
|
import net.minestom.server.entity.GameMode;
|
||||||
import net.minestom.server.event.player.PlayerBlockBreakEvent;
|
|
||||||
import net.minestom.server.event.player.PlayerMoveEvent;
|
import net.minestom.server.event.player.PlayerMoveEvent;
|
||||||
import net.minestom.server.event.player.PlayerStartDiggingEvent;
|
import net.minestom.server.event.player.PlayerStartDiggingEvent;
|
||||||
import net.minestom.server.instance.batch.AbsoluteBlockBatch;
|
import net.minestom.server.instance.batch.AbsoluteBlockBatch;
|
||||||
@@ -78,15 +77,6 @@ public class Spleef extends StatelessGame {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onBlockBreak(@NotNull PlayerBlockBreakEvent event) {
|
|
||||||
if(!isRunning) {
|
|
||||||
event.setCancelled(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setBlock(event.getBlockPosition(), Block.AIR);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void destroyBlock(PlayerStartDiggingEvent event) {
|
private void destroyBlock(PlayerStartDiggingEvent event) {
|
||||||
if(!isRunning) return;
|
if(!isRunning) return;
|
||||||
setBlock(event.getBlockPosition(), Block.AIR);
|
setBlock(event.getBlockPosition(), Block.AIR);
|
||||||
|
@@ -2,7 +2,7 @@ package eu.mhsl.minenet.minigames.instance.game.stateless.types.stickfight;
|
|||||||
|
|
||||||
import eu.mhsl.minenet.minigames.instance.Dimension;
|
import eu.mhsl.minenet.minigames.instance.Dimension;
|
||||||
import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame;
|
import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame;
|
||||||
import eu.mhsl.minenet.minigames.score.LowestPointsWinScore;
|
import eu.mhsl.minenet.minigames.score.LastWinsScore;
|
||||||
import eu.mhsl.minenet.minigames.world.generator.terrain.CircularPlateTerrainGenerator;
|
import eu.mhsl.minenet.minigames.world.generator.terrain.CircularPlateTerrainGenerator;
|
||||||
import io.github.togar2.pvp.events.FinalAttackEvent;
|
import io.github.togar2.pvp.events.FinalAttackEvent;
|
||||||
import io.github.togar2.pvp.feature.CombatFeatures;
|
import io.github.togar2.pvp.feature.CombatFeatures;
|
||||||
@@ -13,17 +13,15 @@ import net.minestom.server.instance.block.Block;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.WeakHashMap;
|
import java.util.WeakHashMap;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
public class Stickfight extends StatelessGame {
|
public class Stickfight extends StatelessGame {
|
||||||
private final double radius = 20;
|
private final double radius = 20;
|
||||||
private final WeakHashMap<Player, Pos> spawnPoints = new WeakHashMap<>();
|
private final WeakHashMap<Player, Pos> spawnPoints = new WeakHashMap<>();
|
||||||
private final Map<Player, Integer> scoreMap = new WeakHashMap<>();
|
|
||||||
|
|
||||||
public Stickfight() {
|
public Stickfight() {
|
||||||
super(Dimension.OVERWORLD.key, "Stickfight", new LowestPointsWinScore());
|
super(Dimension.OVERWORLD.key, "Stickfight", new LastWinsScore());
|
||||||
|
|
||||||
eventNode().addChild(
|
eventNode().addChild(
|
||||||
CombatFeatures.empty()
|
CombatFeatures.empty()
|
||||||
@@ -68,11 +66,6 @@ public class Stickfight extends StatelessGame {
|
|||||||
super.start();
|
super.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onStop() {
|
|
||||||
this.scoreMap.forEach((player, score) -> getScore().insertResult(player, score));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void generateBridge(int startX, int startY, int startZ) {
|
private void generateBridge(int startX, int startY, int startZ) {
|
||||||
int steps = (int) (radius * 1.5);
|
int steps = (int) (radius * 1.5);
|
||||||
for (int i = 0; i < steps; i++) {
|
for (int i = 0; i < steps; i++) {
|
||||||
@@ -85,22 +78,19 @@ public class Stickfight extends StatelessGame {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPlayerMove(@NotNull PlayerMoveEvent playerMoveEvent) {
|
protected void onPlayerMove(@NotNull PlayerMoveEvent playerMoveEvent) {
|
||||||
Player player = playerMoveEvent.getPlayer();
|
if(!spawnPoints.containsKey(playerMoveEvent.getPlayer())) {
|
||||||
if(!spawnPoints.containsKey(player)) {
|
|
||||||
playerMoveEvent.setCancelled(true);
|
playerMoveEvent.setCancelled(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isBeforeBeginning) {
|
if(isBeforeBeginning) {
|
||||||
if(spawnPoints.get(player).distance(playerMoveEvent.getNewPosition()) < 1) return;
|
if(spawnPoints.get(playerMoveEvent.getPlayer()).distance(playerMoveEvent.getNewPosition()) < 1) return;
|
||||||
playerMoveEvent.setCancelled(true);
|
playerMoveEvent.setCancelled(true);
|
||||||
player.teleport(spawnPoints.get(player));
|
playerMoveEvent.getPlayer().teleport(spawnPoints.get(playerMoveEvent.getPlayer()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(playerMoveEvent.getNewPosition().y() < 40) {
|
if(playerMoveEvent.getNewPosition().y() < 40) {
|
||||||
player.teleport(spawnPoints.get(player));
|
playerMoveEvent.getPlayer().teleport(spawnPoints.get(playerMoveEvent.getPlayer()));
|
||||||
this.scoreMap.putIfAbsent(player, 0);
|
|
||||||
this.scoreMap.put(player, this.scoreMap.get(player) + 1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -5,8 +5,6 @@ import eu.mhsl.minenet.minigames.instance.game.stateless.config.ConfigManager;
|
|||||||
import eu.mhsl.minenet.minigames.instance.game.stateless.config.GameFactory;
|
import eu.mhsl.minenet.minigames.instance.game.stateless.config.GameFactory;
|
||||||
import eu.mhsl.minenet.minigames.instance.game.stateless.config.Option;
|
import eu.mhsl.minenet.minigames.instance.game.stateless.config.Option;
|
||||||
import eu.mhsl.minenet.minigames.instance.game.stateless.config.common.NumericOption;
|
import eu.mhsl.minenet.minigames.instance.game.stateless.config.common.NumericOption;
|
||||||
import eu.mhsl.minenet.minigames.instance.game.stateless.config.restriction.RestrictionHandler;
|
|
||||||
import eu.mhsl.minenet.minigames.instance.game.stateless.config.restriction.common.MinimalPlayeramountGameRestriction;
|
|
||||||
import eu.mhsl.minenet.minigames.instance.room.Room;
|
import eu.mhsl.minenet.minigames.instance.room.Room;
|
||||||
import eu.mhsl.minenet.minigames.message.component.TranslatedComponent;
|
import eu.mhsl.minenet.minigames.message.component.TranslatedComponent;
|
||||||
import net.minestom.server.item.Material;
|
import net.minestom.server.item.Material;
|
||||||
@@ -40,10 +38,4 @@ public class SumoFactory implements GameFactory {
|
|||||||
public Game manufacture(Room parent, Map<String, Option<?>> configuration) throws Exception {
|
public Game manufacture(Room parent, Map<String, Option<?>> configuration) throws Exception {
|
||||||
return new Sumo(configuration.get("radius").getAsInt(), configuration.get("health").getAsInt(), configuration.get("seconds").getAsInt()).setParent(parent);
|
return new Sumo(configuration.get("radius").getAsInt(), configuration.get("health").getAsInt(), configuration.get("seconds").getAsInt()).setParent(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public RestrictionHandler globalRestrictions() {
|
|
||||||
return new RestrictionHandler()
|
|
||||||
.addRestriction(new MinimalPlayeramountGameRestriction(2));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -156,7 +156,6 @@ class TrafficLightRace extends StatelessGame {
|
|||||||
@Override
|
@Override
|
||||||
protected void onPlayerMove(@NotNull PlayerMoveEvent playerMoveEvent) {
|
protected void onPlayerMove(@NotNull PlayerMoveEvent playerMoveEvent) {
|
||||||
if(isBeforeBeginning) return;
|
if(isBeforeBeginning) return;
|
||||||
if(getScore().hasResult(playerMoveEvent.getPlayer())) return;
|
|
||||||
|
|
||||||
if(phase.equals(LightPhase.RED) && playerMoveEvent.getNewPosition().z()-0.01 > playerMoveEvent.getPlayer().getPosition().z()) {
|
if(phase.equals(LightPhase.RED) && playerMoveEvent.getNewPosition().z()-0.01 > playerMoveEvent.getPlayer().getPosition().z()) {
|
||||||
playerMoveEvent.getPlayer().setVelocity(new Vec(0, 8, -15));
|
playerMoveEvent.getPlayer().setVelocity(new Vec(0, 8, -15));
|
||||||
|
@@ -0,0 +1,263 @@
|
|||||||
|
package eu.mhsl.minenet.minigames.instance.game.stateless.types.turtleGame;
|
||||||
|
|
||||||
|
import eu.mhsl.minenet.minigames.instance.Dimension;
|
||||||
|
import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame;
|
||||||
|
import eu.mhsl.minenet.minigames.instance.game.stateless.types.turtleGame.gameObjects.Turtle;
|
||||||
|
import eu.mhsl.minenet.minigames.score.PointsWinScore;
|
||||||
|
import net.kyori.adventure.sound.Sound;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
import net.kyori.adventure.text.format.TextDecoration;
|
||||||
|
import net.minestom.server.MinecraftServer;
|
||||||
|
import net.minestom.server.coordinate.Pos;
|
||||||
|
import net.minestom.server.entity.*;
|
||||||
|
import net.minestom.server.entity.metadata.other.FallingBlockMeta;
|
||||||
|
import net.minestom.server.event.player.PlayerStartSneakingEvent;
|
||||||
|
import net.minestom.server.event.player.PlayerStopSneakingEvent;
|
||||||
|
import net.minestom.server.event.player.PlayerTickEvent;
|
||||||
|
import net.minestom.server.instance.block.Block;
|
||||||
|
import net.minestom.server.item.ItemStack;
|
||||||
|
import net.minestom.server.item.Material;
|
||||||
|
import net.minestom.server.network.packet.server.play.ParticlePacket;
|
||||||
|
import net.minestom.server.particle.Particle;
|
||||||
|
import net.minestom.server.sound.SoundEvent;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
class TurtleGame extends StatelessGame {
|
||||||
|
private final int radius;
|
||||||
|
private final Map<Player, Turtle> turtlePlayerMap = new WeakHashMap<>();
|
||||||
|
private final ArrayList<Entity> snacks = new ArrayList<>();
|
||||||
|
private final ArrayList<Entity> bombs = new ArrayList<>();
|
||||||
|
private final Block snackBlock = Block.SUNFLOWER.withProperty("half", "upper");
|
||||||
|
private final double startSpeed;
|
||||||
|
|
||||||
|
public TurtleGame(int radius, int startSpeed) {
|
||||||
|
super(Dimension.OVERWORLD.key, "Turtle Game", new PointsWinScore());
|
||||||
|
this.radius = radius;
|
||||||
|
this.startSpeed = startSpeed;
|
||||||
|
|
||||||
|
this.eventNode()
|
||||||
|
.addListener(PlayerTickEvent.class, this::onPlayerTick)
|
||||||
|
.addListener(PlayerStartSneakingEvent.class, this::onPlayerStartSneak)
|
||||||
|
.addListener(PlayerStopSneakingEvent.class, this::onPlayerStopSneak);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onLoad(@NotNull CompletableFuture<Void> callback) {
|
||||||
|
this.generatePlatform();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generatePlatform() {
|
||||||
|
for(int x = -this.radius - 1; x <= this.radius + 1; x++) {
|
||||||
|
for(int z = -this.radius - 1; z <= this.radius + 1; z++) {
|
||||||
|
double distance = new Pos(x, 0, z).distance(new Pos(0, 0, 0));
|
||||||
|
if(distance <= this.radius) {
|
||||||
|
boolean isEdge = this.radius - 1 < distance;
|
||||||
|
this.setBlock(x, 0, z, Block.SAND);
|
||||||
|
this.setBlock(x, 1, z, isEdge ? Block.STONE : Block.AIR);
|
||||||
|
this.setBlock(x, 2, z, isEdge ? Block.STONE_SLAB : Block.AIR);
|
||||||
|
} else {
|
||||||
|
this.setBlock(x, 0, z, Block.AIR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onPlayerStartSneak(@NotNull PlayerStartSneakingEvent event) {
|
||||||
|
Player p = event.getPlayer();
|
||||||
|
this.turtlePlayerMap.get(p).boostSpeed();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onPlayerStopSneak(@NotNull PlayerStopSneakingEvent event) {
|
||||||
|
Player p = event.getPlayer();
|
||||||
|
this.turtlePlayerMap.get(p).cancelBoost();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onPlayerTick(@NotNull PlayerTickEvent event) {
|
||||||
|
Player p = event.getPlayer();
|
||||||
|
if(p.getGameMode() == GameMode.SPECTATOR) return;
|
||||||
|
Turtle turtle = this.turtlePlayerMap.get(p);
|
||||||
|
turtle.adaptView();
|
||||||
|
if(this.isRunning()) {
|
||||||
|
turtle.move();
|
||||||
|
this.snacks.stream()
|
||||||
|
.filter(turtle::checkCollisionWithEntity)
|
||||||
|
.toList()
|
||||||
|
.forEach(snack -> {
|
||||||
|
this.eat(p, snack);
|
||||||
|
this.generateNewSnack();
|
||||||
|
if(this.turtlePlayerMap.get(p).getScore() % 5 == 0) {
|
||||||
|
this.generateNewBomb();
|
||||||
|
this.addSpeed(0.4, p);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.bombs.stream()
|
||||||
|
.filter(turtle::checkCollisionWithEntity)
|
||||||
|
.toList()
|
||||||
|
.forEach(bomb -> {
|
||||||
|
this.explode(p, bomb);
|
||||||
|
this.generateNewBombs(2);
|
||||||
|
this.addGlobalSpeed(0.3);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addSpeed(double amount, Player p) {
|
||||||
|
this.turtlePlayerMap.get(p).addSpeed(amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addGlobalSpeed(double amount) {
|
||||||
|
this.turtlePlayerMap.values().forEach(turtle -> turtle.addSpeed(amount));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void eat(Player p, Entity snack) {
|
||||||
|
p.playSound(Sound.sound(SoundEvent.ENTITY_GENERIC_EAT, Sound.Source.MASTER, 1f, 1f), snack.getPosition());
|
||||||
|
Material snackMaterial = this.snackBlock.registry().material();
|
||||||
|
if(snackMaterial == null) snackMaterial = Material.DIRT;
|
||||||
|
p.sendPacket(new ParticlePacket(Particle.ITEM.withItem(ItemStack.of(snackMaterial)), p.getPosition(), new Pos(0.5, 0.5, 0.5), 0, 8));
|
||||||
|
this.snacks.remove(snack);
|
||||||
|
snack.remove();
|
||||||
|
this.turtlePlayerMap.get(p).increaseScore();
|
||||||
|
this.turtlePlayerMap.get(p).increaseBoostChargeLevel(0.02f);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void explode(Player p, Entity bomb) {
|
||||||
|
this.letPlayerLoose(p);
|
||||||
|
p.playSound(Sound.sound(SoundEvent.ENTITY_GENERIC_EXPLODE, Sound.Source.MASTER, 2f, 1f), bomb.getPosition());
|
||||||
|
p.playSound(Sound.sound(SoundEvent.ENTITY_GENERIC_EXPLODE, Sound.Source.MASTER, 2f, 1f), bomb.getPosition());
|
||||||
|
p.sendPacket(new ParticlePacket(Particle.EXPLOSION, p.getPosition(), new Pos(0.5, 0.5, 0.5), 0, 8));
|
||||||
|
if(this.getLeftPlayers().size() == 1) this.setTimeLimit(10);
|
||||||
|
this.bombs.remove(bomb);
|
||||||
|
bomb.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void letPlayerLoose(Player p) {
|
||||||
|
p.setGameMode(GameMode.SPECTATOR);
|
||||||
|
p.setFlying(true);
|
||||||
|
this.turtlePlayerMap.get(p).destroy();
|
||||||
|
this.getScore().insertResult(p, this.turtlePlayerMap.get(p).getScore());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<Player> getLeftPlayers() {
|
||||||
|
return this.turtlePlayerMap.keySet().stream().filter(player -> !player.isFlying()).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean onPlayerJoin(Player p) {
|
||||||
|
this.turtlePlayerMap.putIfAbsent(p, new Turtle(p, this.startSpeed));
|
||||||
|
p.setLevel(this.turtlePlayerMap.get(p).getScore());
|
||||||
|
|
||||||
|
Turtle turtle = this.turtlePlayerMap.get(p);
|
||||||
|
MinecraftServer.getSchedulerManager().scheduleNextTick(turtle::spawnTurtle);
|
||||||
|
return super.onPlayerJoin(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPlayerLeave(Player p) {
|
||||||
|
Turtle turtle = this.turtlePlayerMap.get(p);
|
||||||
|
turtle.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Pos getSpawn() {
|
||||||
|
double theta = this.rnd.nextDouble() * 2 * Math.PI;
|
||||||
|
|
||||||
|
double spawnRadius = this.radius - 4;
|
||||||
|
double x = spawnRadius * Math.cos(theta);
|
||||||
|
double z = spawnRadius * Math.sin(theta);
|
||||||
|
|
||||||
|
return new Pos(x, 1, z).withLookAt(new Pos(0, 0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateNewSnacks(int count) {
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
this.generateNewSnack();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateNewSnack() {
|
||||||
|
Entity snack = new Entity(EntityType.FALLING_BLOCK);
|
||||||
|
FallingBlockMeta meta = (FallingBlockMeta) snack.getEntityMeta();
|
||||||
|
meta.setBlock(this.snackBlock.withProperty("half", "upper"));
|
||||||
|
meta.setCustomName(Component.text("Snack").color(NamedTextColor.WHITE));
|
||||||
|
meta.setCustomNameVisible(true);
|
||||||
|
snack.setInstance(this);
|
||||||
|
Pos spawnPosition = this.newSpawnPosition(snack);
|
||||||
|
if(spawnPosition == null) {
|
||||||
|
snack.remove();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
snack.teleport(spawnPosition);
|
||||||
|
this.snacks.add(snack);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateNewBombs(int count) {
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
this.generateNewBomb();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateNewBomb() {
|
||||||
|
Entity bomb = new Entity(EntityType.FALLING_BLOCK);
|
||||||
|
FallingBlockMeta meta = (FallingBlockMeta) bomb.getEntityMeta();
|
||||||
|
meta.setBlock(Block.TNT);
|
||||||
|
meta.setCustomName(Component.text("Bomb").color(NamedTextColor.RED).decorate(TextDecoration.BOLD));
|
||||||
|
meta.setCustomNameVisible(true);
|
||||||
|
bomb.setInstance(this);
|
||||||
|
Pos spawnPosition = this.newSpawnPosition(bomb, false);
|
||||||
|
if(spawnPosition == null) {
|
||||||
|
bomb.remove();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
bomb.teleport(spawnPosition);
|
||||||
|
this.bombs.add(bomb);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private Pos newSpawnPosition(Entity entity) {
|
||||||
|
return this.newSpawnPosition(entity, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private Pos newSpawnPosition(Entity entity, boolean nearPlayers) {
|
||||||
|
Pos spawnPosition;
|
||||||
|
int counter = 0;
|
||||||
|
boolean isInRadius, collides;
|
||||||
|
do {
|
||||||
|
if(counter > 200) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
int x = this.rnd.nextInt(-this.radius+2, this.radius-2);
|
||||||
|
int z = this.rnd.nextInt(-this.radius+2, this.radius-2);
|
||||||
|
spawnPosition = new Pos(x, 1, z).add(0.5, 0, 0.5);
|
||||||
|
Pos checkPosition = spawnPosition;
|
||||||
|
isInRadius = checkPosition.distance(0, 1, 0) < this.radius-2;
|
||||||
|
collides = this.getEntities().stream()
|
||||||
|
.filter(e -> !e.equals(entity))
|
||||||
|
.anyMatch(e -> entity.getBoundingBox().intersectBox(e.getPosition().sub(checkPosition), e.getBoundingBox()));
|
||||||
|
if(!collides && !nearPlayers) collides = this.turtlePlayerMap.values().stream()
|
||||||
|
.filter(turtle -> !turtle.equals(entity))
|
||||||
|
.anyMatch(turtle -> entity.getBoundingBox()
|
||||||
|
.growSymmetrically(turtle.getBombBorder(), 1, turtle.getBombBorder())
|
||||||
|
.intersectBox(turtle.getPosition().sub(checkPosition), turtle.getBoundingBox()));
|
||||||
|
counter++;
|
||||||
|
} while (!isInRadius || collides);
|
||||||
|
return spawnPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onStart() {
|
||||||
|
this.generateNewSnacks((int) Math.ceil(this.turtlePlayerMap.size() * 1.5));
|
||||||
|
this.generateNewBombs((int) Math.ceil(this.snacks.size() * 0.5));
|
||||||
|
this.turtlePlayerMap.values().forEach(Turtle::startBoostRefill);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onStop() {
|
||||||
|
this.getLeftPlayers().forEach(this::letPlayerLoose);
|
||||||
|
}
|
||||||
|
}
|
@@ -1,4 +1,4 @@
|
|||||||
package eu.mhsl.minenet.minigames.instance.game.stateless.types.blockBreakRace;
|
package eu.mhsl.minenet.minigames.instance.game.stateless.types.turtleGame;
|
||||||
|
|
||||||
import eu.mhsl.minenet.minigames.instance.game.Game;
|
import eu.mhsl.minenet.minigames.instance.game.Game;
|
||||||
import eu.mhsl.minenet.minigames.instance.game.stateless.config.ConfigManager;
|
import eu.mhsl.minenet.minigames.instance.game.stateless.config.ConfigManager;
|
||||||
@@ -11,30 +11,32 @@ import net.minestom.server.item.Material;
|
|||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class BlockBreakRaceFactory implements GameFactory {
|
public class TurtleGameFactory implements GameFactory {
|
||||||
@Override
|
|
||||||
public TranslatedComponent name() {
|
|
||||||
return TranslatedComponent.byId("game_BlockBreakRace#name");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Material symbol() {
|
public TranslatedComponent name() {
|
||||||
return Material.DIAMOND_PICKAXE;
|
return TranslatedComponent.byId("game_TurtleGame#name");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TranslatedComponent description() {
|
public TranslatedComponent description() {
|
||||||
return TranslatedComponent.byId("game_BlockBreakRace#description");
|
return TranslatedComponent.byId("game_TurtleGame#description");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ConfigManager configuration() {
|
public ConfigManager configuration() {
|
||||||
return new ConfigManager()
|
return new ConfigManager()
|
||||||
.addOption(new NumericOption("height", Material.SCAFFOLDING, TranslatedComponent.byId("optionCommon#height"), 20, 30, 40, 50));
|
.addOption(new NumericOption("radius", Material.HEART_OF_THE_SEA, TranslatedComponent.byId("optionCommon#radius"), 10, 20, 30, 40))
|
||||||
|
.addOption(new NumericOption("startSpeed", Material.LEATHER_BOOTS, TranslatedComponent.byId("game_TurtleGame#startSpeed"), 2, 4, 6, 8, 10));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Game manufacture(Room parent, Map<String, Option<?>> configuration) throws Exception {
|
public Game manufacture(Room parent, Map<String, Option<?>> configuration) throws Exception {
|
||||||
return new BlockBreakRace(configuration.get("height").getAsInt()).setParent(parent);
|
return new TurtleGame(configuration.get("radius").getAsInt(), configuration.get("startSpeed").getAsInt()).setParent(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Material symbol() {
|
||||||
|
return Material.TURTLE_EGG;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -0,0 +1,112 @@
|
|||||||
|
package eu.mhsl.minenet.minigames.instance.game.stateless.types.turtleGame.gameObjects;
|
||||||
|
|
||||||
|
import net.minestom.server.MinecraftServer;
|
||||||
|
import net.minestom.server.coordinate.Vec;
|
||||||
|
import net.minestom.server.entity.Entity;
|
||||||
|
import net.minestom.server.entity.EntityCreature;
|
||||||
|
import net.minestom.server.entity.EntityType;
|
||||||
|
import net.minestom.server.entity.Player;
|
||||||
|
import net.minestom.server.entity.attribute.Attribute;
|
||||||
|
import net.minestom.server.timer.Task;
|
||||||
|
import net.minestom.server.timer.TaskSchedule;
|
||||||
|
|
||||||
|
public class Turtle extends EntityCreature {
|
||||||
|
private final Player player;
|
||||||
|
private int score = 0;
|
||||||
|
private double speed;
|
||||||
|
private double boostSpeedMultiplier = 1;
|
||||||
|
private float boostChargeLevel = 0f;
|
||||||
|
private Task boostTask;
|
||||||
|
private Task boostRefillTask;
|
||||||
|
|
||||||
|
public Turtle(Player player, double speed) {
|
||||||
|
super(EntityType.TURTLE);
|
||||||
|
this.player = player;
|
||||||
|
this.speed = speed;
|
||||||
|
|
||||||
|
this.getAttribute(Attribute.MOVEMENT_SPEED).setBaseValue(0.15);
|
||||||
|
this.getAttribute(Attribute.MAX_HEALTH).setBaseValue(1);
|
||||||
|
this.player.setExp(this.boostChargeLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void spawnTurtle() {
|
||||||
|
this.setInstance(this.player.getInstance());
|
||||||
|
this.teleport(this.player.getPosition());
|
||||||
|
this.addPassenger(this.player);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startBoostRefill() {
|
||||||
|
this.boostRefillTask = MinecraftServer.getSchedulerManager().scheduleTask(() -> {
|
||||||
|
if(this.boostChargeLevel >= 1f) return;
|
||||||
|
this.increaseBoostChargeLevel(0.02f);
|
||||||
|
}, TaskSchedule.seconds(1), TaskSchedule.seconds(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void destroy() {
|
||||||
|
this.removePassenger(this.player);
|
||||||
|
this.remove();
|
||||||
|
this.kill();
|
||||||
|
if(this.boostRefillTask.isAlive()) this.boostRefillTask.cancel();
|
||||||
|
if(this.boostTask.isAlive()) this.boostTask.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void adaptView() {
|
||||||
|
this.teleport(this.getPosition().withView(this.player.getPosition().withPitch(this.getPosition().pitch())));
|
||||||
|
Vec lookingVector = this.player.getPosition().direction().withY(0).mul(100);
|
||||||
|
this.lookAt(this.getPosition().add(lookingVector.asPosition()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void move() {
|
||||||
|
this.adaptView();
|
||||||
|
Vec direction = this.player.getPosition().direction();
|
||||||
|
Vec movementVector = direction.withY(0).normalize().mul(this.speed * this.boostSpeedMultiplier);
|
||||||
|
this.setVelocity(movementVector);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean checkCollisionWithEntity(Entity other) {
|
||||||
|
return this.getBoundingBox().intersectBox(other.getPosition().sub(this.getPosition()), other.getBoundingBox());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void boostSpeed() {
|
||||||
|
if(this.boostChargeLevel <= 0f) return;
|
||||||
|
this.boostSpeedMultiplier = 3.5;
|
||||||
|
this.boostTask = MinecraftServer.getSchedulerManager().scheduleTask(() -> {
|
||||||
|
if(this.boostChargeLevel <= 0f) {
|
||||||
|
this.cancelBoost();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.boostChargeLevel = Math.max(0f, this.boostChargeLevel - 0.025f);
|
||||||
|
System.out.println(this.boostChargeLevel);
|
||||||
|
this.player.setExp(this.boostChargeLevel);
|
||||||
|
}, TaskSchedule.millis(30), TaskSchedule.millis(30));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cancelBoost() {
|
||||||
|
if(!this.boostTask.isAlive()) return;
|
||||||
|
this.boostTask.cancel();
|
||||||
|
this.boostSpeedMultiplier = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void increaseBoostChargeLevel(float amount) {
|
||||||
|
this.boostChargeLevel = Math.min(1f, this.boostChargeLevel + amount);
|
||||||
|
this.player.setExp(this.boostChargeLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addSpeed(double amount) {
|
||||||
|
this.speed += amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getScore() {
|
||||||
|
return this.score;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getBombBorder() {
|
||||||
|
// 1 bei speed 2; 2 bei speed 4; 4 bei speed 8
|
||||||
|
return Math.clamp((this.speed * this.boostSpeedMultiplier) / 2, 1.5, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void increaseScore() {
|
||||||
|
this.score += 1;
|
||||||
|
this.player.setLevel(this.score);
|
||||||
|
}
|
||||||
|
}
|
@@ -1,29 +0,0 @@
|
|||||||
package eu.mhsl.minenet.minigames.score;
|
|
||||||
|
|
||||||
import eu.mhsl.minenet.minigames.util.MapUtil;
|
|
||||||
import net.minestom.server.entity.Player;
|
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class LowestPointsWinScore extends PointsWinScore {
|
|
||||||
@Override
|
|
||||||
protected void insertResultImplementation(Set<Player> p, int currentPoints) {
|
|
||||||
Set<Player> combined = scoreOrder.entrySet().stream()
|
|
||||||
.filter(entrySet -> Objects.equals(entrySet.getValue(), currentPoints))
|
|
||||||
.map(Map.Entry::getKey)
|
|
||||||
.findFirst()
|
|
||||||
.orElseGet(() -> {
|
|
||||||
Set<Player> s = new HashSet<>();
|
|
||||||
scoreOrder.put(s, currentPoints);
|
|
||||||
return s;
|
|
||||||
});
|
|
||||||
combined.addAll(p);
|
|
||||||
|
|
||||||
this.scoreOrder = MapUtil.sortReversedByValue(this.scoreOrder);
|
|
||||||
getScores().clear();
|
|
||||||
this.scoreOrder.forEach((player, integer) -> getScores().addFirst(player));
|
|
||||||
}
|
|
||||||
}
|
|
@@ -12,21 +12,11 @@ import java.util.*;
|
|||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class PointsWinScore extends Score {
|
public class PointsWinScore extends Score {
|
||||||
Map<Set<Player>, Integer> scoreOrder = new HashMap<>();
|
private Map<Set<Player>, Integer> scoreOrder = new HashMap<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void insertResultImplementation(Set<Player> p, int currentPoints) {
|
protected void insertResultImplementation(Set<Player> p, int currentPoints) {
|
||||||
Set<Player> combined = scoreOrder.entrySet().stream()
|
this.scoreOrder.put(p, currentPoints);
|
||||||
.filter(entrySet -> Objects.equals(entrySet.getValue(), currentPoints))
|
|
||||||
.map(Map.Entry::getKey)
|
|
||||||
.findFirst()
|
|
||||||
.orElseGet(() -> {
|
|
||||||
Set<Player> s = new HashSet<>();
|
|
||||||
scoreOrder.put(s, currentPoints);
|
|
||||||
return s;
|
|
||||||
});
|
|
||||||
combined.addAll(p);
|
|
||||||
|
|
||||||
this.scoreOrder = MapUtil.sortByValue(this.scoreOrder);
|
this.scoreOrder = MapUtil.sortByValue(this.scoreOrder);
|
||||||
getScores().clear();
|
getScores().clear();
|
||||||
this.scoreOrder.forEach((player, integer) -> getScores().addFirst(player));
|
this.scoreOrder.forEach((player, integer) -> getScores().addFirst(player));
|
||||||
@@ -52,12 +42,13 @@ public class PointsWinScore extends Score {
|
|||||||
.filter(player -> !player.getUsername().isBlank())
|
.filter(player -> !player.getUsername().isBlank())
|
||||||
.toList()
|
.toList()
|
||||||
.isEmpty())
|
.isEmpty())
|
||||||
.map(players -> players.stream()
|
.map(players -> players
|
||||||
.map(Player::getUsername)
|
.stream()
|
||||||
.sorted()
|
.filter(player -> scoreOrder.get(Set.of(player)) != null)
|
||||||
.collect(Collectors.joining(", "))
|
.map(player -> player.getUsername()+" : "+scoreOrder.get(Set.of(player)).toString())
|
||||||
+ " : " + scoreOrder.get(players)
|
.collect(Collectors.joining(", "))
|
||||||
).toList()
|
)
|
||||||
|
.toList()
|
||||||
)
|
)
|
||||||
.undent()
|
.undent()
|
||||||
.newLine()
|
.newLine()
|
||||||
|
@@ -4,7 +4,6 @@ import eu.mhsl.minenet.minigames.score.Score;
|
|||||||
import net.minestom.server.entity.Player;
|
import net.minestom.server.entity.Player;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class Tournament {
|
public class Tournament {
|
||||||
private final List<Score> gameScores = new ArrayList<>();
|
private final List<Score> gameScores = new ArrayList<>();
|
||||||
@@ -44,11 +43,9 @@ public class Tournament {
|
|||||||
public Rewards getRewards() {
|
public Rewards getRewards() {
|
||||||
Map<UUID, Integer> itemCount = new HashMap<>();
|
Map<UUID, Integer> itemCount = new HashMap<>();
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (Set<Player> players : getPlaces()) {
|
for (Player player : getPlaces()) {
|
||||||
if(count >= this.rewardConfiguration.rewardCount().size()) break;
|
if(count >= this.rewardConfiguration.rewardCount().size()) break;
|
||||||
for(Player player : players) {
|
itemCount.put(player.getUuid(), this.rewardConfiguration.rewardCount().get(count));
|
||||||
itemCount.put(player.getUuid(), this.rewardConfiguration.rewardCount().get(count));
|
|
||||||
}
|
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,21 +53,18 @@ public class Tournament {
|
|||||||
this.memorialConfiguration.memorialMaterial().namespace().value(),
|
this.memorialConfiguration.memorialMaterial().namespace().value(),
|
||||||
this.memorialConfiguration.memorialTitle(),
|
this.memorialConfiguration.memorialTitle(),
|
||||||
this.memorialConfiguration.memorialLore(),
|
this.memorialConfiguration.memorialLore(),
|
||||||
getGameScores().keySet().stream().map(Player::getUuid).toList(),
|
getPlaces().stream().map(Player::getUuid).toList(),
|
||||||
this.rewardConfiguration.item().namespace().value(),
|
this.rewardConfiguration.item().namespace().value(),
|
||||||
itemCount
|
itemCount
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Set<Player>> getPlaces() {
|
public List<Player> getPlaces() {
|
||||||
List<Set<Player>> players = new ArrayList<>(
|
List<Player> players = new ArrayList<>(
|
||||||
getGameScores().entrySet().stream()
|
getGameScores().entrySet().stream()
|
||||||
.collect(
|
.sorted(Map.Entry.comparingByValue())
|
||||||
Collectors.groupingBy(
|
.map(Map.Entry::getKey)
|
||||||
Map.Entry::getValue,
|
.toList()
|
||||||
Collectors.mapping(Map.Entry::getKey, Collectors.toSet())
|
|
||||||
)
|
|
||||||
).values()
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Collections.reverse(players);
|
Collections.reverse(players);
|
||||||
|
@@ -12,12 +12,10 @@ import net.minestom.server.entity.*;
|
|||||||
import net.minestom.server.event.player.PlayerMoveEvent;
|
import net.minestom.server.event.player.PlayerMoveEvent;
|
||||||
import net.minestom.server.instance.anvil.AnvilLoader;
|
import net.minestom.server.instance.anvil.AnvilLoader;
|
||||||
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class TournamentDisplay extends MineNetInstance implements Spawnable {
|
public class TournamentDisplay extends MineNetInstance implements Spawnable {
|
||||||
private final List<Set<Player>> places;
|
private final List<Player> places;
|
||||||
private final Tournament tournament;
|
private final Tournament tournament;
|
||||||
|
|
||||||
private final Pos[] placePositions = new Pos[] {
|
private final Pos[] placePositions = new Pos[] {
|
||||||
@@ -32,7 +30,7 @@ public class TournamentDisplay extends MineNetInstance implements Spawnable {
|
|||||||
this.places = tournament.getPlaces();
|
this.places = tournament.getPlaces();
|
||||||
this.tournament = tournament;
|
this.tournament = tournament;
|
||||||
|
|
||||||
this.places.forEach(players -> players.forEach(player -> player.setGameMode(GameMode.ADVENTURE)));
|
this.places.forEach(player -> player.setGameMode(GameMode.ADVENTURE));
|
||||||
|
|
||||||
eventNode().addListener(PlayerMoveEvent.class, playerMoveEvent -> {
|
eventNode().addListener(PlayerMoveEvent.class, playerMoveEvent -> {
|
||||||
if(isOnDisplay(playerMoveEvent.getPlayer()) && !playerMoveEvent.getNewPosition().sameBlock(placePositions[getRankPosition(playerMoveEvent.getPlayer())])) {
|
if(isOnDisplay(playerMoveEvent.getPlayer()) && !playerMoveEvent.getNewPosition().sameBlock(placePositions[getRankPosition(playerMoveEvent.getPlayer())])) {
|
||||||
@@ -47,10 +45,7 @@ public class TournamentDisplay extends MineNetInstance implements Spawnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private int getRankPosition(Player player) {
|
private int getRankPosition(Player player) {
|
||||||
for (int i = 0; i < places.size(); i++) {
|
return this.places.indexOf(player);
|
||||||
if (places.get(i).contains(player)) return i;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -61,11 +56,8 @@ public class TournamentDisplay extends MineNetInstance implements Spawnable {
|
|||||||
p.teleport(placePositions[getRankPosition(p)]);
|
p.teleport(placePositions[getRankPosition(p)]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
List<Player> players = this.places.stream()
|
|
||||||
.flatMap(s -> s.stream().sorted(Comparator.comparing(Player::getUsername)))
|
|
||||||
.toList();
|
|
||||||
new ChatMessage(Icon.STAR)
|
new ChatMessage(Icon.STAR)
|
||||||
.list(players.stream().map(player -> String.format("%d. %s - %s Punkte", this.getRankPosition(player)+1, player.getUsername(), tournament.getGameScores().get(player))).toList())
|
.numberedList(this.places.stream().map(player -> String.format("%s - %s Punkte", player.getUsername(), tournament.getGameScores().get(player))).toList())
|
||||||
.send(p);
|
.send(p);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,9 @@
|
|||||||
package eu.mhsl.minenet.minigames.util;
|
package eu.mhsl.minenet.minigames.util;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public class MapUtil {
|
public class MapUtil {
|
||||||
public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map) {
|
public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map) {
|
||||||
@@ -14,16 +17,4 @@ public class MapUtil {
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <K, V extends Comparable<? super V>> Map<K, V> sortReversedByValue(Map<K, V> map) {
|
|
||||||
List<Map.Entry<K, V>> list = new ArrayList<>(map.entrySet());
|
|
||||||
list.sort(Map.Entry.<K, V>comparingByValue().reversed());
|
|
||||||
|
|
||||||
Map<K, V> result = new LinkedHashMap<>();
|
|
||||||
for (Map.Entry<K, V> entry : list) {
|
|
||||||
result.put(entry.getKey(), entry.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
@@ -144,7 +144,7 @@ ns:game_Fastbridge#;;
|
|||||||
name;Fastbridge;Fastbridge
|
name;Fastbridge;Fastbridge
|
||||||
description;Speedbridge to the other platform. The first one there wins!;Baue dich so schnell wie möglich zur anderen Plattform. Wer zuerst dort ist, gewinnt!
|
description;Speedbridge to the other platform. The first one there wins!;Baue dich so schnell wie möglich zur anderen Plattform. Wer zuerst dort ist, gewinnt!
|
||||||
;;
|
;;
|
||||||
ns:game_BlockBreakRace#;;
|
ns:game_TurtleGame#;;
|
||||||
name;Block Break Race;Blockbruch-Rennen
|
name;Turtle Game;Turtle Game
|
||||||
description;Dig down through the tubes using the right tools. The first player to reach the bottom wins!;Grabe dich durch die Röhren nach unten und verwende dabei das richtige Werkzeug. Wer zuerst unten ankommt, gewinnt!
|
description;Eat snacks and dodge bombs to get the highest score!;Esse Snacks und weiche Bomben aus, um den höchsten Score zu erreichen!
|
||||||
;;
|
startSpeed;Start Speed;Startgeschwindigkeit
|
||||||
|
Can't render this file because it has a wrong number of fields in line 114.
|
Reference in New Issue
Block a user