SteamWar/FightSystem
Archiviert
13
1

Schematic pasting refactoring #286

Manuell gemergt
Lixfel hat 5 Commits von weRefactoring nach master 2021-09-11 17:57:23 +02:00 zusammengeführt
13 geänderte Dateien mit 204 neuen und 301 gelöschten Zeilen

Datei anzeigen

@ -19,44 +19,14 @@
package de.steamwar.fightsystem.utils; package de.steamwar.fightsystem.utils;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import org.bukkit.DyeColor;
import org.bukkit.Material; import org.bukkit.Material;
@SuppressWarnings("deprecation")
public class WorldeditWrapper12 extends WorldeditWrapper8 { public class WorldeditWrapper12 extends WorldeditWrapper8 {
@SuppressWarnings("deprecation") static {
private static final int COLOR_TO_REPLACE = DyeColor.PINK.getWoolData(); colorBlocks.add(new BaseBlock(Material.CONCRETE.getId(), COLOR_TO_REPLACE));
colorBlocks.add(new BaseBlock(Material.CONCRETE_POWDER.getId(), COLOR_TO_REPLACE));
@SuppressWarnings("deprecation")
private static final BaseBlock CONCRETE = new BaseBlock(Material.CONCRETE.getId(), COLOR_TO_REPLACE);
@SuppressWarnings("deprecation")
private static final BaseBlock CONCRETE_POWDER = new BaseBlock(Material.CONCRETE_POWDER.getId(), COLOR_TO_REPLACE);
@SuppressWarnings("deprecation")
@Override
public void replaceTeamColor(Clipboard clipboard, DyeColor c) throws WorldEditException {
super.replaceTeamColor(clipboard, c);
Vector minimum = clipboard.getRegion().getMinimumPoint();
BaseBlock concrete = new BaseBlock(CONCRETE.getId(), c.getWoolData());
BaseBlock concretePowder = new BaseBlock(CONCRETE_POWDER.getId(), c.getWoolData());
for(int x = 0; x < clipboard.getDimensions().getX(); x++){
for(int y = 0; y < clipboard.getDimensions().getY(); y++){
for(int z = 0; z < clipboard.getDimensions().getZ(); z++){
Vector pos = minimum.add(x, y, z);
BaseBlock block = clipboard.getBlock(pos);
if(block.equals(CONCRETE)){
clipboard.setBlock(pos, concrete);
}else if(block.equals(CONCRETE_POWDER)){
clipboard.setBlock(pos, concretePowder);
}
}
}
}
} }
} }

Datei anzeigen

@ -23,6 +23,7 @@ import com.sk89q.jnbt.NBTInputStream;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.bukkit.BukkitWorld; import com.sk89q.worldedit.bukkit.BukkitWorld;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.clipboard.Clipboard;
@ -32,116 +33,87 @@ import com.sk89q.worldedit.extent.clipboard.io.SpongeSchematicReader;
import com.sk89q.worldedit.function.operation.ForwardExtentCopy; import com.sk89q.worldedit.function.operation.ForwardExtentCopy;
import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.math.transform.AffineTransform; import com.sk89q.worldedit.math.transform.AffineTransform;
import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.session.ClipboardHolder; import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.block.BlockTypes;
import de.steamwar.fightsystem.Config;
import de.steamwar.fightsystem.FightSystem; import de.steamwar.fightsystem.FightSystem;
import de.steamwar.sql.Schematic; import de.steamwar.sql.Schematic;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.DyeColor; import org.bukkit.DyeColor;
import org.bukkit.Location;
import org.bukkit.util.Vector;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.zip.GZIPInputStream; import java.util.zip.GZIPInputStream;
public class WorldeditWrapper14 implements WorldeditWrapper.IWorldeditWrapper { public class WorldeditWrapper14 implements WorldeditWrapper.IWorldeditWrapper {
private static final BaseBlock WOOL = Objects.requireNonNull(BlockTypes.PINK_WOOL).getDefaultState().toBaseBlock(); private static final Map<BaseBlock, String> colorBlocks = new HashMap<>();
private static final BaseBlock CLAY = Objects.requireNonNull(BlockTypes.PINK_TERRACOTTA).getDefaultState().toBaseBlock();
private static final BaseBlock GLASS = Objects.requireNonNull(BlockTypes.PINK_STAINED_GLASS).getDefaultState().toBaseBlock(); static {
private static final BaseBlock GLASS_PANE = Objects.requireNonNull(BlockTypes.PINK_STAINED_GLASS_PANE).getDefaultState().toBaseBlock(); colorBlocks.put(Objects.requireNonNull(BlockTypes.PINK_WOOL).getDefaultState().toBaseBlock(), "_wool");
private static final BaseBlock CONCRETE = Objects.requireNonNull(BlockTypes.PINK_CONCRETE).getDefaultState().toBaseBlock(); colorBlocks.put(Objects.requireNonNull(BlockTypes.PINK_TERRACOTTA).getDefaultState().toBaseBlock(), "_terracotta");
private static final BaseBlock CONCRETE_POWDER = Objects.requireNonNull(BlockTypes.PINK_CONCRETE_POWDER).getDefaultState().toBaseBlock(); colorBlocks.put(Objects.requireNonNull(BlockTypes.PINK_STAINED_GLASS).getDefaultState().toBaseBlock(), "_stained_glass");
private static final BaseBlock CARPET = Objects.requireNonNull(BlockTypes.PINK_CARPET).getDefaultState().toBaseBlock(); colorBlocks.put(Objects.requireNonNull(BlockTypes.PINK_STAINED_GLASS_PANE).getDefaultState().toBaseBlock(), "_stained_glass_pane");
colorBlocks.put(Objects.requireNonNull(BlockTypes.PINK_CONCRETE).getDefaultState().toBaseBlock(), "_concrete");
colorBlocks.put(Objects.requireNonNull(BlockTypes.PINK_CONCRETE_POWDER).getDefaultState().toBaseBlock(), "_concrete_powder");
colorBlocks.put(Objects.requireNonNull(BlockTypes.PINK_CARPET).getDefaultState().toBaseBlock(), "_carpet");
}
@Override @Override
public void replaceTeamColor(Clipboard clipboard, DyeColor c) throws WorldEditException { public void replaceTeamColor(Clipboard clipboard, DyeColor c) throws WorldEditException {
BlockVector3 minimum = clipboard.getRegion().getMinimumPoint(); BlockVector3 minimum = clipboard.getRegion().getMinimumPoint();
BaseBlock wool = Objects.requireNonNull(BlockTypes.get(c.name().toLowerCase() + "_wool")).getDefaultState().toBaseBlock(); Map<BaseBlock, BaseBlock> replaceMap = new HashMap<>();
BaseBlock clay = Objects.requireNonNull(BlockTypes.get(c.name().toLowerCase() + "_terracotta")).getDefaultState().toBaseBlock(); colorBlocks.forEach((base, postfix) -> replaceMap.put(base, Objects.requireNonNull(BlockTypes.get(c.name().toLowerCase() + postfix)).getDefaultState().toBaseBlock()));
BaseBlock glass = Objects.requireNonNull(BlockTypes.get(c.name().toLowerCase() + "_stained_glass")).getDefaultState().toBaseBlock();
BaseBlock glassPane = Objects.requireNonNull(BlockTypes.get(c.name().toLowerCase() + "_stained_glass_pane")).getDefaultState().toBaseBlock();
BaseBlock carpet = Objects.requireNonNull(BlockTypes.get(c.name().toLowerCase() + "_carpet")).getDefaultState().toBaseBlock();
BaseBlock concrete = Objects.requireNonNull(BlockTypes.get(c.name().toLowerCase() + "_concrete")).getDefaultState().toBaseBlock();
BaseBlock concretePowder = Objects.requireNonNull(BlockTypes.get(c.name().toLowerCase() + "_concrete_powder")).getDefaultState().toBaseBlock();
for(int x = 0; x < clipboard.getDimensions().getX(); x++){ for(int x = 0; x < clipboard.getDimensions().getX(); x++){
for(int y = 0; y < clipboard.getDimensions().getY(); y++){ for(int y = 0; y < clipboard.getDimensions().getY(); y++){
for(int z = 0; z < clipboard.getDimensions().getZ(); z++){ for(int z = 0; z < clipboard.getDimensions().getZ(); z++){
BlockVector3 pos = minimum.add(x, y, z); BlockVector3 pos = minimum.add(x, y, z);
BaseBlock block = clipboard.getFullBlock(pos); BaseBlock replacement = replaceMap.get(clipboard.getFullBlock(pos));
if(block.equals(WOOL)){ if(replacement != null)
clipboard.setBlock(pos, wool); clipboard.setBlock(pos, replacement);
}else if(block.equals(CLAY)){
clipboard.setBlock(pos, clay);
}else if(block.equals(GLASS)){
clipboard.setBlock(pos, glass);
}else if(block.equals(GLASS_PANE)){
clipboard.setBlock(pos, glassPane);
}else if(block.equals(CARPET)){
clipboard.setBlock(pos, carpet);
}else if(block.equals(CONCRETE)){
clipboard.setBlock(pos, concrete);
}else if(block.equals(CONCRETE_POWDER)){
clipboard.setBlock(pos, concretePowder);
}
} }
} }
} }
} }
@Override @Override
public void pasteSchematic(Clipboard clipboard, Region region, boolean rotate) { public int getWaterDepth(Clipboard clipboard) {
BlockVector3 paste = BlockVector3.at(region.centerX(), region.getMinY(), region.centerZ()); BlockVector3 it = clipboard.getMinimumPoint().add(0, 0, 1);
World w = new BukkitWorld(Bukkit.getWorlds().get(0));
BlockVector3 dimensions = clipboard.getDimensions();
BlockVector3 v;
BlockVector3 offset = clipboard.getRegion().getMinimumPoint().subtract(clipboard.getOrigin());
AffineTransform aT = new AffineTransform();
if(rotate){
aT = aT.rotateY(180);
v = paste.add(dimensions.getX()/2 + dimensions.getX()%2, 0, dimensions.getZ()/2 + dimensions.getZ()%2).subtract(offset.multiply(-1, 1, -1)).subtract(1, 0, 1);
}else{
v = paste.subtract(dimensions.getX()/2, 0, dimensions.getZ()/2).subtract(offset);
}
if(Config.WaterDepth != 0){
BlockVector3 it = clipboard.getMinimumPoint();
int depth = 0; int depth = 0;
while(!clipboard.getBlock(it).getBlockType().getMaterial().isAir()){ while(!clipboard.getBlock(it).getBlockType().getMaterial().isAir()){
depth++; depth++;
it = it.add(0, 1, 0); it = it.add(0, 1, 0);
} }
v = v.add(0, Config.WaterDepth - depth, 0); return depth;
} }
EditSession e = WorldEdit.getInstance().getEditSessionFactory().getEditSession(w, -1); @Override
public void pasteClipboard(Clipboard clipboard, Location position, Vector offset, AffineTransform aT) {
EditSession e = WorldEdit.getInstance().getEditSessionFactory().getEditSession(new BukkitWorld(position.getWorld()), -1);
ClipboardHolder ch = new ClipboardHolder(clipboard); ClipboardHolder ch = new ClipboardHolder(clipboard);
ch.setTransform(aT); ch.setTransform(aT);
Operations.completeBlindly(ch.createPaste(e).to(v).build()); Operations.completeBlindly(ch.createPaste(e).to(BukkitAdapter.asVector(position).add(
aT.apply(Vector3.at(offset.getX(), offset.getY(), offset.getZ()).add(clipboard.getOrigin().toVector3()).subtract(clipboard.getMinimumPoint().toVector3()))
).round().toBlockPoint()).build());
e.flushSession(); e.flushSession();
} }
@Override @Override
public void pasteChar(Clipboard character, int charOffset, int length, int x, int y, int z, AffineTransform aT) { public Vector getDimensions(Clipboard clipboard) {
BlockVector3 offset = character.getRegion().getMinimumPoint().subtract(character.getOrigin()); BlockVector3 dims = clipboard.getDimensions();
BlockVector3 v = BlockVector3.ZERO.subtract(- charOffset + length / 2, 0, 0).subtract(offset); return new Vector(dims.getX(), dims.getY(), dims.getZ());
v = aT.apply(v.toVector3()).toBlockPoint();
v = v.add(x, y, z);
EditSession e = WorldEdit.getInstance().getEditSessionFactory().getEditSession(new BukkitWorld(Bukkit.getWorlds().get(0)), -1);
ClipboardHolder ch = new ClipboardHolder(character);
ch.setTransform(aT);
Operations.completeBlindly(ch.createPaste(e).to(v).ignoreAirBlocks(true).build());
e.flushSession();
} }
@Override @Override
@ -150,21 +122,17 @@ public class WorldeditWrapper14 implements WorldeditWrapper.IWorldeditWrapper {
} }
@Override @Override
public void saveSchem(Schematic schem, Region region, int minY) { public void saveSchem(Schematic schem, Region region, int minY) throws WorldEditException {
World w = new BukkitWorld(Bukkit.getWorlds().get(0)); World w = new BukkitWorld(Bukkit.getWorlds().get(0));
BlockVector3 min = BlockVector3.at(region.getMinX(), minY, region.getMinZ()); BlockVector3 min = BlockVector3.at(region.getMinX(), minY, region.getMinZ());
CuboidRegion cuboidRegion = new CuboidRegion(w, min, BlockVector3.at(region.getMaxX(), region.getMaxY(), region.getMaxZ())); CuboidRegion cuboidRegion = new CuboidRegion(w, min, BlockVector3.at(region.getMaxX(), region.getMaxY(), region.getMaxZ()));
BlockArrayClipboard clipboard = new BlockArrayClipboard(cuboidRegion); BlockArrayClipboard clipboard = new BlockArrayClipboard(cuboidRegion);
EditSession editSession = WorldEdit.getInstance().getEditSessionFactory().getEditSession(w, -1);
ForwardExtentCopy forwardExtentCopy = new ForwardExtentCopy(editSession, cuboidRegion, clipboard, min); ForwardExtentCopy forwardExtentCopy = new ForwardExtentCopy(
WorldEdit.getInstance().getEditSessionFactory().getEditSession(w, -1), cuboidRegion, clipboard, min
);
forwardExtentCopy.setCopyingEntities(false); forwardExtentCopy.setCopyingEntities(false);
try{
Operations.complete(forwardExtentCopy); Operations.complete(forwardExtentCopy);
}catch(WorldEditException e){
throw new IllegalStateException(e);
}
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try { try {
@ -172,7 +140,7 @@ public class WorldeditWrapper14 implements WorldeditWrapper.IWorldeditWrapper {
writer.write(clipboard); writer.write(clipboard);
writer.close(); writer.close();
} catch (IOException e) { } catch (IOException e) {
throw new IllegalStateException(e); throw new SecurityException(e);
} }
schem.saveFromBytes(outputStream.toByteArray(), true); schem.saveFromBytes(outputStream.toByteArray(), true);

Datei anzeigen

@ -37,110 +37,82 @@ import com.sk89q.worldedit.math.transform.AffineTransform;
import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.session.ClipboardHolder; import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import de.steamwar.fightsystem.Config;
import de.steamwar.fightsystem.FightSystem; import de.steamwar.fightsystem.FightSystem;
import de.steamwar.sql.Schematic; import de.steamwar.sql.Schematic;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.DyeColor; import org.bukkit.DyeColor;
import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.zip.GZIPInputStream; import java.util.zip.GZIPInputStream;
@SuppressWarnings("deprecation")
public class WorldeditWrapper8 implements WorldeditWrapper.IWorldeditWrapper { public class WorldeditWrapper8 implements WorldeditWrapper.IWorldeditWrapper {
@SuppressWarnings("deprecation") protected static final int COLOR_TO_REPLACE = DyeColor.PINK.getWoolData();
private static final int COLOR_TO_REPLACE = DyeColor.PINK.getWoolData(); protected static final Set<BaseBlock> colorBlocks = new HashSet<>();
@SuppressWarnings("deprecation") static {
private static final BaseBlock WOOL = new BaseBlock(Material.WOOL.getId(), COLOR_TO_REPLACE); colorBlocks.add(new BaseBlock(Material.WOOL.getId(), COLOR_TO_REPLACE));
@SuppressWarnings("deprecation") colorBlocks.add(new BaseBlock(Material.STAINED_GLASS.getId(), COLOR_TO_REPLACE));
private static final BaseBlock GLASS = new BaseBlock(Material.STAINED_GLASS.getId(), COLOR_TO_REPLACE); colorBlocks.add(new BaseBlock(Material.CLAY.getId(), COLOR_TO_REPLACE));
@SuppressWarnings("deprecation") colorBlocks.add(new BaseBlock(Material.STAINED_GLASS_PANE.getId(), COLOR_TO_REPLACE));
private static final BaseBlock CLAY = new BaseBlock(Material.CLAY.getId(), COLOR_TO_REPLACE); colorBlocks.add(new BaseBlock(Material.CARPET.getId(), COLOR_TO_REPLACE));
@SuppressWarnings("deprecation") }
private static final BaseBlock GLASS_PANE = new BaseBlock(Material.STAINED_GLASS_PANE.getId(), COLOR_TO_REPLACE);
@SuppressWarnings("deprecation")
private static final BaseBlock CARPET = new BaseBlock(Material.CARPET.getId(), COLOR_TO_REPLACE);
@SuppressWarnings("deprecation")
@Override @Override
public void replaceTeamColor(Clipboard clipboard, DyeColor c) throws WorldEditException { public void replaceTeamColor(Clipboard clipboard, DyeColor c) throws WorldEditException {
Vector minimum = clipboard.getRegion().getMinimumPoint(); Vector minimum = clipboard.getRegion().getMinimumPoint();
BaseBlock wool = new BaseBlock(WOOL.getId(), c.getWoolData()); Map<BaseBlock, BaseBlock> replaceMap = new HashMap<>();
BaseBlock clay = new BaseBlock(CLAY.getId(), c.getWoolData()); colorBlocks.forEach(base -> replaceMap.put(base, new BaseBlock(base.getId(), c.getWoolData())));
BaseBlock glass = new BaseBlock(GLASS.getId(), c.getWoolData());
BaseBlock glassPane = new BaseBlock(GLASS_PANE.getId(), c.getWoolData());
BaseBlock carpet = new BaseBlock(CARPET.getId(), c.getWoolData());
for(int x = 0; x < clipboard.getDimensions().getX(); x++){ for(int x = 0; x < clipboard.getDimensions().getX(); x++){
for(int y = 0; y < clipboard.getDimensions().getY(); y++){ for(int y = 0; y < clipboard.getDimensions().getY(); y++){
for(int z = 0; z < clipboard.getDimensions().getZ(); z++){ for(int z = 0; z < clipboard.getDimensions().getZ(); z++){
Vector pos = minimum.add(x, y, z); Vector pos = minimum.add(x, y, z);
BaseBlock block = clipboard.getBlock(pos); BaseBlock replacement = replaceMap.get(clipboard.getBlock(pos));
if(block.equals(WOOL)){ if(replacement != null)
clipboard.setBlock(pos, wool); clipboard.setBlock(pos, replacement);
}else if(block.equals(CLAY)){
clipboard.setBlock(pos, clay);
}else if(block.equals(GLASS)){
clipboard.setBlock(pos, glass);
}else if(block.equals(GLASS_PANE)){
clipboard.setBlock(pos, glassPane);
}else if(block.equals(CARPET)){
clipboard.setBlock(pos, carpet);
}
} }
} }
} }
} }
@Override @Override
public void pasteSchematic(Clipboard clipboard, Region region, boolean rotate) { public int getWaterDepth(Clipboard clipboard) {
World w = new BukkitWorld(Bukkit.getWorlds().get(0)); Vector it = clipboard.getMinimumPoint().add(0, 0, 1);
Vector dimensions = clipboard.getDimensions();
Vector v = new Vector(region.centerX(), region.getMinY(), region.centerZ());
Vector offset = clipboard.getMinimumPoint().subtract(clipboard.getOrigin());
AffineTransform aT = new AffineTransform();
if(rotate){
aT = aT.rotateY(180);
v = v.add(dimensions.getX()/2 + dimensions.getX()%2, 0, dimensions.getZ()/2 + dimensions.getZ()%2).subtract(offset.multiply(-1, 1, -1)).subtract(1, 0, 1);
}else{
v = v.subtract(dimensions.getX()/2 - dimensions.getX()%2, 0, dimensions.getZ()/2 - dimensions.getZ()%2).subtract(offset);
}
if(Config.WaterDepth != 0){
Vector it = clipboard.getMinimumPoint();
int depth = 0; int depth = 0;
while(!clipboard.getBlock(it).isAir()){ while(!clipboard.getBlock(it).isAir()) {
depth++; depth++;
it = it.setY(it.getY()+1); it = it.add(0, 1, 0);
} }
v = v.add(0, Config.WaterDepth - depth, 0); return depth;
} }
@Override
public void pasteClipboard(Clipboard clipboard, Location position, org.bukkit.util.Vector offset, AffineTransform aT) {
World w = new BukkitWorld(position.getWorld());
EditSession e = WorldEdit.getInstance().getEditSessionFactory().getEditSession(w, -1); EditSession e = WorldEdit.getInstance().getEditSessionFactory().getEditSession(w, -1);
ClipboardHolder ch = new ClipboardHolder(clipboard, w.getWorldData()); ClipboardHolder ch = new ClipboardHolder(clipboard, w.getWorldData());
ch.setTransform(aT); ch.setTransform(aT);
Operations.completeBlindly(ch.createPaste(e, w.getWorldData()).to(v).build()); Operations.completeBlindly(ch.createPaste(e, w.getWorldData()).to(new Vector(position.getX(), position.getY(), position.getZ()).add(
aT.apply(new Vector(offset.getX(), offset.getY(), offset.getZ()).add(clipboard.getOrigin()).subtract(clipboard.getMinimumPoint()))
).round().toBlockPoint()).build());
e.flushQueue(); e.flushQueue();
} }
@Override @Override
public void pasteChar(Clipboard character, int charOffset, int length, int x, int y, int z, AffineTransform aT) { public org.bukkit.util.Vector getDimensions(Clipboard clipboard) {
World w = new BukkitWorld(Bukkit.getWorlds().get(0)); Vector dims = clipboard.getDimensions();
Vector offset = character.getRegion().getMinimumPoint().subtract(character.getOrigin()); return new org.bukkit.util.Vector(dims.getBlockX(), dims.getBlockY(), dims.getBlockZ());
Vector v = Vector.ZERO.subtract(- charOffset + length / 2, 0, 0).subtract(offset);
v = aT.apply(v).toBlockPoint();
v = v.add(x, y, z);
EditSession e = WorldEdit.getInstance().getEditSessionFactory().getEditSession(w, -1);
ClipboardHolder ch = new ClipboardHolder(character, w.getWorldData());
ch.setTransform(aT);
Operations.completeBlindly(ch.createPaste(e, w.getWorldData()).to(v).build());
e.flushQueue();
} }
@Override @Override
@ -149,19 +121,16 @@ public class WorldeditWrapper8 implements WorldeditWrapper.IWorldeditWrapper {
} }
@Override @Override
public void saveSchem(Schematic schem, Region region, int minY) { public void saveSchem(Schematic schem, Region region, int minY) throws WorldEditException {
World w = new BukkitWorld(Bukkit.getWorlds().get(0)); World w = new BukkitWorld(Bukkit.getWorlds().get(0));
Vector min = new Vector(region.getMinX(), minY, region.getMinZ()); Vector min = new Vector(region.getMinX(), minY, region.getMinZ());
CuboidRegion cuboidRegion = new CuboidRegion(w, min, new Vector(region.getMaxX(), region.getMaxY(), region.getMaxZ())); CuboidRegion cuboidRegion = new CuboidRegion(w, min, new Vector(region.getMaxX(), region.getMaxY(), region.getMaxZ()));
BlockArrayClipboard clipboard = new BlockArrayClipboard(cuboidRegion); BlockArrayClipboard clipboard = new BlockArrayClipboard(cuboidRegion);
EditSession editSession = WorldEdit.getInstance().getEditSessionFactory().getEditSession(w, -1);
ForwardExtentCopy forwardExtentCopy = new ForwardExtentCopy(editSession, cuboidRegion, clipboard, min); ForwardExtentCopy forwardExtentCopy = new ForwardExtentCopy(
try{ WorldEdit.getInstance().getEditSessionFactory().getEditSession(w, -1), cuboidRegion, clipboard, min
);
Operations.complete(forwardExtentCopy); Operations.complete(forwardExtentCopy);
}catch(WorldEditException e){
throw new IllegalStateException(e);
}
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try { try {
@ -169,7 +138,7 @@ public class WorldeditWrapper8 implements WorldeditWrapper.IWorldeditWrapper {
writer.write(clipboard, w.getWorldData()); writer.write(clipboard, w.getWorldData());
writer.close(); writer.close();
} catch (IOException e) { } catch (IOException e) {
throw new IllegalStateException(e); throw new SecurityException(e);
} }
schem.saveFromBytes(outputStream.toByteArray(), false); schem.saveFromBytes(outputStream.toByteArray(), false);

Datei anzeigen

@ -61,9 +61,9 @@ public class Config {
public static final Location TeamRedSpawn; public static final Location TeamRedSpawn;
public static final Location SpecSpawn; public static final Location SpecSpawn;
private static final int BlueToRedX; public static final int BlueToRedX;
private static final int BlueToRedY; private static final int BlueToRedY;
private static final int BlueToRedZ; public static final int BlueToRedZ;
public static final int PreperationArea; public static final int PreperationArea;
public static final int WaterDepth; public static final int WaterDepth;
@ -132,14 +132,15 @@ public class Config {
public static final int ReplayID; public static final int ReplayID;
static{ static{
if(!new File(FightSystem.getPlugin().getDataFolder(), System.getProperty("config", "config.yml")).exists()) { String configFile = System.getProperty("config", "config.yml");
if(!new File(FightSystem.getPlugin().getDataFolder(), configFile).exists()) {
FightSystem.getPlugin().saveDefaultConfig(); FightSystem.getPlugin().saveDefaultConfig();
Bukkit.getLogger().log(Level.SEVERE, "Arenaconfig fehlt!"); Bukkit.getLogger().log(Level.SEVERE, "Arenaconfig fehlt!");
Bukkit.shutdown(); Bukkit.shutdown();
} }
FileConfiguration config = YamlConfiguration.loadConfiguration(new File(FightSystem.getPlugin().getDataFolder(), System.getProperty("config", "config.yml"))); FileConfiguration config = YamlConfiguration.loadConfiguration(new File(FightSystem.getPlugin().getDataFolder(), configFile));
File worldConfigFile = new File(Bukkit.getWorlds().get(0).getWorldFolder(), config.getString("Arenaconfig", "config.yml")); File worldConfigFile = new File(Bukkit.getWorlds().get(0).getWorldFolder(), "config.yml");
if(!worldConfigFile.exists()) { if(!worldConfigFile.exists()) {
Bukkit.getLogger().log(Level.SEVERE, "Weltconfig fehlt!"); Bukkit.getLogger().log(Level.SEVERE, "Weltconfig fehlt!");
Bukkit.shutdown(); Bukkit.shutdown();
@ -173,7 +174,7 @@ public class Config {
GroundWalkable = config.getBoolean("Arena.GroundWalkable"); GroundWalkable = config.getBoolean("Arena.GroundWalkable");
RanksEnabled = config.getBoolean("Schematic.RanksEnabled"); RanksEnabled = config.getBoolean("Schematic.RanksEnabled");
SchematicType = de.steamwar.sql.SchematicType.fromDB(config.getString("Schematic.SchematicType")); SchematicType = de.steamwar.sql.SchematicType.fromDB(Objects.requireNonNull(config.getString("Schematic.SchematicType")));
IgnorePublicOnly = config.getBoolean("Schematic.IgnorePublicOnly"); IgnorePublicOnly = config.getBoolean("Schematic.IgnorePublicOnly");
boolean rotate = config.getBoolean("Schematic.Rotate"); boolean rotate = config.getBoolean("Schematic.Rotate");
PasteAligned = config.getBoolean("Schematic.PasteAligned"); PasteAligned = config.getBoolean("Schematic.PasteAligned");

Datei anzeigen

@ -145,11 +145,7 @@ public class FightSystem extends JavaPlugin {
}else if(Config.mode == ArenaMode.CHECK){ }else if(Config.mode == ArenaMode.CHECK){
Fight.getBlueTeam().setSchem(Schematic.getSchemFromDB(Config.CheckSchemID)); Fight.getBlueTeam().setSchem(Schematic.getSchemFromDB(Config.CheckSchemID));
}else if(Config.mode == ArenaMode.PREPARE) { }else if(Config.mode == ArenaMode.PREPARE) {
if(Config.BlueRotate){ Fight.getUnrotated().setSchem(Schematic.getSchemFromDB(Config.PrepareSchemID));
Fight.getRedTeam().setSchem(Schematic.getSchemFromDB(Config.PrepareSchemID));
}else{
Fight.getBlueTeam().setSchem(Schematic.getSchemFromDB(Config.PrepareSchemID));
}
}else if(Config.mode == ArenaMode.REPLAY) { }else if(Config.mode == ArenaMode.REPLAY) {
FightWorld.forceLoad(); FightWorld.forceLoad();
FileSource.startReplay(); FileSource.startReplay();

Datei anzeigen

@ -88,6 +88,10 @@ public class Fight {
return blueTeam; return blueTeam;
} }
public static FightTeam getUnrotated() {
return Config.BlueRotate ? Fight.getRedTeam() : Fight.getBlueTeam();
}
public static void playSound(Sound sound, float volume, float pitch) { public static void playSound(Sound sound, float volume, float pitch) {
GlobalRecorder.getInstance().soundAtPlayer(sound.name(), volume, pitch); GlobalRecorder.getInstance().soundAtPlayer(sound.name(), volume, pitch);
//volume: max. 100, pitch: max. 2 //volume: max. 100, pitch: max. 2

Datei anzeigen

@ -32,15 +32,12 @@ import de.steamwar.fightsystem.utils.ColorConverter;
import de.steamwar.fightsystem.utils.Region; import de.steamwar.fightsystem.utils.Region;
import de.steamwar.fightsystem.utils.WorldeditWrapper; import de.steamwar.fightsystem.utils.WorldeditWrapper;
import de.steamwar.sql.Schematic; import de.steamwar.sql.Schematic;
import org.bukkit.Bukkit; import org.bukkit.*;
import org.bukkit.DyeColor;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.event.HandlerList; import org.bukkit.event.HandlerList;
import org.bukkit.util.Vector;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
import java.util.logging.Level; import java.util.logging.Level;
@ -62,7 +59,7 @@ public class FightSchematic extends StateDependent {
register(); register();
} }
public boolean hasSchematic(){ public boolean hasSchematic() {
return clipboard != null; return clipboard != null;
} }
@ -75,7 +72,7 @@ public class FightSchematic extends StateDependent {
try { try {
clipboard = schem.load(); clipboard = schem.load();
} catch (IOException e) { } catch (IOException e) {
team.broadcast(FightSystem.PREFIX + "§cKonnte die Schematic nicht laden!"); team.broadcast(FightSystem.PREFIX + "§cSchematic konnte nicht geladen werden!");
Bukkit.getLogger().log(Level.SEVERE, e, () -> "Couldn't load Schematic " + schem.getSchemName()); Bukkit.getLogger().log(Level.SEVERE, e, () -> "Couldn't load Schematic " + schem.getSchemName());
} }
} }
@ -117,80 +114,35 @@ public class FightSchematic extends StateDependent {
Bukkit.getScheduler().runTask(FightSystem.getPlugin(), this::paste); Bukkit.getScheduler().runTask(FightSystem.getPlugin(), this::paste);
} }
private void replaceTeamColor(Clipboard clipboard) throws WorldEditException { private void replaceTeamColor(Clipboard clipboard) {
try {
WorldeditWrapper.impl.replaceTeamColor(clipboard, ArenaMode.AntiPrepare.contains(Config.mode) ? ColorConverter.chat2dye(team.getColor()) : DyeColor.PINK); WorldeditWrapper.impl.replaceTeamColor(clipboard, ArenaMode.AntiPrepare.contains(Config.mode) ? ColorConverter.chat2dye(team.getColor()) : DyeColor.PINK);
} catch (WorldEditException e) {
Bukkit.getLogger().log(Level.SEVERE, "Could not recolor schematic", e);
}
} }
private void paste(){ private void paste(){
FreezeWorld freezer = new FreezeWorld(); FreezeWorld freezer = new FreezeWorld();
try {
replaceTeamColor(clipboard); replaceTeamColor(clipboard);
WorldeditWrapper.impl.pasteSchematic(clipboard, region, rotate);
} catch (WorldEditException e) { Vector dims = WorldeditWrapper.impl.getDimensions(clipboard);
FightSystem.broadcast("§cFehler beim Pasten der Schematic"); WorldeditWrapper.impl.pasteClipboard(
Bukkit.getScheduler().runTask(FightSystem.getPlugin(), FightSystem::setPreSchemState); clipboard,
throw new SecurityException("Could not paste schematic", e); new Location(Bukkit.getWorlds().get(0), region.centerX(), region.getMinY(), region.centerZ()),
} new Vector(
-(Config.PasteAligned && Config.BlueToRedX != 0 ? region.getSizeX() : dims.getBlockX())/2.0,
Config.WaterDepth != 0 ? Config.WaterDepth - WorldeditWrapper.impl.getWaterDepth(clipboard) : 0,
-(Config.PasteAligned && Config.BlueToRedZ != 0 ? region.getSizeZ() : dims.getBlockZ())/2.0
),
new AffineTransform().rotateY(rotate ? 180 : 0)
);
Bukkit.getScheduler().runTaskLater(FightSystem.getPlugin(), freezer::disable, 3); Bukkit.getScheduler().runTaskLater(FightSystem.getPlugin(), freezer::disable, 3);
Bukkit.getScheduler().runTaskLater(FightSystem.getPlugin(), team::teleportToSpawn, 40); Bukkit.getScheduler().runTaskLater(FightSystem.getPlugin(), team::teleportToSpawn, 40);
} }
private Clipboard loadTextSchem(String schemName) throws IOException {
return WorldeditWrapper.impl.loadChar(schemName);
}
public void pasteTeamName(){
List<Clipboard> characters = new ArrayList<>();
for(char c : team.getName().toCharArray()){
try {
characters.add(loadTextSchem(c == '/' ? "slash" : String.valueOf(c)));
} catch (IOException e) {
Bukkit.getLogger().log(Level.WARNING, "Could not display character {} due to missing file!", c);
try {
characters.add(loadTextSchem(""));
}catch (IOException ex) {
throw new SecurityException("Could not load text", ex);
}
}
}
//Calc character sizes
int[] lengthes = new int[characters.size()];
for(int i = 0; i < lengthes.length; i++)
lengthes[i] = characters.get(i).getDimensions().getBlockX();
//Calc character offsets
int[] offsets = new int[lengthes.length];
int previousOffset = 0;
for(int i = 0; i < offsets.length; i++){
offsets[i] = previousOffset;
previousOffset += lengthes[i] + 1; // 1 is the distance between characters
}
int length = lengthes.length == 0 ? 0 : lengthes[lengthes.length - 1] + offsets[offsets.length - 1];
int z = team.getSchemRegion().centerZ();
AffineTransform aT = new AffineTransform();
if(rotate){
aT = aT.rotateY(180);
z += team.getSchemRegion().getSizeZ() / 2;
}else{
z -= team.getSchemRegion().getSizeZ() / 2;
}
for(int i = 0; i < characters.size(); i++){
try {
replaceTeamColor(characters.get(i));
} catch (WorldEditException e) {
Bukkit.getLogger().log(Level.SEVERE, "Could not recolor team text", e);
}
WorldeditWrapper.impl.pasteChar(characters.get(i), offsets[i], length, team.getSchemRegion().centerX(), team.getExtendRegion().getMaxY(), z, aT);
}
}
@Override @Override
public void disable() { public void disable() {
if(!Config.ReplaceObsidianBedrock) if(!Config.ReplaceObsidianBedrock)
@ -207,6 +159,41 @@ public class FightSchematic extends StateDependent {
HandlerList.unregisterAll(freezer); HandlerList.unregisterAll(freezer);
} }
public void pasteTeamName(){
char[] chars = team.getName().toCharArray();
Clipboard[] characters = new Clipboard[chars.length];
int length = 0;
int[] offsets = new int[chars.length];
for(int i = 0; i < chars.length; i++){
Clipboard character;
try {
character = WorldeditWrapper.impl.loadChar(chars[i] == '/' ? "slash" : String.valueOf(chars[i]));
} catch (IOException e) {
Bukkit.getLogger().log(Level.WARNING, "Could not display character {} due to missing file!", chars[i]);
try {
character = WorldeditWrapper.impl.loadChar("");
}catch (IOException ex) {
throw new SecurityException("Could not load text", ex);
}
}
replaceTeamColor(character);
characters[i] = character;
offsets[i] = length;
length += WorldeditWrapper.impl.getDimensions(character).getBlockX() + 1; // 1 is the distance between characters
}
length -= 1;
AffineTransform aT = new AffineTransform().rotateY(rotate ? 180 : 0);
Location base = new Location(Bukkit.getWorlds().get(0), region.centerX(), team.getExtendRegion().getMaxY(), region.centerZ());
for(int i = 0; i < characters.length; i++){
WorldeditWrapper.impl.pasteClipboard(characters[i], base, new Vector(offsets[i] - length/2, 0, region.getSizeZ()/2), aT);
}
}
private void replaceSync(Material target, Material replacement){ private void replaceSync(Material target, Material replacement){
World world = Bukkit.getWorlds().get(0); World world = Bukkit.getWorlds().get(0);

Datei anzeigen

@ -305,7 +305,7 @@ public class FightTeam {
private void testPasteAction(){ private void testPasteAction(){
if(Config.test()) if(Config.test())
this.schematic.enable(); this.schematic.enable();
else if(Fight.getOpposite(this).hasSchematic()){ else if(Fight.getOpposite(this).schematic.hasSchematic()){
FightSystem.setPostSchemState(); FightSystem.setPostSchemState();
} }
} }
@ -319,10 +319,6 @@ public class FightTeam {
broadcast(FightSystem.PREFIX + "§7Das §e" + Config.GameName + " " + schematic.getSchemName() + " §7wird für den Kampf verwendet!"); broadcast(FightSystem.PREFIX + "§7Das §e" + Config.GameName + " " + schematic.getSchemName() + " §7wird für den Kampf verwendet!");
} }
public boolean hasSchematic(){
return schematic.hasSchematic();
}
public void setReady(boolean ready) { public void setReady(boolean ready) {
Player l = leader.getPlayer(); Player l = leader.getPlayer();

Datei anzeigen

@ -19,6 +19,7 @@
package de.steamwar.fightsystem.listener; package de.steamwar.fightsystem.listener;
import com.sk89q.worldedit.WorldEditException;
import de.steamwar.fightsystem.ArenaMode; import de.steamwar.fightsystem.ArenaMode;
import de.steamwar.fightsystem.Config; import de.steamwar.fightsystem.Config;
import de.steamwar.fightsystem.FightSystem; import de.steamwar.fightsystem.FightSystem;
@ -45,8 +46,8 @@ public class PrepareSchem implements Listener {
public void disable() { public void disable() {
super.disable(); super.disable();
World world = Bukkit.getWorlds().get(0); World world = Bukkit.getWorlds().get(0);
Region region = Config.BlueRotate ? Fight.getRedTeam().getExtendRegion() : Fight.getBlueTeam().getExtendRegion(); Region region = Fight.getUnrotated().getExtendRegion();
int minY = Config.BlueRotate ? Fight.getRedTeam().getSchemRegion().getMinY() : Fight.getBlueTeam().getSchemRegion().getMinY(); int minY = Fight.getUnrotated().getSchemRegion().getMinY();
Schematic schem; Schematic schem;
try{ try{
@ -69,7 +70,7 @@ public class PrepareSchem implements Listener {
try{ try{
WorldeditWrapper.impl.saveSchem(schem, region, minY); WorldeditWrapper.impl.saveSchem(schem, region, minY);
}catch(IllegalStateException e){ }catch(WorldEditException e){
FightSystem.shutdown(FightSystem.PREFIX + "§cDie Schematic konnte nicht gespeichert werden, Einsenden wird abgebrochen."); FightSystem.shutdown(FightSystem.PREFIX + "§cDie Schematic konnte nicht gespeichert werden, Einsenden wird abgebrochen.");
throw new SecurityException("Could not save schem", e); throw new SecurityException("Could not save schem", e);
} }
@ -86,11 +87,7 @@ public class PrepareSchem implements Listener {
FightTeam team = Fight.getPlayerTeam(player); FightTeam team = Fight.getPlayerTeam(player);
if (team == null) { if (team == null) {
if(Config.BlueRotate){ Fight.getUnrotated().addMember(player);
Fight.getRedTeam().addMember(player);
}else{
Fight.getBlueTeam().addMember(player);
}
} }
if(FightState.getFightState() == FightState.PRE_LEADER_SETUP) { if(FightState.getFightState() == FightState.PRE_LEADER_SETUP) {

Datei anzeigen

@ -38,10 +38,7 @@ import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
import java.io.DataOutputStream; import java.io.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.logging.Level; import java.util.logging.Level;
public interface Recorder { public interface Recorder {
@ -249,16 +246,23 @@ public interface Recorder {
} }
default void schem(int embedId, int noEmbedId, int schemId){ default void schem(int embedId, int noEmbedId, int schemId){
try { if(schemId == 0) {
if(schemId == 0)
throw new IOException();
write(embedId, schemId, Schematic.getSchemFromDB(schemId).schemData());
} catch (IOException e) {
if(schemId != 0)
Bukkit.getLogger().log(Level.SEVERE, "Could not embed schematic", e);
write(noEmbedId, schemId); write(noEmbedId, schemId);
return;
} }
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
try{
copy(Schematic.getSchemFromDB(schemId).schemData(), buffer);
}catch (EOFException e) {
Bukkit.getLogger().log(Level.INFO, "EOFException ignored");
} catch (IOException e) {
Bukkit.getLogger().log(Level.SEVERE, "Could not embed schematic", e);
disable();
return;
}
write(embedId, schemId, buffer.toByteArray());
} }
default void scoreboardTitle(String title){ default void scoreboardTitle(String title){
@ -292,8 +296,8 @@ public interface Recorder {
stream.writeDouble((Double)o); stream.writeDouble((Double)o);
else if(o instanceof String) else if(o instanceof String)
stream.writeUTF((String)o); stream.writeUTF((String)o);
else if(o instanceof InputStream) else if(o instanceof byte[])
copy((InputStream) o, stream); stream.write((byte[])o);
else else
throw new SecurityException("Undefined write for: " + o.getClass().getName()); throw new SecurityException("Undefined write for: " + o.getClass().getName());
} }

Datei anzeigen

@ -71,6 +71,10 @@ public class Region {
return maxZ; return maxZ;
} }
public int getSizeX() {
return maxX - minX;
}
public int getSizeZ() { public int getSizeZ() {
return maxZ - minZ; return maxZ - minZ;
} }
@ -120,12 +124,12 @@ public class Region {
return (maxX - minX) * (maxY - minY) * (maxZ - minZ); return (maxX - minX) * (maxY - minY) * (maxZ - minZ);
} }
public int centerX() { public double centerX() {
return (maxX - minX) / 2 + minX; return (maxX - minX) / 2.0 + minX;
} }
public int centerZ() { public double centerZ() {
return (maxZ - minZ) / 2 + minZ; return (maxZ - minZ) / 2.0 + minZ;
} }
public boolean in2dRegion(Location location){ public boolean in2dRegion(Location location){

Datei anzeigen

@ -25,6 +25,8 @@ import com.sk89q.worldedit.math.transform.AffineTransform;
import de.steamwar.fightsystem.VersionDependent; import de.steamwar.fightsystem.VersionDependent;
import de.steamwar.sql.Schematic; import de.steamwar.sql.Schematic;
import org.bukkit.DyeColor; import org.bukkit.DyeColor;
import org.bukkit.Location;
import org.bukkit.util.Vector;
import java.io.IOException; import java.io.IOException;
@ -35,9 +37,10 @@ public class WorldeditWrapper {
public interface IWorldeditWrapper { public interface IWorldeditWrapper {
void replaceTeamColor(Clipboard clipboard, DyeColor c) throws WorldEditException; void replaceTeamColor(Clipboard clipboard, DyeColor c) throws WorldEditException;
void pasteSchematic(Clipboard clipboard, Region region, boolean rotate); int getWaterDepth(Clipboard clipboard);
void pasteChar(Clipboard character, int charOffset, int length, int x, int y, int z, AffineTransform aT); void pasteClipboard(Clipboard clipboard, Location position, Vector offset, AffineTransform aT);
Vector getDimensions(Clipboard clipboard);
Clipboard loadChar(String charName) throws IOException; Clipboard loadChar(String charName) throws IOException;
void saveSchem(Schematic schem, Region region, int minY); void saveSchem(Schematic schem, Region region, int minY) throws WorldEditException;
} }
} }

Datei anzeigen

@ -23,13 +23,17 @@ public enum Winconditions {
TIMEOUT, TIMEOUT,
HEART_RATIO_TIMEOUT, HEART_RATIO_TIMEOUT,
PERCENT_TIMEOUT, PERCENT_TIMEOUT,
ALL_DEAD, ALL_DEAD,
CAPTAIN_DEAD, CAPTAIN_DEAD,
PERCENT_SYSTEM, PERCENT_SYSTEM,
RELATIVE_PERCENT, RELATIVE_PERCENT,
POINTS, POINTS,
TIME_TECH_KO, TIME_TECH_KO,
WATER_TECH_KO, WATER_TECH_KO,
PUMPKIN_TECH_KO, PUMPKIN_TECH_KO,
HELLS_BELLS HELLS_BELLS
} }