Added Bedwars

Added ConfigurationHandler for games
Further progress
This commit is contained in:
2023-01-07 23:54:55 +01:00
parent bf4d8b97ed
commit d1432347c1
452 changed files with 671 additions and 44019 deletions

View File

@ -13,6 +13,8 @@ import java.util.logging.Logger;
public enum Resource {
HUB_MAP("maps/hub"),
LOBBY_MAP("maps/lobby"),
GAME_MAP("maps/game"),
LOCALES("lang");
private final Path path;

View File

@ -1,8 +1,8 @@
package eu.mhsl.minenet.minigames.command;
import eu.mhsl.minenet.minigames.command.admin.*;
import eu.mhsl.minenet.minigames.command.user.HubCommand;
import eu.mhsl.minenet.minigames.command.user.LeaveCommand;
import eu.mhsl.minenet.minigames.command.privileged.*;
import eu.mhsl.minenet.minigames.command.anonymous.HubCommand;
import eu.mhsl.minenet.minigames.command.anonymous.LeaveCommand;
import eu.mhsl.minenet.minigames.message.Icon;
import eu.mhsl.minenet.minigames.message.type.ChatMessage;
import net.minestom.server.MinecraftServer;

View File

@ -1,4 +1,4 @@
package eu.mhsl.minenet.minigames.command.user;
package eu.mhsl.minenet.minigames.command.anonymous;
import eu.mhsl.minenet.minigames.util.MoveInstance;
import eu.mhsl.minenet.minigames.instance.hub.Hub;

View File

@ -1,4 +1,4 @@
package eu.mhsl.minenet.minigames.command.user;
package eu.mhsl.minenet.minigames.command.anonymous;
import eu.mhsl.minenet.minigames.instance.game.Game;
import eu.mhsl.minenet.minigames.instance.room.Room;

View File

@ -1,4 +1,4 @@
package eu.mhsl.minenet.minigames.command.admin;
package eu.mhsl.minenet.minigames.command.privileged;
import eu.mhsl.minenet.minigames.message.Icon;
import eu.mhsl.minenet.minigames.message.type.ActionBarMessage;

View File

@ -1,4 +1,4 @@
package eu.mhsl.minenet.minigames.command.admin;
package eu.mhsl.minenet.minigames.command.privileged;
import net.minestom.server.command.builder.Command;
import net.minestom.server.coordinate.Vec;

View File

@ -1,4 +1,4 @@
package eu.mhsl.minenet.minigames.command.admin;
package eu.mhsl.minenet.minigames.command.privileged;
import net.minestom.server.command.builder.Command;
import net.minestom.server.command.builder.arguments.ArgumentEnum;

View File

@ -1,4 +1,4 @@
package eu.mhsl.minenet.minigames.command.admin;
package eu.mhsl.minenet.minigames.command.privileged;
import eu.mhsl.minenet.minigames.message.type.ChatMessage;
import eu.mhsl.minenet.minigames.message.Icon;

View File

@ -1,4 +1,4 @@
package eu.mhsl.minenet.minigames.command.admin;
package eu.mhsl.minenet.minigames.command.privileged;
import eu.mhsl.minenet.minigames.lang.Languages;
import eu.mhsl.minenet.minigames.lang.Lang;

View File

@ -1,4 +1,4 @@
package eu.mhsl.minenet.minigames.command.admin;
package eu.mhsl.minenet.minigames.command.privileged;
import eu.mhsl.minenet.minigames.message.Icon;
import eu.mhsl.minenet.minigames.message.TranslatableMessage;

View File

@ -1,4 +1,4 @@
package eu.mhsl.minenet.minigames.command.admin;
package eu.mhsl.minenet.minigames.command.privileged;
import eu.mhsl.minenet.minigames.message.type.ChatMessage;
import eu.mhsl.minenet.minigames.message.Icon;

View File

@ -9,6 +9,8 @@ import net.minestom.server.MinecraftServer;
import net.minestom.server.entity.Player;
import net.minestom.server.event.EventListener;
import net.minestom.server.event.instance.AddEntityToInstanceEvent;
import net.minestom.server.potion.Potion;
import net.minestom.server.potion.PotionEffect;
import net.minestom.server.timer.ExecutionType;
import org.jetbrains.annotations.NotNull;
@ -26,7 +28,7 @@ public class AddEntityToInstanceEventListener implements EventListener<AddEntity
new ActionBarMessage().appendStatic(Component.text("Instance: ", NamedTextColor.DARK_GRAY)).appendStatic(event.getInstance().getUniqueId().toString()).send(p);
new ChatMessage(Icon.SCIENCE).appendStatic(Component.text(event.getInstance().getUniqueId().toString())).send(p);
//p.addEffect(new Potion(PotionEffect.BLINDNESS, (byte) 1, 20)); //TODO Uncomment, currently buggy causes disconnect see https://github.com/Minestom/Minestom/discussions/1302
p.addEffect(new Potion(PotionEffect.BLINDNESS, (byte) 1, 20)); //TODO Uncomment, currently buggy causes disconnect see https://github.com/Minestom/Minestom/discussions/1302
}
return Result.SUCCESS;

View File

@ -24,7 +24,7 @@ public class PlayerLoginHandler implements EventListener<PlayerLoginEvent> {
p.setRespawnPoint(Hub.INSTANCE.getSpawn());
p.sendMessage(p.getUuid().toString());
event.setSpawningInstance(Hub.INSTANCE);
SkinCache.applySkin(p);
//SkinCache.applySkin(p);
if(p.getUsername().equalsIgnoreCase("minetec"))

View File

@ -1,8 +1,10 @@
package eu.mhsl.minenet.minigames.instance.game;
import eu.mhsl.minenet.minigames.instance.MineNetInstance;
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.stateless.config.GameFactory;
import eu.mhsl.minenet.minigames.instance.game.stateless.config.Option;
import eu.mhsl.minenet.minigames.message.Icon;
import eu.mhsl.minenet.minigames.message.type.ChatMessage;
import eu.mhsl.minenet.minigames.util.CommonEventHandles;
import eu.mhsl.minenet.minigames.instance.Spawnable;
import eu.mhsl.minenet.minigames.instance.room.Room;
@ -46,11 +48,17 @@ public abstract class Game extends MineNetInstance implements Spawnable {
.addListener(ItemDropEvent.class, this::onItemDrop);
}
public static Game initialize(GameFactory factory, List<Option<?>> options, Player owner) {
Game game = factory.manufacture(options);
Room.getRoom(owner).moveMembersToGame(game);
game.load();
return game;
public static void initialize(GameFactory factory, List<Option<?>> options, Player owner) {
try {
Game game = factory.manufacture(options);
Room.getRoom(owner).moveMembersToGame(game);
game.load();
} catch (Exception e) {
new ChatMessage(Icon.ERROR).appendStatic("Instance crashed:" + e.getMessage()).send(owner);
e.printStackTrace();
}
}
/**
@ -93,7 +101,10 @@ public abstract class Game extends MineNetInstance implements Spawnable {
}, TaskSchedule.seconds(10), TaskSchedule.stop());
}
protected void onLoad(CompletableFuture<Void> callback) {}
protected void onLoad(CompletableFuture<Void> callback) {
callback.complete(null);
}
protected void onStart() {}
protected void onStop() {}
protected void onUnload() {}

View File

@ -1,17 +1,19 @@
package eu.mhsl.minenet.minigames.instance.game;
import eu.mhsl.minenet.minigames.instance.game.minigame.config.GameFactory;
import eu.mhsl.minenet.minigames.instance.game.minigame.types.bedwars.BedwarsFactory;
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;
import eu.mhsl.minenet.minigames.instance.game.stateless.config.GameFactory;
import eu.mhsl.minenet.minigames.instance.game.stateless.types.bedwars.BedwarsFactory;
import eu.mhsl.minenet.minigames.instance.game.stateless.types.deathcube.DeathcubeFactory;
import eu.mhsl.minenet.minigames.instance.game.stateless.types.minerun.MinerunFactory;
import eu.mhsl.minenet.minigames.instance.game.stateless.types.stickfight.StickFightFactory;
import eu.mhsl.minenet.minigames.instance.game.stateless.types.towerdefense.TowerdefenseFactory;
import eu.mhsl.minenet.minigames.instance.game.stateless.types.trafficlightrace.TrafficLightRaceFactory;
public enum GameList {
DEATHCUBE(new DeathcubeFactory(), GameType.OTHER),
STICKFIGHT(new StickFightFactory(), GameType.PVP),
MINERUN(new MinerunFactory(), GameType.PVE),
TRAFFICLIGHTRACE(new TrafficLightRaceFactory(), GameType.OTHER),
TOWERDEFENSE(new TowerdefenseFactory(), GameType.PVE),
BEDWARS(new BedwarsFactory(), GameType.PVP);
private final GameFactory factory;

View File

@ -1,10 +0,0 @@
package eu.mhsl.minenet.minigames.instance.game.minigame.types.bedwars;
import eu.mhsl.minenet.minigames.instance.Dimension;
import eu.mhsl.minenet.minigames.instance.game.minigame.Minigame;
public class Bedwars extends Minigame {
public Bedwars() {
super(Dimension.OVERWORLD.DIMENSION, "Bedwars");
}
}

View File

@ -1,4 +1,4 @@
package eu.mhsl.minenet.minigames.instance.game.minigame;
package eu.mhsl.minenet.minigames.instance.game.stateless;
import eu.mhsl.minenet.minigames.instance.game.Game;
import eu.mhsl.minenet.minigames.message.Countdown;
@ -16,14 +16,14 @@ import net.minestom.server.world.DimensionType;
import java.time.Duration;
import java.util.concurrent.CompletableFuture;
public class Minigame extends Game {
public class StatelessGame extends Game {
private final String name;
private final Score score = new Score(this);
private int timeLimit = 0;
private int timePlayed = 0;
private final boolean preventExit = false;
public Minigame(DimensionType dimensionType, String gameName) {
public StatelessGame(DimensionType dimensionType, String gameName) {
super(dimensionType);
this.name = gameName;

View File

@ -1,4 +1,4 @@
package eu.mhsl.minenet.minigames.instance.game.minigame.config;
package eu.mhsl.minenet.minigames.instance.game.stateless.config;
import java.util.ArrayList;

View File

@ -1,9 +1,9 @@
package eu.mhsl.minenet.minigames.instance.game.minigame.config;
package eu.mhsl.minenet.minigames.instance.game.stateless.config;
import eu.mhsl.minenet.minigames.instance.game.Game;
import eu.mhsl.minenet.minigames.instance.game.minigame.config.restriction.Restriction;
import eu.mhsl.minenet.minigames.instance.game.minigame.config.restriction.RestrictionData;
import eu.mhsl.minenet.minigames.instance.game.minigame.config.restriction.RestrictionHandler;
import eu.mhsl.minenet.minigames.instance.game.stateless.config.restriction.Restriction;
import eu.mhsl.minenet.minigames.instance.game.stateless.config.restriction.RestrictionData;
import eu.mhsl.minenet.minigames.instance.game.stateless.config.restriction.RestrictionHandler;
import eu.mhsl.minenet.minigames.message.component.TranslatedComponent;
import eu.mhsl.minenet.minigames.shared.inventory.InteractableInventory;
import eu.mhsl.minenet.minigames.util.InventoryItemAlignment;
@ -12,6 +12,7 @@ import net.kyori.adventure.sound.Sound;
import net.kyori.adventure.text.format.NamedTextColor;
import net.minestom.server.MinecraftServer;
import net.minestom.server.entity.Player;
import net.minestom.server.event.EventListener;
import net.minestom.server.event.instance.AddEntityToInstanceEvent;
import net.minestom.server.event.instance.RemoveEntityFromInstanceEvent;
import net.minestom.server.inventory.InventoryType;

View File

@ -1,7 +1,7 @@
package eu.mhsl.minenet.minigames.instance.game.minigame.config;
package eu.mhsl.minenet.minigames.instance.game.stateless.config;
import eu.mhsl.minenet.minigames.instance.game.minigame.Minigame;
import eu.mhsl.minenet.minigames.instance.game.minigame.config.restriction.RestrictionHandler;
import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame;
import eu.mhsl.minenet.minigames.instance.game.stateless.config.restriction.RestrictionHandler;
import eu.mhsl.minenet.minigames.message.component.TranslatedComponent;
import net.minestom.server.item.Material;
@ -11,7 +11,9 @@ import java.util.Map;
public interface GameFactory {
TranslatedComponent name();
ConfigManager configuration();
default ConfigManager configuration() {
return null;
}
default RestrictionHandler globalRestrictions() {
return new RestrictionHandler();
}
@ -23,9 +25,9 @@ public interface GameFactory {
return TranslatedComponent.byId("GameFactory#missingDescription");
}
Minigame manufacture(Map<String, Option<?>> configuration);
StatelessGame manufacture(Map<String, Option<?>> configuration) throws Exception;
default Minigame manufacture(List<Option<?>> configuration) {
default StatelessGame manufacture(List<Option<?>> configuration) throws Exception {
if(configuration == null) return manufacture();
Map<String, Option<?>> cnf = new HashMap<>();
@ -34,7 +36,7 @@ public interface GameFactory {
return manufacture(cnf);
}
default Minigame manufacture() {
default StatelessGame manufacture() throws Exception {
if(this.configuration() == null) return manufacture(List.of());
return manufacture(this.configuration().getAll());

View File

@ -1,6 +1,6 @@
package eu.mhsl.minenet.minigames.instance.game.minigame.config;
package eu.mhsl.minenet.minigames.instance.game.stateless.config;
import eu.mhsl.minenet.minigames.instance.game.minigame.config.restriction.RestrictionHandler;
import eu.mhsl.minenet.minigames.instance.game.stateless.config.restriction.RestrictionHandler;
import eu.mhsl.minenet.minigames.message.component.TranslatedComponent;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;

View File

@ -1,6 +1,6 @@
package eu.mhsl.minenet.minigames.instance.game.minigame.config.common;
package eu.mhsl.minenet.minigames.instance.game.stateless.config.common;
import eu.mhsl.minenet.minigames.instance.game.minigame.config.Option;
import eu.mhsl.minenet.minigames.instance.game.stateless.config.Option;
import eu.mhsl.minenet.minigames.message.component.TranslatedComponent;
import net.minestom.server.item.Material;

View File

@ -1,6 +1,6 @@
package eu.mhsl.minenet.minigames.instance.game.minigame.config.common;
package eu.mhsl.minenet.minigames.instance.game.stateless.config.common;
import eu.mhsl.minenet.minigames.instance.game.minigame.config.Option;
import eu.mhsl.minenet.minigames.instance.game.stateless.config.Option;
import eu.mhsl.minenet.minigames.message.component.TranslatedComponent;
import net.minestom.server.item.Material;

View File

@ -1,4 +1,4 @@
package eu.mhsl.minenet.minigames.instance.game.minigame.config.restriction;
package eu.mhsl.minenet.minigames.instance.game.stateless.config.restriction;
public interface IRestriction {

View File

@ -1,9 +1,9 @@
package eu.mhsl.minenet.minigames.instance.game.minigame.config.restriction;
package eu.mhsl.minenet.minigames.instance.game.stateless.config.restriction;
import eu.mhsl.minenet.minigames.message.component.TranslatedComponent;
public record Restriction(TranslatedComponent name, TranslatedComponent description, TranslatedComponent warnMessage,
eu.mhsl.minenet.minigames.instance.game.minigame.config.restriction.Restriction.Type type) {
eu.mhsl.minenet.minigames.instance.game.stateless.config.restriction.Restriction.Type type) {
public Restriction(TranslatedComponent name, TranslatedComponent description, TranslatedComponent warnMessage, Type type) {
this.name = name;
this.description = description;

View File

@ -1,4 +1,4 @@
package eu.mhsl.minenet.minigames.instance.game.minigame.config.restriction;
package eu.mhsl.minenet.minigames.instance.game.stateless.config.restriction;
import eu.mhsl.minenet.minigames.instance.room.Room;

View File

@ -1,4 +1,4 @@
package eu.mhsl.minenet.minigames.instance.game.minigame.config.restriction;
package eu.mhsl.minenet.minigames.instance.game.stateless.config.restriction;
import eu.mhsl.minenet.minigames.message.component.TranslatedComponent;

View File

@ -1,8 +1,8 @@
package eu.mhsl.minenet.minigames.instance.game.minigame.config.restriction.common;
package eu.mhsl.minenet.minigames.instance.game.stateless.config.restriction.common;
import eu.mhsl.minenet.minigames.instance.game.minigame.config.restriction.IRestriction;
import eu.mhsl.minenet.minigames.instance.game.minigame.config.restriction.Restriction;
import eu.mhsl.minenet.minigames.instance.game.minigame.config.restriction.RestrictionData;
import eu.mhsl.minenet.minigames.instance.game.stateless.config.restriction.IRestriction;
import eu.mhsl.minenet.minigames.instance.game.stateless.config.restriction.Restriction;
import eu.mhsl.minenet.minigames.instance.game.stateless.config.restriction.RestrictionData;
import eu.mhsl.minenet.minigames.message.component.TranslatedComponent;
public class MaximalPlayeramountGameRestriction implements IRestriction {

View File

@ -1,8 +1,8 @@
package eu.mhsl.minenet.minigames.instance.game.minigame.config.restriction.common;
package eu.mhsl.minenet.minigames.instance.game.stateless.config.restriction.common;
import eu.mhsl.minenet.minigames.instance.game.minigame.config.restriction.IRestriction;
import eu.mhsl.minenet.minigames.instance.game.minigame.config.restriction.Restriction;
import eu.mhsl.minenet.minigames.instance.game.minigame.config.restriction.RestrictionData;
import eu.mhsl.minenet.minigames.instance.game.stateless.config.restriction.IRestriction;
import eu.mhsl.minenet.minigames.instance.game.stateless.config.restriction.Restriction;
import eu.mhsl.minenet.minigames.instance.game.stateless.config.restriction.RestrictionData;
import eu.mhsl.minenet.minigames.message.component.TranslatedComponent;
public class MinimalPlayeramountGameRestriction implements IRestriction {

View File

@ -0,0 +1,122 @@
package eu.mhsl.minenet.minigames.instance.game.stateless.types.bedwars;
import eu.mhsl.minenet.minigames.Resource;
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.bedwars.data.BedwarsTeam;
import eu.mhsl.minenet.minigames.message.type.ActionBarMessage;
import eu.mhsl.minenet.minigames.util.MaterialUtil;
import eu.mhsl.minenet.minigames.util.Position;
import net.kyori.adventure.text.Component;
import net.md_5.bungee.config.Configuration;
import net.md_5.bungee.config.ConfigurationProvider;
import net.md_5.bungee.config.YamlConfiguration;
import net.minestom.server.coordinate.Point;
import net.minestom.server.coordinate.Pos;
import net.minestom.server.entity.ItemEntity;
import net.minestom.server.entity.Player;
import net.minestom.server.event.item.ItemDropEvent;
import net.minestom.server.event.item.PickupItemEvent;
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.instance.AnvilLoader;
import net.minestom.server.item.ItemStack;
import net.minestom.server.item.Material;
import net.minestom.server.timer.ExecutionType;
import net.minestom.server.timer.TaskSchedule;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.util.*;
public class Bedwars extends StatelessGame {
List<Point> placedBlocks = new ArrayList<>();
List<BedwarsTeam> teams = new ArrayList<>();
public Bedwars() throws IOException {
super(Dimension.OVERWORLD.DIMENSION, "Bedwars");
setChunkLoader(new AnvilLoader(Resource.GAME_MAP.getPath().resolve("bedwars/test")));
Configuration config = ConfigurationProvider.getProvider(YamlConfiguration.class).load(Resource.GAME_MAP.getPath().resolve("bedwars/test/config.yml").toFile());
List<String> teamNames = config.getStringList("setup.teams");
teamNames.forEach(teamName -> {
String path = "teams." + teamName;
teams.add(new BedwarsTeam(
config.getString(path + ".name"),
Position.getPosFromCommaSeparated(config.getString(path + ".pos.spawn")),
Position.getPosFromCommaSeparated(config.getString(path + ".pos.spawner")),
config.getStringList(path + ".pos.bed").stream().map(Position::getPosFromCommaSeparated).toList().toArray(new Pos[0]),
MaterialUtil.fromString(config.getString(path + ".material.block"), Material.BLACK_WOOL)
));
});
eventNode().addListener(PickupItemEvent.class, pickupItemEvent -> {
if(pickupItemEvent.getEntity() instanceof Player p) {
p.getInventory().addItemStack(pickupItemEvent.getItemStack());
}
});
}
@Override
protected void onItemDrop(@NotNull ItemDropEvent itemDropEvent) {
itemDropEvent.setCancelled(false);
}
@Override
protected void onStart() {
scheduler().submitTask(() -> {
if(!isRunning) return TaskSchedule.stop();
teams.forEach(bedwarsTeam -> {
ItemEntity item = new ItemEntity(ItemStack.of(bedwarsTeam.getBlock()));
item.setNoGravity(true);
item.setInstance(this, bedwarsTeam.getSpawner());
});
return TaskSchedule.stop();
}, ExecutionType.SYNC);
}
@Override
protected void onBlockPlace(@NotNull PlayerBlockPlaceEvent playerBlockPlaceEvent) {
placedBlocks.add(playerBlockPlaceEvent.getBlockPosition());
}
@Override
protected void onBlockBreak(@NotNull PlayerBlockBreakEvent playerBlockBreakEvent) {
if(!placedBlocks.contains(playerBlockBreakEvent.getBlockPosition())) playerBlockBreakEvent.setCancelled(true);
teams.forEach(bedwarsTeam -> {
if(Arrays.stream(bedwarsTeam.getBed()).anyMatch(pos -> pos.sameBlock(playerBlockBreakEvent.getBlockPosition())))
breakBed(bedwarsTeam);
});
if(playerBlockBreakEvent.isCancelled())
new ActionBarMessage().appendStatic(Component.text("BLAH")).send(playerBlockBreakEvent.getPlayer());
}
@Override
protected void onPlayerMove(@NotNull PlayerMoveEvent playerMoveEvent) {
if(playerMoveEvent.getNewPosition().y() < 0) death(playerMoveEvent.getPlayer());
}
private void breakBed(BedwarsTeam team) {
team.removeBed();
for (Pos blockPos : team.getBed()) {
setBlock(blockPos, Material.AIR.block());
}
}
private void death(Player p) {
}
@Override
public Pos getSpawn() {
return new Pos(0, 13, 0);
}
}

View File

@ -1,11 +1,11 @@
package eu.mhsl.minenet.minigames.instance.game.minigame.types.bedwars;
package eu.mhsl.minenet.minigames.instance.game.stateless.types.bedwars;
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.restriction.RestrictionHandler;
import eu.mhsl.minenet.minigames.instance.game.minigame.config.restriction.common.MinimalPlayeramountGameRestriction;
import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame;
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.restriction.RestrictionHandler;
import eu.mhsl.minenet.minigames.instance.game.stateless.config.restriction.common.MinimalPlayeramountGameRestriction;
import eu.mhsl.minenet.minigames.message.component.TranslatedComponent;
import net.minestom.server.item.Material;
@ -17,15 +17,10 @@ public class BedwarsFactory implements GameFactory {
return TranslatedComponent.byId("game_Bedwars#name");
}
@Override
public ConfigManager configuration() {
return null;
}
@Override
public RestrictionHandler globalRestrictions() {
return new RestrictionHandler()
.addRestriction(new MinimalPlayeramountGameRestriction(2));
.addRestriction(new MinimalPlayeramountGameRestriction(1));
}
@Override
@ -39,7 +34,7 @@ public class BedwarsFactory implements GameFactory {
}
@Override
public Minigame manufacture(Map<String, Option<?>> configuration) {
public StatelessGame manufacture(Map<String, Option<?>> configuration) throws Exception {
return new Bedwars();
}
}

View File

@ -0,0 +1,66 @@
package eu.mhsl.minenet.minigames.instance.game.stateless.types.bedwars.data;
import net.minestom.server.coordinate.Pos;
import net.minestom.server.entity.Player;
import net.minestom.server.item.Material;
import java.util.ArrayList;
import java.util.List;
public class BedwarsTeam {
private List<Player> members = new ArrayList<>();
private final String name;
private final Pos spawn;
private final Pos spawner;
private final Pos[] bed;
private final Material block;
private boolean hasBed = true;
public BedwarsTeam(String name, Pos spawn, Pos spawner, Pos[] bed, Material block) {
this.name = name;
this.spawn = spawn;
this.spawner = spawner;
this.bed = bed;
this.block = block;
}
public void removeBed() {
this.hasBed = false;
}
public boolean isHasBed() {
return hasBed;
}
public List<Player> getMembers() {
return members;
}
public void setMembers(List<Player> members) {
this.members = members;
}
public String getName() {
return name;
}
public Pos getSpawn() {
return spawn;
}
public Pos getSpawner() {
return spawner;
}
public Pos[] getBed() {
return bed;
}
public Material getBlock() {
return block;
}
}

View File

@ -1,10 +1,13 @@
package eu.mhsl.minenet.minigames.instance.game.minigame.types.deathcube;
package eu.mhsl.minenet.minigames.instance.game.stateless.types.deathcube;
import eu.mhsl.minenet.minigames.instance.game.minigame.Minigame;
import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame;
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 io.github.bloepiloepi.pvp.config.AttackConfig;
import io.github.bloepiloepi.pvp.config.DamageConfig;
import io.github.bloepiloepi.pvp.config.PvPConfig;
import net.minestom.server.coordinate.Pos;
import net.minestom.server.event.player.PlayerMoveEvent;
import net.minestom.server.instance.batch.AbsoluteBlockBatch;
@ -12,18 +15,25 @@ import org.jetbrains.annotations.NotNull;
import java.util.concurrent.CompletableFuture;
class Deathcube extends Minigame {
class Deathcube extends StatelessGame {
final int radius;
final int height;
final int percentage;
public Deathcube(int radius, int height, int percentage) {
public Deathcube(int radius, int height, int percentage, int pvpEnabled) {
super(Dimension.THE_END.DIMENSION, "Deathcube");
this.radius = radius;
this.height = height + 49;
this.percentage = percentage;
this.setGenerator(new CircularTerrainGenerator(radius+10, true));
if(pvpEnabled == 1) eventNode().addChild(
PvPConfig.emptyBuilder()
.damage(DamageConfig.legacyBuilder().fallDamage(false))
.attack(AttackConfig.legacyBuilder().attackCooldown(true))
.build().createNode()
);
System.out.println(radius);
}

View File

@ -1,10 +1,10 @@
package eu.mhsl.minenet.minigames.instance.game.minigame.types.deathcube;
package eu.mhsl.minenet.minigames.instance.game.stateless.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.common.NumericOption;
import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame;
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.ConfigManager;
import eu.mhsl.minenet.minigames.instance.game.stateless.config.common.NumericOption;
import eu.mhsl.minenet.minigames.message.component.TranslatedComponent;
import net.minestom.server.item.Material;
@ -26,12 +26,14 @@ public class DeathcubeFactory implements GameFactory {
return new ConfigManager()
.addOption(new NumericOption("radius", Material.HEART_OF_THE_SEA, TranslatedComponent.byId("optionCommon#radius"), 10, 20, 30))
.addOption(new NumericOption("height", Material.SCAFFOLDING, TranslatedComponent.byId("optionCommon#height"), 10, 30, 50))
.addOption(new NumericOption("percentage", Material.COBWEB, TranslatedComponent.byId("game_Deathcube#optionPercentageBlocks"), 5, 7, 9, 11, 13));
.addOption(new NumericOption("percentage", Material.COBWEB, TranslatedComponent.byId("game_Deathcube#optionPercentageBlocks"), 5, 7, 9, 11, 13))
.addOption(new NumericOption("pvpEnabled", Material.STICK, TranslatedComponent.byId("game_Deathcube#optionPvpEnabled"), 1, 0));
}
@Override
public Minigame manufacture(Map<String, Option<?>> configuration) {
return new Deathcube(configuration.get("radius").getAsInt(), configuration.get("height").getAsInt(), configuration.get("percentage").getAsInt());
public StatelessGame manufacture(Map<String, Option<?>> configuration) {
return new Deathcube(configuration.get("radius").getAsInt(), configuration.get("height").getAsInt(), configuration.get("percentage").getAsInt(), configuration.get("pvpEnabled").getAsInt());
}
@Override

View File

@ -1,6 +1,6 @@
package eu.mhsl.minenet.minigames.instance.game.minigame.types.minerun;
package eu.mhsl.minenet.minigames.instance.game.stateless.types.minerun;
import eu.mhsl.minenet.minigames.instance.game.minigame.Minigame;
import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame;
import eu.mhsl.minenet.minigames.message.type.ActionBarMessage;
import eu.mhsl.minenet.minigames.util.BatchUtil;
import eu.mhsl.minenet.minigames.util.Intersect;
@ -22,7 +22,7 @@ import org.jetbrains.annotations.NotNull;
import java.util.*;
import java.util.concurrent.CompletableFuture;
class Minerun extends Minigame {
class Minerun extends StatelessGame {
private int minePercentage = 50;
private int width = 100;

View File

@ -1,10 +1,10 @@
package eu.mhsl.minenet.minigames.instance.game.minigame.types.minerun;
package eu.mhsl.minenet.minigames.instance.game.stateless.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.common.NumericOption;
import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame;
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.message.component.TranslatedComponent;
import net.minestom.server.item.Material;
@ -25,7 +25,7 @@ public class MinerunFactory implements GameFactory {
}
@Override
public Minigame manufacture(Map<String, Option<?>> configuration) {
public StatelessGame manufacture(Map<String, Option<?>> configuration) {
return new Minerun(configuration.get("width").getAsInt(), configuration.get("length").getAsInt(), configuration.get("percentage").getAsInt());
}

View File

@ -1,13 +1,13 @@
package eu.mhsl.minenet.minigames.instance.game.minigame.types.stickfight;
package eu.mhsl.minenet.minigames.instance.game.stateless.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 eu.mhsl.minenet.minigames.instance.game.minigame.config.common.NumericOption;
import eu.mhsl.minenet.minigames.instance.game.minigame.config.restriction.RestrictionHandler;
import eu.mhsl.minenet.minigames.instance.game.minigame.config.restriction.common.MaximalPlayeramountGameRestriction;
import eu.mhsl.minenet.minigames.instance.game.minigame.config.restriction.common.MinimalPlayeramountGameRestriction;
import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame;
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.game.stateless.config.restriction.RestrictionHandler;
import eu.mhsl.minenet.minigames.instance.game.stateless.config.restriction.common.MaximalPlayeramountGameRestriction;
import eu.mhsl.minenet.minigames.instance.game.stateless.config.restriction.common.MinimalPlayeramountGameRestriction;
import eu.mhsl.minenet.minigames.message.component.TranslatedComponent;
import net.minestom.server.item.Material;
@ -38,7 +38,7 @@ public class StickFightFactory implements GameFactory {
}
@Override
public Minigame manufacture(Map<String, Option<?>> configuration) {
public StatelessGame manufacture(Map<String, Option<?>> configuration) {
return new Stickfight();
}

View File

@ -1,7 +1,7 @@
package eu.mhsl.minenet.minigames.instance.game.minigame.types.stickfight;
package eu.mhsl.minenet.minigames.instance.game.stateless.types.stickfight;
import eu.mhsl.minenet.minigames.instance.Dimension;
import eu.mhsl.minenet.minigames.instance.game.minigame.Minigame;
import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame;
import eu.mhsl.minenet.minigames.util.BatchUtil;
import eu.mhsl.minenet.minigames.world.generator.terrain.CircularTerrainGenerator;
import io.github.bloepiloepi.pvp.config.*;
@ -15,7 +15,7 @@ import org.jetbrains.annotations.NotNull;
import java.util.concurrent.CompletableFuture;
public class Stickfight extends Minigame {
public class Stickfight extends StatelessGame {
public Stickfight() {
super(Dimension.OVERWORLD.DIMENSION, "Stickfight");

View File

@ -0,0 +1,24 @@
package eu.mhsl.minenet.minigames.instance.game.stateless.types.towerdefense;
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.towerdefense.generator.MazeGenerator;
import net.minestom.server.entity.Player;
import net.minestom.server.item.ItemStack;
import net.minestom.server.item.Material;
public class Towerdefense extends StatelessGame {
public Towerdefense() {
super(Dimension.NETHER.DIMENSION, "Towerdefense");
setGenerator(new MazeGenerator());
}
@Override
protected boolean onPlayerJoin(Player p) {
p.getInventory().setItemStack(1, ItemStack.of(Material.ARMOR_STAND));
return false;
}
}

View File

@ -0,0 +1,30 @@
package eu.mhsl.minenet.minigames.instance.game.stateless.types.towerdefense;
import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame;
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.message.component.TranslatedComponent;
import net.minestom.server.item.Material;
import java.util.Map;
public class TowerdefenseFactory implements GameFactory {
@Override
public TranslatedComponent name() {
return TranslatedComponent.byId("game_Towerdefense#name");
}
@Override
public Material symbol() {
return Material.ARMOR_STAND;
}
@Override
public TranslatedComponent description() {
return TranslatedComponent.byId("game_Towerdefense#description");
}
@Override
public StatelessGame manufacture(Map<String, Option<?>> configuration) {
return new Towerdefense();
}
}

View File

@ -0,0 +1,13 @@
package eu.mhsl.minenet.minigames.instance.game.stateless.types.towerdefense.generator;
import net.minestom.server.instance.block.Block;
import net.minestom.server.instance.generator.GenerationUnit;
import net.minestom.server.instance.generator.Generator;
import org.jetbrains.annotations.NotNull;
public class MazeGenerator implements Generator {
@Override
public void generate(@NotNull GenerationUnit unit) {
unit.modifier().fillHeight(0, 1, Block.BLACK_WOOL);
}
}

View File

@ -1,4 +1,4 @@
package eu.mhsl.minenet.minigames.instance.game.minigame.types.trafficlightrace;
package eu.mhsl.minenet.minigames.instance.game.stateless.types.trafficlightrace;
import net.minestom.server.item.ItemStack;
import net.minestom.server.item.Material;

View File

@ -1,6 +1,6 @@
package eu.mhsl.minenet.minigames.instance.game.minigame.types.trafficlightrace;
package eu.mhsl.minenet.minigames.instance.game.stateless.types.trafficlightrace;
import eu.mhsl.minenet.minigames.instance.game.minigame.Minigame;
import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame;
import eu.mhsl.minenet.minigames.util.BatchUtil;
import eu.mhsl.minenet.minigames.instance.Dimension;
import net.minestom.server.coordinate.Vec;
@ -13,7 +13,7 @@ import org.jetbrains.annotations.NotNull;
import java.util.concurrent.CompletableFuture;
class TrafficLightRace extends Minigame {
class TrafficLightRace extends StatelessGame {
private LightPhase phase = LightPhase.RED;
private int phaseCounter = 1;

View File

@ -1,9 +1,9 @@
package eu.mhsl.minenet.minigames.instance.game.minigame.types.trafficlightrace;
package eu.mhsl.minenet.minigames.instance.game.stateless.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 eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame;
import eu.mhsl.minenet.minigames.instance.game.stateless.config.GameFactory;
import eu.mhsl.minenet.minigames.instance.game.stateless.config.ConfigManager;
import eu.mhsl.minenet.minigames.instance.game.stateless.config.Option;
import eu.mhsl.minenet.minigames.message.component.TranslatedComponent;
import net.minestom.server.item.Material;
@ -21,7 +21,7 @@ public class TrafficLightRaceFactory implements GameFactory {
}
@Override
public Minigame manufacture(Map<String, Option<?>> configuration) {
public StatelessGame manufacture(Map<String, Option<?>> configuration) {
return new TrafficLightRace();
}

View File

@ -17,6 +17,9 @@ import net.minestom.server.entity.Player;
import net.minestom.server.event.player.PlayerBlockBreakEvent;
import net.minestom.server.event.player.PlayerDisconnectEvent;
import net.minestom.server.instance.AnvilLoader;
import team.unnamed.hephaestus.ModelDataCursor;
import team.unnamed.hephaestus.reader.ModelReader;
import team.unnamed.hephaestus.reader.blockbench.BBModelReader;
import java.util.*;
import java.util.logging.Logger;
@ -78,6 +81,7 @@ public class Room extends MineNetInstance implements Spawnable {
setOwner(owner);
new GameSelector().setInstance(this, new Pos(0.5, 16, 9.5));
}
public Player getOwner() {

View File

@ -2,8 +2,8 @@ package eu.mhsl.minenet.minigames.instance.room.inventory;
import eu.mhsl.minenet.minigames.instance.game.GameList;
import eu.mhsl.minenet.minigames.instance.game.GameType;
import eu.mhsl.minenet.minigames.instance.game.minigame.config.GameConfigurationInventory;
import eu.mhsl.minenet.minigames.instance.game.minigame.config.GameFactory;
import eu.mhsl.minenet.minigames.instance.game.stateless.config.GameConfigurationInventory;
import eu.mhsl.minenet.minigames.instance.game.stateless.config.GameFactory;
import eu.mhsl.minenet.minigames.instance.room.Room;
import eu.mhsl.minenet.minigames.message.component.TranslatedComponent;
import eu.mhsl.minenet.minigames.shared.inventory.InteractableInventory;

View File

@ -7,6 +7,6 @@ public class DummyLang extends Lang {
@Override
public String getEntry(String key) {
return "translation:" + key;
return "missingI18n:" + key;
}
}

View File

@ -7,6 +7,7 @@ import net.minestom.server.event.entity.EntityAttackEvent;
import net.minestom.server.event.instance.AddEntityToInstanceEvent;
import net.minestom.server.event.instance.RemoveEntityFromInstanceEvent;
import net.minestom.server.event.player.PlayerEntityInteractEvent;
import net.minestom.server.event.player.PlayerMoveEvent;
import org.jetbrains.annotations.NotNull;
@ -24,8 +25,13 @@ public class InteractableEntity extends EntityCreature {
.addListener(AddEntityToInstanceEvent.class, this::onSpawn)
.addListener(RemoveEntityFromInstanceEvent.class, this::onDespawn)
.addListener(PlayerEntityInteractEvent.class, this::onInteract)
.addListener(PlayerEntityInteractEvent.class, this::onInteract) //TODO Why are some of these listeners not working?
.addListener(EntityAttackEvent.class, this::onAttack);
System.out.println(eventNode().getChildren());
System.out.println(eventNode().getParent().getChildren());
}
private void setInstanceEvent(@NotNull AddEntityToInstanceEvent addEntityToInstanceEvent) {
@ -34,16 +40,19 @@ public class InteractableEntity extends EntityCreature {
}
addEntityToInstanceEvent.getInstance().eventNode()
.addListener(PlayerMoveEvent.class, playerMoveEvent -> {
//TODO might be expensive
if(this.position.distance(playerMoveEvent.getNewPosition()) < 5)
this.lookAt(playerMoveEvent.getPlayer());
})
.addListener(PlayerEntityInteractEvent.class, playerEntityInteractEvent -> {
if(playerEntityInteractEvent.getTarget() == this) {
onInteract(playerEntityInteractEvent);
this.lookAt(playerEntityInteractEvent.getPlayer());
}
})
.addListener(EntityAttackEvent.class, entityAttackEvent -> {
if(entityAttackEvent.getTarget() == this) {
onAttack(entityAttackEvent);
this.lookAt(entityAttackEvent.getEntity());
}
});
}

View File

@ -0,0 +1,9 @@
package eu.mhsl.minenet.minigames.util;
import net.minestom.server.item.Material;
public class MaterialUtil {
public static Material fromString(String name, Material def) {
return Material.values().stream().filter(material -> material.name().equals(name)).findFirst().orElse(def);
}
}

View File

@ -1,5 +1,26 @@
package eu.mhsl.minenet.minigames.util;
import net.minestom.server.coordinate.Pos;
import java.util.InputMismatchException;
public class Position {
public static final double PIXEL = 0.0625;
public static Pos getPosFromCommaSeparated(String input) {
String[] coordinates = input.split(",");
if(coordinates.length < 3) throw new InputMismatchException("Coordinates have to contain at least x, y and z");
float x = Float.parseFloat(coordinates[0]);
float y = Float.parseFloat(coordinates[1]);
float z = Float.parseFloat(coordinates[2]);
if(coordinates.length > 4) {
float yaw = Float.parseFloat(coordinates[3]);
float pitch = Float.parseFloat(coordinates[4]);
return new Pos(x, y, z, yaw, pitch);
}
return new Pos(x, y, z);
}
}

View File

@ -1 +1 @@
,elias,ELIAS-PC,03.10.2022 16:40,file:///home/elias/.config/libreoffice/4;
,elias,ELIAS-PC,07.01.2023 22:39,file:///home/elias/.config/libreoffice/4;

View File

@ -10,6 +10,13 @@ welcome;Welcome!;Willkommen!
back;Back;Zurück
forward;Next;Nächste
;;
ns:tablist#UNUSED;;
title;MineNet Network;MineNet Servernetzwerk
players;Players;Spieler
ram;RAM;RAM
tick;TICK;TICK
;;
;;
ns:GameType#;;
other;Other games;Andere Spiele
other_description;Games which does not fit into other Categories;Spiele welche nicht in die anderen Kategorien passen
@ -29,8 +36,8 @@ join_notFound;Lobby not found: ;Lobby konnte nicht gefunden werden:
;;
ns:score#;;
result;Results;Ergebnisse
thanks;Thank you for Playing;Danke fürs spielen
;;
thanks;Thank you for Playing;Danke für‘s spielen
finish;Finish;Fertig
;;
ns:restriction#;;
fail;Some requirements are not met;Bedinungen sind nicht erfüllt
@ -47,13 +54,6 @@ length;Length;Länge
height;Height;Höhe
radius;Radius;Radius
;;
;;
;;
;;
;;
;;
;;
;;
ns:room#;;
invTitle;Select a Minigame;Wähle einen Spielmodus
noOption;No options here;Keine Optionen hier
@ -79,3 +79,7 @@ description;Push your opponents off the Bridge;Stoße deine Gegener von der Brü
ns:game_TrafficlightRace#;;
name;Red light green light;Rotes licht, Grünes licht
description;Only go forward if the Trafficlights show green;Gehe nur bei Grün vorran
;;
ns:game_Towerdefense#;;
name;Towerdefense;Towerdefense
description;Protect the path ????;??????

1 map en_us de_de
10 back Back Zurück
11 forward Next Nächste
12
13 ns:tablist#UNUSED
14 title MineNet Network MineNet Servernetzwerk
15 players Players Spieler
16 ram RAM RAM
17 tick TICK TICK
18
19
20 ns:GameType#
21 other Other games Andere Spiele
22 other_description Games which does not fit into other Categories Spiele welche nicht in die anderen Kategorien passen
36
37 ns:score#
38 result Results Ergebnisse
39 thanks Thank you for Playing Danke für‘s spielen Danke für‘s spielen
40 finish Finish Fertig
41
42 ns:restriction#
43 fail Some requirements are not met Bedinungen sind nicht erfüllt
54 height Height Höhe
55 radius Radius Radius
56
57 ns:room#
58 invTitle Select a Minigame Wähle einen Spielmodus
59 noOption No options here Keine Optionen hier
79 ns:game_TrafficlightRace#
80 name Red light green light Rotes licht, Grünes licht
81 description Only go forward if the Trafficlights show green Gehe nur bei Grün vorran
82
83 ns:game_Towerdefense#
84 name Towerdefense Towerdefense
85 description Protect the path ???? ??????

View File

@ -0,0 +1,29 @@
setup:
teams:
- 'blue'
- 'orange'
teams:
blue:
name: 'blue'
pos:
spawn: '31.5,11,0.5,90,0'
spawner: '31.5,11,0.5'
bed:
- '32,11,0'
- '33,11,0'
material:
block: 'BLUE_WOOL'
bed: 'BLUE_BED'
orange:
name: "orange"
pos:
spawn: '-31.5,11,0.5,-90,0'
spawner: '-31.5,11,0.5'
bed:
- '-33,11,0'
- '-34,11,0'
material:
block: 'ORANGE_WOOL'
bed: 'ORANGE_BED'