Compare commits
13 Commits
develop-ha
...
382d850605
| Author | SHA1 | Date | |
|---|---|---|---|
| 382d850605 | |||
| a49b3b20cc | |||
| 148b5fc634 | |||
| abf907af24 | |||
| 8bd0ab1974 | |||
| 2c92553a8a | |||
| f26c3a9e6d | |||
| 81524cfecf | |||
| f2fc4835c3 | |||
| abcb23d96a | |||
| eabbb312b9 | |||
| d98cebd86f | |||
| c87d318421 |
@@ -19,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.towerdefense.TowerdefenseFactory;
|
||||
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 {
|
||||
DEATHCUBE(new DeathcubeFactory(), GameType.JUMPNRUN),
|
||||
@@ -29,6 +30,7 @@ public enum GameList {
|
||||
BEDWARS(new BedwarsFactory(), GameType.PROTOTYPE),
|
||||
BACKROOMS(new BackroomsFactory(), GameType.PROTOTYPE),
|
||||
BOWSPLEEF(new BowSpleefFactory(), GameType.PROTOTYPE),
|
||||
TURTLEGAME(new TurtleGameFactory(), GameType.PROTOTYPE),
|
||||
TETRIS(new TetrisFactory(), GameType.OTHER),
|
||||
TNTRUN(new TntRunFactory(), GameType.OTHER),
|
||||
ANVILRUN(new AnvilRunFactory(), GameType.PVE),
|
||||
|
||||
@@ -112,9 +112,11 @@ class Tetris extends StatelessGame {
|
||||
|
||||
private void letPlayerLoose(Player player) {
|
||||
TetrisGame tetrisGame = this.tetrisGames.get(player);
|
||||
if(!this.getScore().hasResult(player)) {
|
||||
player.setGameMode(GameMode.SPECTATOR);
|
||||
player.setInvisible(true);
|
||||
this.getScore().insertResult(player, tetrisGame.getScore());
|
||||
}
|
||||
|
||||
boolean allGamesLost = this.tetrisGames.values().stream()
|
||||
.filter(game -> !game.lost)
|
||||
|
||||
@@ -0,0 +1,213 @@
|
||||
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.score.PointsWinScore;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.coordinate.Pos;
|
||||
import net.minestom.server.coordinate.Vec;
|
||||
import net.minestom.server.entity.*;
|
||||
import net.minestom.server.entity.attribute.Attribute;
|
||||
import net.minestom.server.entity.metadata.other.FallingBlockMeta;
|
||||
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 org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
// TODO: Sound Effects, Partikel und Info für Score
|
||||
|
||||
class TurtleGame extends StatelessGame {
|
||||
private final int radius;
|
||||
private final Map<Player, EntityCreature> turtlePlayerMap = new WeakHashMap<>();
|
||||
private final Map<Player, Integer> scoreMap = new WeakHashMap<>();
|
||||
private final ArrayList<Entity> snacks = new ArrayList<>();
|
||||
private final ArrayList<Entity> bombs = new ArrayList<>();
|
||||
private double speed;
|
||||
private final double maxSpeedIncrease;
|
||||
|
||||
public TurtleGame(int radius, int startSpeed) {
|
||||
super(Dimension.OVERWORLD.key, "Turtle Game", new PointsWinScore());
|
||||
this.radius = radius;
|
||||
this.speed = startSpeed;
|
||||
this.maxSpeedIncrease = (double) this.radius / 4;
|
||||
|
||||
this.eventNode()
|
||||
.addListener(PlayerTickEvent.class, this::onPlayerTick);
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void onPlayerTick(@NotNull PlayerTickEvent event) {
|
||||
Player p = event.getPlayer();
|
||||
if(p.getGameMode() == GameMode.SPECTATOR) return;
|
||||
EntityCreature turtle = this.turtlePlayerMap.get(p);
|
||||
turtle.teleport(turtle.getPosition().withView(p.getPosition()));
|
||||
Vec direction = p.getPosition().direction();
|
||||
if(this.isRunning()) {
|
||||
Vec targetDirection = direction.withY(0).normalize().mul(this.speed);
|
||||
turtle.setVelocity(targetDirection);
|
||||
|
||||
List<Entity> hitSnacks = this.snacks.stream()
|
||||
.filter(snack -> snack.getBoundingBox().intersectBox(turtle.getPosition().sub(snack.getPosition()), turtle.getBoundingBox()))
|
||||
.toList();
|
||||
List<Entity> hitBombs = this.bombs.stream()
|
||||
.filter(bomb -> bomb.getBoundingBox().intersectBox(turtle.getPosition().sub(bomb.getPosition()), turtle.getBoundingBox()))
|
||||
.toList();
|
||||
|
||||
hitSnacks.forEach(snack -> {
|
||||
this.snacks.remove(snack);
|
||||
snack.remove();
|
||||
this.generateNewSnack();
|
||||
this.scoreMap.put(p, this.scoreMap.get(p) + 1);
|
||||
});
|
||||
hitBombs.forEach(bomb -> {
|
||||
p.setGameMode(GameMode.SPECTATOR);
|
||||
p.setFlying(true);
|
||||
turtle.removePassenger(p);
|
||||
turtle.remove();
|
||||
turtle.kill();
|
||||
this.bombs.remove(bomb);
|
||||
bomb.remove();
|
||||
this.generateNewBomb(2);
|
||||
this.getScore().insertResult(p, this.scoreMap.get(p));
|
||||
this.speed += this.maxSpeedIncrease / this.getPlayers().size();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onPlayerJoin(Player p) {
|
||||
p.getInventory().setItemStack(0, ItemStack.builder(Material.BARRIER).customName(Component.text("Reset Snack")).build());
|
||||
|
||||
if(this.turtlePlayerMap.get(p) == null) {
|
||||
EntityCreature turtle = new EntityCreature(EntityType.TURTLE);
|
||||
this.turtlePlayerMap.put(p, turtle);
|
||||
}
|
||||
this.scoreMap.putIfAbsent(p, 0);
|
||||
|
||||
EntityCreature turtle = this.turtlePlayerMap.get(p);
|
||||
MinecraftServer.getSchedulerManager().scheduleNextTick(() -> {
|
||||
turtle.setInstance(this);
|
||||
turtle.teleport(p.getPosition());
|
||||
turtle.addPassenger(p);
|
||||
turtle.getAttribute(Attribute.MOVEMENT_SPEED).setBaseValue(0.15);
|
||||
});
|
||||
|
||||
return super.onPlayerJoin(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPlayerLeave(Player p) {
|
||||
EntityCreature 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 generateNewSnack(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(Block.SUNFLOWER.withProperty("half", "upper"));
|
||||
snack.setInstance(this);
|
||||
Pos spawnPosition = this.newSpawnPosition(snack);
|
||||
if(spawnPosition == null) {
|
||||
snack.remove();
|
||||
return;
|
||||
}
|
||||
snack.teleport(spawnPosition);
|
||||
this.snacks.add(snack);
|
||||
}
|
||||
|
||||
private void generateNewBomb(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);
|
||||
bomb.setInstance(this);
|
||||
Pos spawnPosition = this.newSpawnPosition(bomb, 2);
|
||||
if(spawnPosition == null) {
|
||||
bomb.remove();
|
||||
return;
|
||||
}
|
||||
bomb.teleport(spawnPosition);
|
||||
this.bombs.add(bomb);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Pos newSpawnPosition(Entity entity) {
|
||||
return this.newSpawnPosition(entity, 0);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Pos newSpawnPosition(Entity entity, double border) {
|
||||
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-3;
|
||||
collides = this.getEntities().stream()
|
||||
.filter(e -> !e.equals(entity))
|
||||
.anyMatch(e -> entity.getBoundingBox().growSymmetrically(border, border, border).intersectBox(e.getPosition().sub(checkPosition), e.getBoundingBox()));
|
||||
counter++;
|
||||
} while (!isInRadius || collides);
|
||||
return spawnPosition;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
this.generateNewSnack((int) Math.ceil(this.turtlePlayerMap.size() * 1.5));
|
||||
this.generateNewBomb((int) Math.ceil(this.snacks.size() * 0.5));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
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.stateless.config.ConfigManager;
|
||||
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.common.NumericOption;
|
||||
import eu.mhsl.minenet.minigames.instance.room.Room;
|
||||
import eu.mhsl.minenet.minigames.message.component.TranslatedComponent;
|
||||
import net.minestom.server.item.Material;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class TurtleGameFactory implements GameFactory {
|
||||
|
||||
@Override
|
||||
public TranslatedComponent name() {
|
||||
return TranslatedComponent.byId("game_TurtleGame#name");
|
||||
}
|
||||
|
||||
@Override
|
||||
public TranslatedComponent description() {
|
||||
return TranslatedComponent.byId("game_TurtleGame#description");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigManager configuration() {
|
||||
return new ConfigManager()
|
||||
.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));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Game manufacture(Room parent, Map<String, Option<?>> configuration) throws Exception {
|
||||
return new TurtleGame(configuration.get("radius").getAsInt(), configuration.get("startSpeed").getAsInt()).setParent(parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Material symbol() {
|
||||
return Material.TURTLE_EGG;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user