forked from SteamWar/SteamWar
Add TowerRun module
This commit is contained in:
@@ -0,0 +1,207 @@
|
||||
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;
|
||||
import java.util.Random;
|
||||
|
||||
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;
|
||||
|
||||
{
|
||||
TowerGenerator.this.height = 0;
|
||||
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++) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user