Archiviert
13
0

tower-generator #6

Zusammengeführt
YoyoNow hat 16 Commits von tower-generator nach master 2023-09-23 21:29:06 +02:00 zusammengeführt
19 geänderte Dateien mit 728 neuen und 59 gelöschten Zeilen

Datei anzeigen

@ -15,11 +15,11 @@ tower:
doors:
1:
x: 138
y: 229
y: 228
z: 858
2:
x: 137
y: 229
y: 228
z: 858
lavaY: 255
laveSpace: 7
@ -32,7 +32,7 @@ tower:
minX: 93
maxX: 167
minZ: 813
maxZ: 863
maxZ: 883
winconditions:
- LAST_REMAINING

154
configs/steamtower.yml Normale Datei
Datei anzeigen

@ -0,0 +1,154 @@
tower:
regions:
1:
minX: 0
maxX: 69
minZ: 0
maxZ: 79
2:
minX: 54
maxX: 74
minZ: 63
maxZ: 84
escapeHeight: 1
spawn:
x: 66
y: 12
z: 71
yaw: 180.0
pitch: 0.0
doors: []
keys: []
lavaY: 62
laveSpace: 8
meltingBlocks:
SPRUCE_TRAPDOOR: 10
SMOOTH_STONE: 120
SMOOTH_STONE_SLAB: 60
STONE_BRICK_SLAB: 60
ANDESITE: 120
ANDESITE_SLAB: 60
ANDESITE_WALL: 45
JUKEBOX: 10
IRON_BLOCK: 240
IRON_DOOR: 60
IRON_TRAPDOOR: 60
QUARTZ_SLAB: 30
QUARTZ_STAIRS: 30
SMOOTH_RED_SANDSTONE_STAIRS: 30
SMOOTH_RED_SANDSTONE_SLAB: 30
END_STONE: 240
REDSTONE_LAMP: 30
GLASS: 30
GLASS_PANE: 3
TINTED_GLASS: 30
WHITE_STAINED_GLASS: 30
WHITE_STAINED_GLASS_PANE: 3
ORANGE_STAINED_GLASS: 30
ORANGE_STAINED_GLASS_PANE: 3
MAGENTA_STAINED_GLASS: 30
MAGENTA_STAINED_GLASS_PANE: 3
LIGHT_BLUE_STAINED_GLASS: 30
LIGHT_BLUE_STAINED_GLASS_PANE: 3
YELLOW_STAINED_GLASS: 30
YELLOW_STAINED_GLASS_PANE: 3
LIME_STAINED_GLASS: 30
LIME_STAINED_GLASS_PANE: 3
PINK_STAINED_GLASS: 30
PINK_STAINED_GLASS_PANE: 3
GRAY_STAINED_GLASS: 30
GRAY_STAINED_GLASS_PANE: 3
LIGHT_GRAY_STAINED_GLASS: 30
LIGHT_GRAY_STAINED_GLASS_PANE: 3
CYAN_STAINED_GLASS: 30
CYAN_STAINED_GLASS_PANE: 3
PURPLE_STAINED_GLASS: 30
PURPLE_STAINED_GLASS_PANE: 3
BLUE_STAINED_GLASS: 30
BLUE_STAINED_GLASS_PANE: 3
BROWN_STAINED_GLASS: 30
BROWN_STAINED_GLASS_PANE: 3
GREEN_STAINED_GLASS: 30
GREEN_STAINED_GLASS_PANE: 3
RED_STAINED_GLASS: 30
RED_STAINED_GLASS_PANE: 3
BLACK_STAINED_GLASS: 30
BLACK_STAINED_GLASS_PANE: 3
towerGenerator:
x: 0
y: 12
z: 0
minHeight: 190
maxHeight: 240
schematicType: steamtower
fillRegions:
1:
minX: 31
minZ: 29
maxX: 38
maxZ: 34
percentage: 0.25
material: MANGROVE_ROOTS
2:
minX: 31
minZ: 46
maxX: 38
maxZ: 51
percentage: 0.25
material: MANGROVE_ROOTS
minNoBombFloors: 2
maxNoBombFloors: 7
minBombs: 20
maxBombs: 60
tntChance: 0.3
tntRegions:
1:
minX: 3
minZ: 3
maxX: 30
maxZ: 77
2:
minX: 40
minZ: 3
maxX: 67
maxZ: 77
3:
minX: 30
minZ: 3
maxX: 40
maxZ: 28
4:
minX: 30
minZ: 52
maxX: 40
maxZ: 77
keyChance: 0.8
minNoKeyFloors: 2
maxNoKeyFloors: 7
doorBlocks:
1:
x: 36
dy: 1
z: 32
2:
x: 36
dy: 1
z: 33
3:
x: 33
dy: 1
z: 46
4:
x: 33
dy: 1
z: 47
minX: -28
maxX: 98
minZ: -27
maxZ: 107
winconditions:
- LAST_REMAINING
- LAST_OUTSIDE

Datei anzeigen

@ -31,5 +31,6 @@ KEY_NAME=
KEY_FOUND=§a{0} §7found a key§8!
GAME_TIE=§aThe game ended in a tie§8!
GAME_TIME=§a{0}:{1}
CATCH_UP_WARNING=§4!! §cYou should catch up §4!!
COMMAND_START=§aThe game will start soon§8!

Datei anzeigen

@ -30,4 +30,6 @@ GAME_TIE=
KEY_NAME=§eSchlüssel
KEY_FOUND=§a{0} §7hat einen Schlüssel gefunden§8!
CATCH_UP_WARNING=§4!! §cDu solltest aufholen §4!!
COMMAND_START=§7Das Spiel startet bald§8!

Datei anzeigen

@ -21,9 +21,12 @@ package de.steamwar.towerrun;
import de.steamwar.message.Message;
import de.steamwar.towerrun.commands.StartCommand;
import de.steamwar.towerrun.config.WorldConfig;
import de.steamwar.towerrun.countdowns.EndCountdown;
import de.steamwar.towerrun.countdowns.GameCountdown;
import de.steamwar.towerrun.countdowns.LobbyCountdown;
import de.steamwar.towerrun.game.TowerRunGame;
import de.steamwar.towerrun.generator.TowerGenerator;
import de.steamwar.towerrun.listener.GlobalListener;
import de.steamwar.towerrun.listener.IngameListener;
import de.steamwar.towerrun.listener.LobbyListener;
@ -50,6 +53,9 @@ public class TowerRun extends JavaPlugin {
@Getter
private static Message message;
@Getter
private static TowerGenerator towerGenerator = null;
@Getter
private static GameCountdown gameCountdown;
@ -59,6 +65,10 @@ public class TowerRun extends JavaPlugin {
instance = this;
message = new Message("TowerRun", getClassLoader());
if (WorldConfig.TOWER_GENERATOR_CONFIG != null) {
towerGenerator = new TowerGenerator(WorldConfig.TOWER_GENERATOR_CONFIG);
}
new LobbyListener();
new IngameListener();
new GlobalListener();
@ -68,5 +78,7 @@ public class TowerRun extends JavaPlugin {
new EndCountdown(lobbyCountdown);
new StartCommand(lobbyCountdown);
gameCountdown = new GameCountdown();
TowerRunGame.reset();
}
}

Datei anzeigen

@ -37,8 +37,10 @@ public class StartCommand extends SWCommand {
@Register
public void command(@Validator Player player) {
if (countdown.getTime() > 10) {
countdown.setOverride(true);
countdown.setTime(10);
}
TowerRun.getMessage().send("COMMAND_START", player);
}

Datei anzeigen

@ -19,6 +19,7 @@
package de.steamwar.towerrun.config;
import de.steamwar.sql.SchematicType;
import de.steamwar.towerrun.TowerRun;
import de.steamwar.towerrun.winconditions.FirstOutsideWincondition;
import de.steamwar.towerrun.winconditions.LastOutsideWincondition;
@ -28,13 +29,13 @@ import lombok.Getter;
import lombok.experimental.UtilityClass;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.util.Vector;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.*;
@UtilityClass
public class WorldConfig {
@ -53,8 +54,11 @@ public class WorldConfig {
public static final int MAP_MIN_Z;
public static final int MAP_MAX_X;
public static final int MAP_MAX_Z;
public static final Map<Material, Integer> MELTING_TIMES;
public static final TowerGeneratorConfig TOWER_GENERATOR_CONFIG;
public static final List<WinCondition> WINCONDITIONS = new ArrayList<>();
static {
WINCONDITIONS.add(new LastRemainingWincondition());
WINCONDITIONS.add(new LastOutsideWincondition());
@ -123,21 +127,31 @@ public class WorldConfig {
ESCAPE_HEIGHT = tower.getInt("escapeHeight");
SPAWN = parseLocation(tower.getConfigurationSection("spawn"));
List<ConfigurationSection> doors = tower.getConfigurationSection("doors").getKeys(false).stream()
ConfigurationSection doorSection = tower.getConfigurationSection("doors");
if (doorSection != null) {
List<ConfigurationSection> doors = doorSection.getKeys(false).stream()
.map(tower.getConfigurationSection("doors")::getConfigurationSection)
.toList();
DOORS = new Location[doors.size()];
for (int i = 0; i < doors.size(); i++) {
DOORS[i] = parseLocation(doors.get(i));
}
} else {
DOORS = new Location[0];
}
List<ConfigurationSection> keys = tower.getConfigurationSection("keys").getKeys(false).stream()
ConfigurationSection keysSection = tower.getConfigurationSection("keys");
if (keysSection != null) {
List<ConfigurationSection> keys = keysSection.getKeys(false).stream()
.map(tower.getConfigurationSection("keys")::getConfigurationSection)
.toList();
KEYS = new Location[keys.size()];
for (int i = 0; i < keys.size(); i++) {
KEYS[i] = parseLocation(keys.get(i));
}
} else {
KEYS = new Location[0];
}
LAVA_Y = tower.getInt("lavaY");
LAVE_SPACE = tower.getInt("laveSpace");
@ -147,8 +161,26 @@ public class WorldConfig {
MAP_MAX_X = config.getInt("maxX");
MAP_MAX_Z = config.getInt("maxZ");
ConfigurationSection meltingBlocksSection = tower.getConfigurationSection("meltingBlocks");
if (meltingBlocksSection != null) {
Map<Material, Integer> meltingTimes = new HashMap<>();
meltingBlocksSection.getKeys(false).forEach(s -> {
meltingTimes.put(Material.valueOf(s), meltingBlocksSection.getInt(s));
});
MELTING_TIMES = Collections.unmodifiableMap(meltingTimes);
} else {
MELTING_TIMES = Collections.emptyMap();
}
ACTIVE_WINCONDITIONS = config.getStringList("winconditions");
WINCONDITIONS.stream().filter(winCondition -> ACTIVE_WINCONDITIONS.contains(winCondition.getName())).forEach(winCondition -> winCondition.setActive(true));
ConfigurationSection towerGeneratorSection = config.getConfigurationSection("towerGenerator");
if (towerGeneratorSection == null) {
TOWER_GENERATOR_CONFIG = null;
} else {
TOWER_GENERATOR_CONFIG = new TowerGeneratorConfig(towerGeneratorSection);
}
}
@Getter
@ -176,4 +208,116 @@ public class WorldConfig {
&& vector.getZ() >= min.getZ() && vector.getZ() <= max.getZ();
}
}
@Getter
public static final class TowerGeneratorConfig {
public final int x;
public final int y;
public final int z;
public final int minHeight;
public final int maxHeight;
public final int minNoBombFloors;
public final int maxNoBombFloors;
public final double tntChance;
public final int minBombs;
public final int maxBombs;
public final double keyChance;
public final int minNoKeyFloors;
public final int maxNoKeyFloors;
public final SchematicType schematicType;
public final TowerGeneratorFillRegion[] fillRegions;
public final Region[] tntRegions;
public final TowerGeneratorDoorBlock[] doorBlocks;
public TowerGeneratorConfig(ConfigurationSection section) {
x = section.getInt("x");
y = section.getInt("y");
z = section.getInt("z");
minHeight = section.getInt("minHeight");
maxHeight = section.getInt("maxHeight");
minNoBombFloors = section.getInt("minNoBombFloors");
maxNoBombFloors = section.getInt("maxNoBombFloors");
minBombs = section.getInt("minBombs");
maxBombs = section.getInt("maxBombs");
tntChance = section.getDouble("tntChance");
keyChance = section.getDouble("keyChance");
minNoKeyFloors = section.getInt("minNoKeyFloors");
maxNoKeyFloors = section.getInt("maxNoKeyFloors");
schematicType = SchematicType.fromDB(section.getString("schematicType"));
ConfigurationSection fillRegionsSection = section.getConfigurationSection("fillRegions");
if (fillRegionsSection != null) {
List<ConfigurationSection> fillRegions = fillRegionsSection.getKeys(false).stream()
.map(fillRegionsSection::getConfigurationSection)
.toList();
this.fillRegions = new TowerGeneratorFillRegion[fillRegions.size()];
for (int i = 0; i < fillRegions.size(); i++) {
this.fillRegions[i] = new TowerGeneratorFillRegion(fillRegions.get(i));
}
} else {
fillRegions = new TowerGeneratorFillRegion[0];
}
ConfigurationSection tntRegionsSection = section.getConfigurationSection("tntRegions");
if (tntRegionsSection != null) {
List<ConfigurationSection> tntRegions = tntRegionsSection.getKeys(false).stream()
.map(tntRegionsSection::getConfigurationSection)
.toList();
this.tntRegions = new Region[tntRegions.size()];
for (int i = 0; i < tntRegions.size(); i++) {
this.tntRegions[i] = new Region(tntRegions.get(i));
}
} else {
tntRegions = new Region[0];
}
ConfigurationSection doorBlocksSection = section.getConfigurationSection("doorBlocks");
if (doorBlocksSection != null) {
List<ConfigurationSection> doorBlocks = doorBlocksSection.getKeys(false).stream()
.map(doorBlocksSection::getConfigurationSection)
.toList();
this.doorBlocks = new TowerGeneratorDoorBlock[doorBlocks.size()];
for (int i = 0; i < doorBlocks.size(); i++) {
this.doorBlocks[i] = new TowerGeneratorDoorBlock(doorBlocks.get(i));
}
} else {
doorBlocks = new TowerGeneratorDoorBlock[0];
}
}
}
@Getter
public static final class TowerGeneratorFillRegion {
private final int minX;
private final int minZ;
private final int maxX;
private final int maxZ;
private final double percentage;
private final Material material;
public TowerGeneratorFillRegion(ConfigurationSection section) {
minX = section.getInt("minX");
minZ = section.getInt("minZ");
maxX = section.getInt("maxX");
maxZ = section.getInt("maxZ");
percentage = section.getDouble("percentage");
material = Material.valueOf(section.getString("material"));
}
}
@Getter
public static final class TowerGeneratorDoorBlock {
private final int x;
private final int dy;
private final int z;
public TowerGeneratorDoorBlock(ConfigurationSection section) {
x = section.getInt("x");
dy = section.getInt("dy");
z = section.getInt("z");
}
}
}

Datei anzeigen

@ -22,6 +22,7 @@ package de.steamwar.towerrun.countdowns;
import de.steamwar.towerrun.TowerRun;
import de.steamwar.towerrun.state.GameStateToggleListener;
import de.steamwar.towerrun.state.GameStates;
import lombok.Getter;
import lombok.Setter;
import org.bukkit.Bukkit;
import org.bukkit.scheduler.BukkitTask;
@ -31,6 +32,7 @@ import java.util.EnumSet;
public abstract class Countdown extends GameStateToggleListener {
@Setter
@Getter
protected int time = defaultTime();
protected BukkitTask task;
@ -38,9 +40,13 @@ public abstract class Countdown extends GameStateToggleListener {
super(enabledStates);
}
int defaultTime() {return 0;}
int defaultTime() {
return 0;
}
void timerEnd() {}
boolean timerShouldCancel() {return true;}
boolean timerShouldCancel() {
return true;
}
void run() {}
void timerStart() {}
void timerReset() {}

Datei anzeigen

@ -32,7 +32,7 @@ public class EndCountdown extends Countdown {
private final LobbyCountdown lobbyCountdown;
private static boolean RESETS = Objects.requireNonNull(Bukkit.getWorlds().get(0).getWorldFolder().list((dir, name) -> name.equals("backup"))).length > 0;
private static final boolean RESETS = Objects.requireNonNull(Bukkit.getWorlds().get(0).getWorldFolder().list((dir, name) -> name.equals("backup"))).length > 0;
public EndCountdown(LobbyCountdown lobbyCountdown) {
super(EnumSet.of(GameStates.ENDING));

Datei anzeigen

@ -47,7 +47,7 @@ public class LobbyCountdown extends Countdown {
@Override
void timerEnd() {
TowerRunGame.start();
TowerRunGame.prepareTowerOrStart();
override = false;
}

Datei anzeigen

@ -48,10 +48,27 @@ public class TowerRunGame {
return PLAYERS_ALIVE.contains(player);
}
public static void start() {
public static void prepareTowerOrStart() {
YoyoNow markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

prepareTower ist glaube ich der falsche Name für diese Funktion. Da die Funktion des generierens nur in einem bruchteil der fälle ausgeführt wird.

`prepareTower` ist glaube ich der falsche Name für diese Funktion. Da die Funktion des generierens nur in einem bruchteil der fälle ausgeführt wird.
if (GameState.getCurrentState() == GameStates.LOBBY) {
GameState.nextState();
if (TowerRun.getTowerGenerator() == null) {
start();
return;
}
TowerRun.getTowerGenerator().generate();
YoyoNow markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

die Generate Funktion hat nur eine Usage, warum braucht die dann nen lambda?

die Generate Funktion hat nur eine Usage, warum braucht die dann nen lambda?
} else {
throw new IllegalStateException("Game is already running!");
}
}
public static void start() {
if (GameState.getCurrentState() == GameStates.GENERATING_TOWER) {
PLAYERS_ALIVE.addAll(TowerRunPlayer.getAll());
PLAYERS_ALIVE.forEach(TowerRunPlayer::reset);
PLAYERS_ALIVE.forEach(p -> {
p.reset();
p.player().setGameMode(GameMode.SURVIVAL);
});
GameState.nextState();
generateLava();
TowerRun.getMessage().broadcast("GAME_START");
@ -70,8 +87,12 @@ public class TowerRunGame {
for (int z = WorldConfig.MIN_TOWER.getBlockZ(); z < WorldConfig.MAX_TOWER.getBlockZ(); z += WorldConfig.LAVE_SPACE) {
Vector pos = new Vector(x, 0, z);
if (Arrays.stream(WorldConfig.REGIONS).anyMatch(region -> region.contains(pos))) {
WorldConfig.MIN_TOWER.getWorld().getBlockAt(x, WorldConfig.LAVA_Y, z).setType(Material.LAVA, true);
WorldConfig.MIN_TOWER.getWorld().getBlockAt(x, WorldConfig.LAVA_Y - 1, z).setType(Material.BEDROCK, true);
int offset = WorldConfig.LAVA_Y;
if (TowerRun.getTowerGenerator() != null) {
offset += TowerRun.getTowerGenerator().getHeight();
}
WorldConfig.MIN_TOWER.getWorld().getBlockAt(x, offset, z).setType(Material.LAVA, true);
WorldConfig.MIN_TOWER.getWorld().getBlockAt(x, offset - 1, z).setType(Material.BEDROCK, true);
}
}
}
@ -107,38 +128,42 @@ public class TowerRunGame {
resetWorld();
GameState.reset();
Bukkit.getOnlinePlayers().forEach(player -> {
if (TowerRun.getTowerGenerator() != null) {
player.setGameMode(GameMode.SPECTATOR);
} else {
player.setGameMode(GameMode.SURVIVAL);
}
player.teleport(WorldConfig.SPAWN);
});
}
private static double posToChunk(int pos){
private static double posToChunk(int pos) {
return pos / 16.0;
}
private static int getMinChunkX(){
private static int getMinChunkX() {
return (int) Math.floor(posToChunk(WorldConfig.MAP_MIN_X));
}
private static int getMaxChunkX(){
private static int getMaxChunkX() {
return (int) Math.ceil(posToChunk(WorldConfig.MAP_MAX_X));
}
private static int getMinChunkZ(){
private static int getMinChunkZ() {
return (int) Math.floor(posToChunk(WorldConfig.MAP_MIN_Z));
}
private static int getMaxChunkZ(){
private static int getMaxChunkZ() {
return (int) Math.ceil(posToChunk(WorldConfig.MAP_MAX_Z));
}
private static void forEachChunk(ObjIntConsumer<Integer> executor) {
for(int x = getMinChunkX(); x <= getMaxChunkX(); x++)
for(int z = getMinChunkZ(); z <= getMaxChunkZ(); z++)
for (int x = getMinChunkX(); x <= getMaxChunkX(); x++)
for (int z = getMinChunkZ(); z <= getMaxChunkZ(); z++)
executor.accept(x, z);
}
private static void resetWorld(){
private static void resetWorld() {
world.getEntities().stream().filter(entity -> entity.getType() != EntityType.PLAYER).forEach(Entity::remove);
World backup = new WorldCreator(world.getName() + "/backup").createWorld();
@ -153,7 +178,7 @@ public class TowerRunGame {
System.arraycopy(backupChunk.d(), 0, chunk.d(), 0, chunk.d().length);
for(Player p : Bukkit.getOnlinePlayers())
for (Player p : Bukkit.getOnlinePlayers())
CraftbukkitWrapper.impl.sendChunk(p, x, z);
}
}

Datei anzeigen

@ -19,6 +19,7 @@
package de.steamwar.towerrun.game;
import de.steamwar.towerrun.TowerRun;
import de.steamwar.towerrun.config.WorldConfig;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
@ -43,7 +44,14 @@ public record TowerRunPlayer(Player player) {
}
public void reset() {
player.getInventory().clear();
player.updateInventory();
player.setHealth(20);
if (TowerRun.getTowerGenerator() != null) {
player.teleport(TowerRun.getTowerGenerator().getSpawn());
} else {
player.teleport(WorldConfig.SPAWN);
}
player.setVelocity(new Vector(0, 0, 0));
}

Datei anzeigen

@ -0,0 +1,206 @@
package de.steamwar.towerrun.generator;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.bukkit.BukkitWorld;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardReader;
import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.session.ClipboardHolder;
import de.steamwar.sql.SchematicData;
import de.steamwar.sql.SchematicNode;
import de.steamwar.towerrun.TowerRun;
import de.steamwar.towerrun.config.WorldConfig;
import de.steamwar.towerrun.game.TowerRunGame;
import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.*;
import org.bukkit.block.data.Bisected;
import org.bukkit.block.data.type.Door;
import org.bukkit.scheduler.BukkitRunnable;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
YoyoNow markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Could be final,
Could be static

Could be final, Could be static
import java.util.Random;
YoyoNow markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

could be final

could be final
YoyoNow markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Attribute sind im camelCase

Attribute sind im camelCase
public class TowerGenerator {
private static final Random random = new Random();
private final WorldConfig.TowerGeneratorConfig config;
private final List<SchematicNode> allSchematics;
private final Clipboard roof;
@Getter
private int height;
@Getter
private Location spawn;
@Getter
private List<Location> keys = new ArrayList<>();
public TowerGenerator(WorldConfig.TowerGeneratorConfig config) {
File file = new File(Bukkit.getWorlds().get(0).getWorldFolder(), "Roof.schem");
if (!file.exists()) {
Bukkit.shutdown();
throw new SecurityException("TowerRun schematic not found");
}
roof = loadSchematic(file);
this.config = config;
allSchematics = SchematicNode.getAllSchematicsOfType(config.schematicType);
spawn = WorldConfig.SPAWN;
}
private Clipboard loadSchematic(File file) {
Clipboard clipboard;
try (ClipboardReader reader = Objects.requireNonNull(ClipboardFormats.findByFile(file)).getReader(new FileInputStream(file))) {
clipboard = reader.read();
} catch (NullPointerException | IOException e) {
Bukkit.shutdown();
throw new SecurityException("TowerRun schematic not found", e);
}
return clipboard;
}
public void generate() {
new BukkitRunnable() {
int height = random.nextInt(config.maxHeight - config.minHeight) + config.minHeight;
int y = TowerGenerator.this.config.y;
int noBombFloors;
int noKeyFloors;
{
noBombFloors = random.nextInt(config.maxNoBombFloors - config.minNoBombFloors) + config.minNoBombFloors;
noKeyFloors = random.nextInt(config.maxNoKeyFloors - config.minNoKeyFloors) + config.minNoKeyFloors;
keys.clear();
}
@Override
public void run() {
if (height > 0) {
SchematicNode schematicNode = allSchematics.get(random.nextInt(allSchematics.size()));
SchematicData schematicData = new SchematicData(schematicNode);
int currentY;
int width;
int depth;
try {
Clipboard clipboard = schematicData.load();
try (EditSession e = WorldEdit.getInstance().getEditSessionFactory().getEditSession(new BukkitWorld(Bukkit.getWorlds().get(0)), -1)) {
ClipboardHolder ch = new ClipboardHolder(clipboard);
Operations.completeBlindly(ch.createPaste(e).to(BlockVector3.at(config.x, y, config.z)).build());
}
width = clipboard.getDimensions().getX();
depth = clipboard.getDimensions().getZ();
currentY = y;
y += clipboard.getDimensions().getY();
height -= clipboard.getDimensions().getY();
TowerGenerator.this.height += clipboard.getDimensions().getY();
} catch (IOException e) {
allSchematics.remove(schematicNode);
return;
}
spawn = WorldConfig.SPAWN.clone().add(0, y, 0);
List<Container> chestBlocks = new ArrayList<>();
for (int x = config.x; x < config.x + width; x++) {
for (int z = config.z; z < config.z + depth; z++) {
YoyoNow markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Könnte man das nicht eher als Countdown umbauen?

Könnte man das nicht eher als Countdown umbauen?
for (int y = currentY; y < this.y; y++) {
Block block = Bukkit.getWorlds().get(0).getBlockAt(x, y, z);
BlockState blockState = block.getState();
if (blockState instanceof Chest) {
chestBlocks.add((Container) blockState);
}
}
}
}
noBombFloors--;
if (noBombFloors < 0 && random.nextDouble() < config.tntChance) {
noBombFloors = random.nextInt(config.maxNoBombFloors - config.minNoBombFloors) + config.minNoBombFloors;
int bombCount = random.nextInt(config.maxBombs - config.minBombs) + config.minBombs;
for (int i = 0; i < bombCount; i++) {
WorldConfig.Region region = config.tntRegions[random.nextInt(config.tntRegions.length)];
int x = random.nextInt(region.max.getBlockX() - region.min.getBlockX()) + region.min.getBlockX();
int z = random.nextInt(region.max.getBlockZ() - region.min.getBlockZ()) + region.min.getBlockZ();
int y = currentY + 1;
Bukkit.getWorlds().get(0).getBlockAt(x, y, z).setType(Material.TNT, true);
}
}
noKeyFloors--;
if (!chestBlocks.isEmpty() && noKeyFloors < 0 && random.nextDouble() < config.keyChance) {
noKeyFloors = random.nextInt(config.maxNoKeyFloors - config.minNoKeyFloors) + config.minNoKeyFloors;
Container container = chestBlocks.get(random.nextInt(chestBlocks.size()));
keys.add(container.getLocation());
for (WorldConfig.TowerGeneratorDoorBlock doorBlock : config.doorBlocks) {
int x = doorBlock.getX();
int y = currentY + doorBlock.getDy();
int z = doorBlock.getZ();
Block block = Bukkit.getWorlds().get(0).getBlockAt(x, y, z);
for (int i = 0; i < 5; i++) {
if (block.getType().isAir()) {
block.setType(Material.IRON_BLOCK, false);
block = block.getRelative(0, 1, 0);
} else {
break;
}
}
Bukkit.getScheduler().runTaskLater(TowerRun.getInstance(), () -> {
Block door = Bukkit.getWorlds().get(0).getBlockAt(x, y, z);
door.setType(Material.IRON_DOOR, false);
door = door.getRelative(0, 1, 0);
door.setType(Material.IRON_DOOR, false);
}, 10);
Bukkit.getScheduler().runTaskLater(TowerRun.getInstance(), () -> {
Block door = Bukkit.getWorlds().get(0).getBlockAt(x, y, z);
Door doorState = (Door) door.getBlockData();
doorState.setFacing(BlockFace.EAST);
door.setBlockData(doorState, false);
door = door.getRelative(0, 1, 0);
doorState = (Door) door.getBlockData();
doorState.setFacing(BlockFace.EAST);
doorState.setHalf(Bisected.Half.TOP);
door.setBlockData(doorState, false);
}, 20);
}
}
for (WorldConfig.TowerGeneratorFillRegion fillRegion : config.fillRegions) {
for (int x = fillRegion.getMinX(); x < fillRegion.getMaxX(); x++) {
for (int z = fillRegion.getMinZ(); z < fillRegion.getMaxZ(); z++) {
for (int y = currentY; y < this.y; y++) {
Block block = Bukkit.getWorlds().get(0).getBlockAt(x, y, z);
if (!block.getType().isAir()) {
continue;
}
if (random.nextDouble() < fillRegion.getPercentage()) {
block.setType(fillRegion.getMaterial(), true);
}
}
}
}
}
} else {
cancel();
try (EditSession e = WorldEdit.getInstance().getEditSessionFactory().getEditSession(new BukkitWorld(Bukkit.getWorlds().get(0)), -1)) {
ClipboardHolder ch = new ClipboardHolder(roof);
Operations.completeBlindly(ch.createPaste(e).to(BlockVector3.at(config.x, y, config.z)).build());
}
TowerRunGame.start();
}
}
}.runTaskTimer(TowerRun.getInstance(), 0, 10);
}
}

Datei anzeigen

@ -23,33 +23,103 @@ import de.steamwar.inventory.SWItem;
import de.steamwar.towerrun.TowerRun;
import de.steamwar.towerrun.config.Config;
import de.steamwar.towerrun.config.WorldConfig;
import de.steamwar.towerrun.game.TowerRunGame;
import de.steamwar.towerrun.state.GameStateBukkitListener;
import de.steamwar.towerrun.state.GameStates;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.*;
import org.bukkit.block.Block;
import org.bukkit.entity.EntityType;
import org.bukkit.event.EventHandler;
import org.bukkit.event.block.Action;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockPhysicsEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.ItemSpawnEvent;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Stream;
public class IngameListener extends GameStateBukkitListener {
private int time = 0;
private final Map<Integer, List<Block>> blocksToMelt = new HashMap<>();
private BukkitRunnable blocksToMeltRunnable;
private BukkitRunnable antiCampRunnable;
public IngameListener() {
super(EnumSet.of(GameStates.INGAME));
}
@Override
public void enable() {
super.enable();
blocksToMeltRunnable = new BukkitRunnable() {
@Override
public void run() {
List<Block> blocks = blocksToMelt.get(time);
time++;
if (blocks == null) {
return;
}
blocks.forEach(block -> {
if (!WorldConfig.MELTING_TIMES.containsKey(block.getType())) return;
block.setType(Material.AIR);
block.getWorld().playSound(block.getLocation(), Sound.BLOCK_FIRE_EXTINGUISH, 0.1F, 1);
});
}
};
blocksToMeltRunnable.runTaskTimer(TowerRun.getInstance(), 0, 1);
antiCampRunnable = new BukkitRunnable() {
@Override
public void run() {
double minY = TowerRunGame.PLAYERS_ALIVE.stream()
.map(p -> p.player().getLocation().getY())
.min(Comparator.comparing(Function.identity()))
.orElse(0.0);
TowerRunGame.PLAYERS_ALIVE.forEach(towerRunPlayer -> {
if (towerRunPlayer.player().getLocation().getY() - minY > 20) {
towerRunPlayer.player().sendTitle("§a", TowerRun.getMessage().parse("CATCH_UP_WARNING", towerRunPlayer.player()), 5, 30, 5);
}
if (towerRunPlayer.player().getLocation().getY() - minY > 30) {
towerRunPlayer.player().damage(1.0);
}
});
}
};
antiCampRunnable.runTaskTimer(TowerRun.getInstance(), 100, 100);
}
@Override
public void disable() {
super.disable();
blocksToMeltRunnable.cancel();
blocksToMeltRunnable = null;
blocksToMelt.clear();
time = 0;
antiCampRunnable.cancel();
antiCampRunnable = null;
}
@EventHandler
public void onPlayerDeath(PlayerDeathEvent event) {
event.setDeathMessage(null);
Bukkit.getScheduler().runTaskLater(TowerRun.getInstance(), () -> {
if (TowerRun.getTowerGenerator() != null) {
event.getEntity().teleport(TowerRun.getTowerGenerator().getSpawn());
YoyoNow markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

vllt. in den TowerGenerator ne höhen angepasste Location reinlegen, dann muss man die nicht immer neuberechnen

vllt. in den TowerGenerator ne höhen angepasste Location reinlegen, dann muss man die nicht immer neuberechnen
} else {
event.getEntity().teleport(WorldConfig.SPAWN);
}
}, 5
);
event.getEntity().setGameMode(GameMode.SPECTATOR);
Bukkit.getOnlinePlayers().forEach(player -> {
player.sendTitle("", TowerRun.getMessage().parse("PLAYER_DIED", player, event.getEntity().getPlayer().getName()), 10, 70, 20);
player.playSound(player.getLocation(), Sound.ENTITY_WITHER_DEATH, 1, 1);
@ -84,13 +154,17 @@ public class IngameListener extends GameStateBukkitListener {
@EventHandler
public void onEntityDamageByEntity(EntityDamageByEntityEvent event) {
if(event.getDamager().getType() == EntityType.PLAYER) {
if (event.getDamager().getType() == EntityType.PLAYER) {
event.setCancelled(true);
}
}
@EventHandler
public void onPlayerInteract(PlayerInteractEvent event) {
if (event.getPlayer().getGameMode() != GameMode.SURVIVAL) {
return;
}
if (event.getAction() != Action.RIGHT_CLICK_BLOCK || !event.hasBlock()) {
return;
}
@ -99,19 +173,38 @@ public class IngameListener extends GameStateBukkitListener {
return;
}
if (Arrays.stream(WorldConfig.KEYS).noneMatch(location -> location.equals(event.getClickedBlock().getLocation()))) {
Stream<Location> locations = TowerRun.getTowerGenerator() == null ? Arrays.stream(WorldConfig.KEYS) : TowerRun.getTowerGenerator().getKeys().stream();
if (locations.noneMatch(location -> location.equals(event.getClickedBlock().getLocation()))) {
event.getClickedBlock().setType(Material.AIR);
return;
}
event.getPlayer().getInventory().addItem(new SWItem(Material.LEVER, TowerRun.getMessage().parse("KEY_NAME", event.getPlayer())).getItemStack());
event.getClickedBlock().setType(Material.AIR);
event.getClickedBlock().setType(Material.ENDER_CHEST);
event.getPlayer().playSound(event.getPlayer().getLocation(), Sound.BLOCK_ENDER_CHEST_OPEN, 1, 1);
TowerRun.getMessage().broadcast("KEY_FOUND", event.getPlayer().getName());
}
@EventHandler
public void onPlayerRespawn(PlayerRespawnEvent event) {
event.setRespawnLocation(WorldConfig.SPAWN);
public void onBlockPhysics(BlockPhysicsEvent event) {
if (event.getSourceBlock().getType() != Material.LAVA) {
return;
}
Block block = event.getSourceBlock();
shouldMelt(block.getRelative(0, 1, 0));
shouldMelt(block.getRelative(0, -1, 0));
shouldMelt(block.getRelative(1, 0, 0));
shouldMelt(block.getRelative(-1, 0, 0));
shouldMelt(block.getRelative(0, 0, 1));
shouldMelt(block.getRelative(0, 0, -1));
}
private void shouldMelt(Block block) {
int meltingTime = WorldConfig.MELTING_TIMES.getOrDefault(block.getType(), -1);
if (meltingTime == -1) {
return;
}
blocksToMelt.computeIfAbsent(time + meltingTime * 20, integer -> new ArrayList<>()).add(block);
}
}

Datei anzeigen

@ -19,6 +19,7 @@
package de.steamwar.towerrun.listener;
import de.steamwar.towerrun.TowerRun;
import de.steamwar.towerrun.config.WorldConfig;
import de.steamwar.towerrun.state.GameStateBukkitListener;
import de.steamwar.towerrun.state.GameStates;
@ -42,13 +43,21 @@ public class LobbyListener extends GameStateBukkitListener {
@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
Player player = event.getPlayer();
if (TowerRun.getTowerGenerator() != null) {
player.teleport(TowerRun.getTowerGenerator().getSpawn());
player.setGameMode(GameMode.SPECTATOR);
} else {
player.teleport(WorldConfig.SPAWN);
player.setGameMode(GameMode.SURVIVAL);
}
}
@EventHandler
public void onPlayerMove(PlayerMoveEvent event) {
if(event.getTo().getY() < WorldConfig.SPAWN.getY() - 10) {
if (TowerRun.getTowerGenerator() != null) {
return;
}
if (event.getTo().getY() < WorldConfig.SPAWN.getY() - 10) {
event.getPlayer().teleport(WorldConfig.SPAWN);
}
}

Datei anzeigen

@ -19,6 +19,7 @@
package de.steamwar.towerrun.listener;
import de.steamwar.towerrun.TowerRun;
import de.steamwar.towerrun.config.WorldConfig;
import de.steamwar.towerrun.state.GameStateBukkitListener;
import de.steamwar.towerrun.state.GameStates;
@ -36,6 +37,10 @@ public class NotLobbyListener extends GameStateBukkitListener {
@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
event.getPlayer().setGameMode(GameMode.SPECTATOR);
if (TowerRun.getTowerGenerator() != null) {
event.getPlayer().teleport(TowerRun.getTowerGenerator().getSpawn());
} else {
event.getPlayer().teleport(WorldConfig.SPAWN);
}
}
}

Datei anzeigen

@ -28,12 +28,13 @@ public abstract class GameStateToggleListener extends GameStateListener {
protected GameStateToggleListener(EnumSet<GameStates> enabledStates) {
super();
this.enabledStates = enabledStates;
if(enabledStates.contains(GameState.getCurrentState())) {
if (enabledStates.contains(GameState.getCurrentState())) {
enable();
}
}
public abstract void enable();
public abstract void disable();
@Override

Datei anzeigen

@ -27,7 +27,8 @@ import lombok.Getter;
public enum GameStates {
ENDING(null),
INGAME(ENDING),
LOBBY(INGAME);
GENERATING_TOWER(INGAME),
LOBBY(GENERATING_TOWER);
private final GameStates nextState;
}

Datei anzeigen

@ -26,7 +26,7 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.entity.PlayerDeathEvent;
public class LastOutsideWincondition extends OutsideWincondition{
public class LastOutsideWincondition extends OutsideWincondition {
public LastOutsideWincondition() {
super("LAST_OUTSIDE");
}
@ -42,8 +42,8 @@ public class LastOutsideWincondition extends OutsideWincondition{
@EventHandler(priority = EventPriority.LOW)
public void onPlayerDeath(PlayerDeathEvent event) {
if(TowerRunGame.PLAYERS_ALIVE.isEmpty()) {
if(TowerRunGame.PLAYERS_ESCAPED.isEmpty()) {
if (TowerRunGame.PLAYERS_ALIVE.isEmpty()) {
if (TowerRunGame.PLAYERS_ESCAPED.isEmpty()) {
TowerRunGame.tie();
return;
}