added Build Battle #15
No files matched your search
@@ -9,6 +9,7 @@ import eu.mhsl.minenet.minigames.instance.game.stateless.types.blockBattle.Block
|
|||||||
import eu.mhsl.minenet.minigames.instance.game.stateless.types.blockBreakRace.BlockBreakRaceFactory;
|
import eu.mhsl.minenet.minigames.instance.game.stateless.types.blockBreakRace.BlockBreakRaceFactory;
|
||||||
import eu.mhsl.minenet.minigames.instance.game.stateless.types.boatRace.BoatRaceFactory;
|
import eu.mhsl.minenet.minigames.instance.game.stateless.types.boatRace.BoatRaceFactory;
|
||||||
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.buildBattle.BuildBattleFactory;
|
||||||
import eu.mhsl.minenet.minigames.instance.game.stateless.types.colorJump.ColorJumpFactory;
|
import eu.mhsl.minenet.minigames.instance.game.stateless.types.colorJump.ColorJumpFactory;
|
||||||
import eu.mhsl.minenet.minigames.instance.game.stateless.types.deathcube.DeathcubeFactory;
|
import eu.mhsl.minenet.minigames.instance.game.stateless.types.deathcube.DeathcubeFactory;
|
||||||
import eu.mhsl.minenet.minigames.instance.game.stateless.types.elytraRace.ElytraRaceFactory;
|
import eu.mhsl.minenet.minigames.instance.game.stateless.types.elytraRace.ElytraRaceFactory;
|
||||||
@@ -54,7 +55,8 @@ public enum GameList {
|
|||||||
PILLARS(new PillarsFactory(), GameType.PROTOTYPE),
|
PILLARS(new PillarsFactory(), GameType.PROTOTYPE),
|
||||||
BLOCKBATTLE(new BlockBattleFactory(), GameType.PVP),
|
BLOCKBATTLE(new BlockBattleFactory(), GameType.PVP),
|
||||||
COLORJUMP(new ColorJumpFactory(), GameType.JUMPNRUN),
|
COLORJUMP(new ColorJumpFactory(), GameType.JUMPNRUN),
|
||||||
PLAYERRACE(new PlayerRaceFactory(), GameType.JUMPNRUN);
|
PLAYERRACE(new PlayerRaceFactory(), GameType.JUMPNRUN),
|
||||||
|
BUILDBATTLE(new BuildBattleFactory(), GameType.PROTOTYPE);
|
||||||
|
|
||||||
private final GameFactory factory;
|
private final GameFactory factory;
|
||||||
private final GameType type;
|
private final GameType type;
|
||||||
|
|||||||
+1
-1
@@ -43,7 +43,7 @@ public class BlockBattle extends StatelessGame {
|
|||||||
);
|
);
|
||||||
|
|
||||||
this.eventNode().addListener(FinalAttackEvent.class, finalAttackEvent -> {
|
this.eventNode().addListener(FinalAttackEvent.class, finalAttackEvent -> {
|
||||||
if(this.isBeforeBeginning) finalAttackEvent.setCancelled(true);
|
if(!this.isRunning) finalAttackEvent.setCancelled(true);
|
||||||
finalAttackEvent.setBaseDamage(0);
|
finalAttackEvent.setBaseDamage(0);
|
||||||
((Player) finalAttackEvent.getTarget()).setHealth(20);
|
((Player) finalAttackEvent.getTarget()).setHealth(20);
|
||||||
});
|
});
|
||||||
|
|||||||
+186
@@ -0,0 +1,186 @@
|
|||||||
|
package eu.mhsl.minenet.minigames.instance.game.stateless.types.buildBattle;
|
||||||
|
|
||||||
|
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.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
import net.kyori.adventure.title.Title;
|
||||||
|
import net.minestom.server.coordinate.Point;
|
||||||
|
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.PlayerBlockPlaceEvent;
|
||||||
|
import net.minestom.server.event.player.PlayerUseItemEvent;
|
||||||
|
import net.minestom.server.item.ItemStack;
|
||||||
|
import net.minestom.server.item.Material;
|
||||||
|
import net.minestom.server.timer.TaskSchedule;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
|
|
||||||
|
public class BuildBattle extends StatelessGame {
|
||||||
|
private static final int height = 100;
|
||||||
|
private static final int plotHalf = BuildBattleChunkgenerator.inner / 2;
|
||||||
|
private static final int rowCount = 5;
|
||||||
|
private static final int ratingSeconds = 15;
|
||||||
|
private static final List<Material> ratingMaterials = List.of(
|
||||||
|
Material.RED_CONCRETE, Material.ORANGE_CONCRETE, Material.YELLOW_CONCRETE,
|
||||||
|
Material.LIME_CONCRETE, Material.GREEN_CONCRETE
|
||||||
|
);
|
||||||
|
private static final List<ItemStack> ratingItems = IntStream.range(0, ratingMaterials.size())
|
||||||
|
.mapToObj(i -> ItemStack.builder(ratingMaterials.get(i))
|
||||||
|
.customName(Component.text((i + 1) + " Punkte"))
|
||||||
|
.build())
|
||||||
|
.toList();
|
||||||
|
private static final List<String> themes = List.of(
|
||||||
|
"Burg", "Raumschiff", "Unterwasserwelt", "Pizzeria", "Spukhaus",
|
||||||
|
"Bauernhof", "Dschungel", "Zukunftsstadt", "Piratenschiff", "Vulkan",
|
||||||
|
"Freizeitpark", "Leuchtturm", "Wikingerdorf", "Weihnachtsmarkt",
|
||||||
|
"Schloss", "Strand", "Berghütte", "Bahnhof", "Zoo", "Schule",
|
||||||
|
"Zeitreise", "Ein Haus, das auf dem Kopf steht", "Eine Stadt auf dem Rücken eines Riesen",
|
||||||
|
"Wohnen in einer Schneekugel", "Alles ist aus Süßigkeiten", "Ein Schiff in der Luft",
|
||||||
|
"Das Museum der Zukunft", "Das letzte Haus vor dem Weltuntergang",
|
||||||
|
"Wenn Schweine fliegen könnten", "Das Gefängnis für Creeper", "Die Wohnung von Herobrine",
|
||||||
|
"Ein Dönerladen im Weltall", "Ein Spa für Enderman", "Der Käse-Palast",
|
||||||
|
"Mein Zimmer nach 3 Wochen ohne Aufräumen", "Die Hüpfburg des Todes"
|
||||||
|
);
|
||||||
|
|
||||||
|
private int spawnPosx = 0;
|
||||||
|
private int spawnPosz = 0;
|
||||||
|
private final Map<Player, Pos> spawnPositions = new WeakHashMap<>();
|
||||||
|
private final int seconds;
|
||||||
|
private final Map<Player, Integer> currentVotes = new HashMap<>();
|
||||||
|
private Player currentOwner = null;
|
||||||
|
|
||||||
|
public BuildBattle(int seconds) {
|
||||||
|
super(Dimension.THE_END.key, "BuildBattle", new PointsWinScore());
|
||||||
|
this.seconds = seconds;
|
||||||
|
this.setGenerator(new BuildBattleChunkgenerator(height));
|
||||||
|
this.eventNode().addListener(PlayerUseItemEvent.class, this::onRatingItemUse);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onStart() {
|
||||||
|
String theme = themes.get(this.rnd.nextInt(themes.size()));
|
||||||
|
|
||||||
|
this.showTitle(Title.title(
|
||||||
|
Component.text("Thema", NamedTextColor.GOLD),
|
||||||
|
Component.text(theme, NamedTextColor.YELLOW)
|
||||||
|
));
|
||||||
|
this.sendMessage(Component.text("Euer Thema: ", NamedTextColor.GRAY)
|
||||||
|
.append(Component.text(theme, NamedTextColor.YELLOW)));
|
||||||
|
this.getPlayers().forEach(player -> player.setGameMode(GameMode.CREATIVE));
|
||||||
|
|
||||||
|
this.scheduler().scheduleTask(this::endBuildPhase, TaskSchedule.seconds(this.seconds), TaskSchedule.stop());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void endBuildPhase() {
|
||||||
|
this.sendMessage(Component.text("Die Bauzeit ist beendet!"));
|
||||||
|
this.getPlayers().forEach(p -> {
|
||||||
|
p.setGameMode(GameMode.ADVENTURE);
|
||||||
|
p.setAllowFlying(true);
|
||||||
|
p.setFlying(true);
|
||||||
|
});
|
||||||
|
this.scheduler().scheduleTask(this::rating, TaskSchedule.seconds(3), TaskSchedule.stop());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean onPlayerJoin(Player player) {
|
||||||
|
Pos plotCenter = new Pos(
|
||||||
|
this.spawnPosx * BuildBattleChunkgenerator.period + plotHalf,
|
||||||
|
height,
|
||||||
|
this.spawnPosz * BuildBattleChunkgenerator.period + plotHalf
|
||||||
|
);
|
||||||
|
this.spawnPositions.put(player, plotCenter);
|
||||||
|
|
||||||
|
if(this.spawnPosx >= rowCount - 1) {
|
||||||
|
this.spawnPosx = 0;
|
||||||
|
this.spawnPosz++;
|
||||||
|
} else this.spawnPosx ++;
|
||||||
|
|
||||||
|
Pupsi marked this conversation as resolved
Outdated
|
|||||||
|
player.setGameMode(GameMode.ADVENTURE);
|
||||||
|
this.scheduler().scheduleNextTick(() -> player.teleport(plotCenter.add(0, 1.5, 0)));
|
||||||
|
return super.onPlayerJoin(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onBlockBreak(@NotNull PlayerBlockBreakEvent event) {
|
||||||
|
event.setCancelled(!this.isInArea(event.getBlockPosition(), event.getPlayer()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onBlockPlace(@NotNull PlayerBlockPlaceEvent event) {
|
||||||
|
event.setCancelled(!this.isInArea(event.getBlockPosition(), event.getPlayer()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void rating() {
|
||||||
|
Queue<Player> owners = new ArrayDeque<>(this.getPlayers());
|
||||||
|
|
||||||
|
this.scheduler().submitTask(() -> {
|
||||||
|
if (this.currentOwner != null) this.finishRound();
|
||||||
|
|
||||||
|
Player next = owners.poll();
|
||||||
|
while (next != null && !(next.isOnline() && this.spawnPositions.containsKey(next))) next = owners.poll();
|
||||||
|
if (next == null) return TaskSchedule.stop();
|
||||||
|
|
||||||
|
this.startRound(next);
|
||||||
|
return TaskSchedule.seconds(ratingSeconds);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startRound(Player owner) {
|
||||||
|
this.currentOwner = owner;
|
||||||
|
this.currentVotes.clear();
|
||||||
|
|
||||||
|
Pos plot = this.spawnPositions.get(owner).add(0, 1.5, 0);
|
||||||
|
this.sendMessage(Component.text("Bewerte das Grundstück von " + owner.getUsername() + "!"));
|
||||||
|
this.getPlayers().forEach(p -> {
|
||||||
|
p.teleport(plot);
|
||||||
|
p.getInventory().clear();
|
||||||
|
if (p != owner) this.giveRatingItems(p);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void giveRatingItems(Player player) {
|
||||||
|
for (int i = 0; i < ratingItems.size(); i++) {
|
||||||
|
player.getInventory().setItemStack(i, ratingItems.get(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onRatingItemUse(PlayerUseItemEvent event) {
|
||||||
|
Player voter = event.getPlayer();
|
||||||
|
if (this.currentOwner == null || voter == this.currentOwner) return;
|
||||||
|
|
||||||
|
int slot = voter.getHeldSlot();
|
||||||
|
if (slot >= ratingItems.size()) return;
|
||||||
|
|
||||||
|
event.setCancelled(true);
|
||||||
|
this.currentVotes.put(voter, slot + 1);
|
||||||
|
voter.sendMessage(Component.text("Du hast " + (slot + 1) + " Punkte vergeben."));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void finishRound() {
|
||||||
|
int voteSum = this.currentVotes.values().stream()
|
||||||
|
Pupsi marked this conversation as resolved
Outdated
Pupsi
commented
Vielleicht lieber einen Durchschnitt oder so anstatt einer Summe? Dann wird es nicht unfair, wenn bewertende Spieler leaven und insgesamt weniger Punkte vergeben werden können. Vielleicht lieber einen Durchschnitt oder so anstatt einer Summe? Dann wird es nicht unfair, wenn bewertende Spieler leaven und insgesamt weniger Punkte vergeben werden können.
|
|||||||
|
.mapToInt(Integer::intValue)
|
||||||
|
.sum();
|
||||||
|
int score = (int) Math.round((double) voteSum / this.getPlayers().size());
|
||||||
|
|
||||||
|
this.getPlayers().forEach(p -> p.getInventory().clear());
|
||||||
|
Pupsi marked this conversation as resolved
Outdated
Pupsi
commented
Wieso nicht erst insertResult(this.currentOwner, sum) und dann currentOwner = null ? Dann wäre Zeile 170 unnötig. Wieso nicht erst insertResult(this.currentOwner, sum) und dann currentOwner = null ? Dann wäre Zeile 170 unnötig.
|
|||||||
|
this.getScore().insertResult(this.currentOwner, score);
|
||||||
|
this.currentOwner = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isInArea(Point block, Player player) {
|
||||||
|
Pos center = this.spawnPositions.get(player);
|
||||||
|
double dx = block.x() - center.x();
|
||||||
|
double dy = block.y() - center.y();
|
||||||
|
double dz = block.z() - center.z();
|
||||||
|
return dx >= -plotHalf && dx < plotHalf
|
||||||
|
&& dy >= 1 && dy <= 300
|
||||||
|
&& dz >= -plotHalf && dz < plotHalf;
|
||||||
|
}
|
||||||
|
}
|
||||||
+41
@@ -0,0 +1,41 @@
|
|||||||
|
package eu.mhsl.minenet.minigames.instance.game.stateless.types.buildBattle;
|
||||||
|
|
||||||
|
import eu.mhsl.minenet.minigames.util.GeneratorUtils;
|
||||||
|
import eu.mhsl.minenet.minigames.world.generator.terrain.BaseGenerator;
|
||||||
|
import net.minestom.server.instance.block.Block;
|
||||||
|
|
||||||
|
public class BuildBattleChunkgenerator extends BaseGenerator {
|
||||||
|
static final int inner = 32;
|
||||||
|
private static final int ring = 3;
|
||||||
|
private static final int wall = 1;
|
||||||
|
private static final int wallHeight = 200;
|
||||||
|
|
||||||
|
static final int period = wall + ring + inner + ring;
|
||||||
|
|
||||||
|
private static final int innerStart = wall + ring;
|
||||||
|
private static final int innerEnd = innerStart + inner;
|
||||||
|
|
||||||
|
private static final Block middleBlocks = Block.QUARTZ_BLOCK;
|
||||||
|
private static final Block outerBlocks = Block.STONE_BRICKS;
|
||||||
|
private static final Block wallBlocks = Block.POLISHED_DEEPSLATE;
|
||||||
|
|
||||||
|
public BuildBattleChunkgenerator(int height) {
|
||||||
|
this.addMixIn(unit -> GeneratorUtils.foreachXZ(unit, point -> {
|
||||||
|
int lx = Math.floorMod(point.blockX() + innerStart, period);
|
||||||
|
int lz = Math.floorMod(point.blockZ() + innerStart, period);
|
||||||
|
|
||||||
|
if (lx < wall || lz < wall) {
|
||||||
|
unit.modifier().fill(point.withY(height), point.add(1, 0, 1).withY(height + wallHeight + 1), wallBlocks);
|
||||||
|
} else {
|
||||||
|
unit.modifier().setBlock(point.withY(height), floorBlock(lx, lz));
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Block floorBlock(int lx, int lz) {
|
||||||
|
boolean inInner = lx >= innerStart && lx < innerEnd
|
||||||
|
&& lz >= innerStart && lz < innerEnd;
|
||||||
|
|
||||||
|
return inInner ? middleBlocks : outerBlocks;
|
||||||
|
}
|
||||||
|
}
|
||||||
+40
@@ -0,0 +1,40 @@
|
|||||||
|
package eu.mhsl.minenet.minigames.instance.game.stateless.types.buildBattle;
|
||||||
|
|
||||||
|
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 BuildBattleFactory implements GameFactory {
|
||||||
|
@Override
|
||||||
|
public TranslatedComponent name() {
|
||||||
|
return TranslatedComponent.byId("game_BuildBattle#name");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ConfigManager configuration() {
|
||||||
|
return new ConfigManager()
|
||||||
|
.addOption(new NumericOption("seconds", Material.CLOCK, TranslatedComponent.byId("game_BuildBattle#seconds"), 60, 120, 300, 600));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Game manufacture(Room parent, Map<String, Option<?>> configuration) throws Exception {
|
||||||
|
return new BuildBattle(configuration.get("seconds").getAsInt()).setParent(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Material symbol() {
|
||||||
|
return Material.SANDSTONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TranslatedComponent description() {
|
||||||
|
return TranslatedComponent.byId("game_BuildBattle#description");
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
@@ -172,5 +172,9 @@ public class ColorJump extends StatelessGame {
|
|||||||
this.getScore().insertResult(player);
|
this.getScore().insertResult(player);
|
||||||
player.setGameMode(GameMode.SPECTATOR);
|
player.setGameMode(GameMode.SPECTATOR);
|
||||||
}
|
}
|
||||||
|
if(!this.isBeforeBeginning && !this.isRunning) {
|
||||||
|
player.setGameMode(GameMode.SPECTATOR);
|
||||||
|
player.teleport(this.getSpawn());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -191,3 +191,8 @@ description;Jump on the right color!;Springe auf die richtige Farbe!
|
|||||||
ns:game_PlayerRace#;;
|
ns:game_PlayerRace#;;
|
||||||
name;Player Race;Wettrennen
|
name;Player Race;Wettrennen
|
||||||
description;Get to the other side as quickly as possible!;Komme so schnell wie möglich auf die andere Seite!
|
description;Get to the other side as quickly as possible!;Komme so schnell wie möglich auf die andere Seite!
|
||||||
|
;;
|
||||||
|
ns:game_BuildBattle#;;
|
||||||
|
name;Build Battle;Bauwettbewerb
|
||||||
|
description;Build the best creation for the given theme before time runs out and win through the other players’ ratings.;Baue in der Zeit das beste Bauwerk zum Thema und gewinne durch die Bewertung der anderen Spieler.
|
||||||
|
seconds;Build Time;Bauzeit
|
||||||
|
Reference in new issue
Block a user
Im if wird x wieder auf 0 gesetzt, aber danach durch spawnPosx++ direkt wieder auf 1. x ist also nur beim ersten Spieler 0.
also das spawnPosx ++ vor das if statement?