diff --git a/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.java b/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.java
index 5de02c4..ff3f99f 100644
--- a/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.java
+++ b/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.java
@@ -22,6 +22,7 @@ package de.steamwar.fightsystem;
import com.comphenix.tinyprotocol.TinyProtocol;
import de.steamwar.core.Core;
import de.steamwar.fightsystem.ai.LixfelAI;
+import de.steamwar.fightsystem.ai.chaos.ChaosAI;
import de.steamwar.fightsystem.commands.*;
import de.steamwar.fightsystem.countdown.*;
import de.steamwar.fightsystem.event.HellsBells;
@@ -42,6 +43,7 @@ import de.steamwar.fightsystem.utils.*;
import de.steamwar.fightsystem.winconditions.*;
import de.steamwar.message.Message;
import de.steamwar.sql.SchematicNode;
+import de.steamwar.sql.SteamwarUser;
import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
@@ -167,6 +169,13 @@ public class FightSystem extends JavaPlugin {
}else if(Config.mode == ArenaMode.PREPARE) {
Fight.getUnrotated().setSchem(SchematicNode.getSchematicNode(Config.PrepareSchemID));
}
+
+ FightStatistics.unrank();
+
+ Bukkit.getScheduler().runTask(getPlugin(), () -> {
+ new ChaosAI(Fight.getBlueTeam());
+ new LixfelAI(Fight.getRedTeam(), "Lixfel.AI");
+ });
}
@Override
diff --git a/FightSystem_Core/src/de/steamwar/fightsystem/ai/AI.java b/FightSystem_Core/src/de/steamwar/fightsystem/ai/AI.java
index 17bed39..fc76c0e 100644
--- a/FightSystem_Core/src/de/steamwar/fightsystem/ai/AI.java
+++ b/FightSystem_Core/src/de/steamwar/fightsystem/ai/AI.java
@@ -155,8 +155,10 @@ public abstract class AI {
return;
Location location = translate(pos, true);
- if(interactionDistanceViolation(location))
+ if(interactionDistanceViolation(location)) {
+ chat("Zu kleine Arme für TNT!");
return;
+ }
Block block = location.getBlock();
if(block.getType() == Material.AIR)
@@ -170,8 +172,10 @@ public abstract class AI {
@Override
public void run() {
Location location = translate(pos, true);
- if(interactionDistanceViolation(location))
+ if(interactionDistanceViolation(location)) {
+ chat("Ich komme da nicht dran!");
return;
+ }
interact(location.getBlock());
}
@@ -205,7 +209,7 @@ public abstract class AI {
public void run() {
Location location = entity.getLocation();
Location target = translate(pos, false);
- if(Math.abs(location.getX() - target.getX()) > 1 || Math.abs(location.getY() - target.getY()) > 1.2 || Math.abs(location.getZ() - target.getZ()) > 1) {
+ if(Math.abs(location.getX() - target.getX()) > 1.9 || Math.abs(location.getY() - target.getY()) > 1.9 || Math.abs(location.getZ() - target.getZ()) > 1.9) {
FightSystem.getPlugin().getLogger().log(Level.INFO, () -> entity.getName() + ": Overdistance movement " + location.toVector() + " " + target.toVector());
return;
}
@@ -287,7 +291,7 @@ public abstract class AI {
queue.poll().run();
}
- private Location translate(Vector pos, boolean blockPos) {
+ public Location translate(Vector pos, boolean blockPos) {
Region extend = team.getExtendRegion();
if(Fight.getUnrotated() == team)
return new Location(
diff --git a/FightSystem_Core/src/de/steamwar/fightsystem/ai/chaos/Bridge.java b/FightSystem_Core/src/de/steamwar/fightsystem/ai/chaos/Bridge.java
new file mode 100644
index 0000000..076b93f
--- /dev/null
+++ b/FightSystem_Core/src/de/steamwar/fightsystem/ai/chaos/Bridge.java
@@ -0,0 +1,31 @@
+/*
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2023 SteamWar.de-Serverteam
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package de.steamwar.fightsystem.ai.chaos;
+
+import org.bukkit.util.Vector;
+
+public class Bridge {
+ private Bridge() {
+ }
+
+ public static final Vector BRIDGE_POS = new Vector(25, 14, 24);
+ public static final Vector BRIDGE_SHIELDS = new Vector(25, 15, 25);
+ public static final Vector BRIDGE_MG = new Vector(21, 15, 24);
+}
diff --git a/FightSystem_Core/src/de/steamwar/fightsystem/ai/chaos/Cannon.java b/FightSystem_Core/src/de/steamwar/fightsystem/ai/chaos/Cannon.java
new file mode 100644
index 0000000..f1abd8a
--- /dev/null
+++ b/FightSystem_Core/src/de/steamwar/fightsystem/ai/chaos/Cannon.java
@@ -0,0 +1,172 @@
+/*
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2023 SteamWar.de-Serverteam
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package de.steamwar.fightsystem.ai.chaos;
+
+import org.bukkit.util.Vector;
+
+public class Cannon {
+ public final Vector[] tnt;
+ public final Vector button;
+ public final Vector load;
+ public final Vector escape;
+ public final String name;
+
+ private Cannon(String name, Vector[] tnt, Vector button, Vector load, Vector escape) {
+ this.tnt = tnt;
+ this.button = button;
+ this.load = load;
+ this.escape = escape;
+ this.name = name;
+ }
+
+ public static final Vector[] DS_LEFT_TNT = new Vector[] {
+ new Vector(40, 24, 12),
+ new Vector(39, 24, 12),
+ new Vector(38, 23, 12),
+ new Vector(38, 24, 12),
+ new Vector(40, 23, 15),
+ new Vector(40, 23, 14),
+ new Vector(40, 24, 15),
+ new Vector(40, 24, 14),
+ new Vector(38, 23, 15),
+ new Vector(38, 23, 14),
+ new Vector(38, 24, 15),
+ new Vector(38, 24, 14),
+ new Vector(40, 23, 12),
+ };
+ public static final Vector DS_LEFT_BUTTON = new Vector(39, 25, 11);
+ public static final Vector DS_LEFT_LOAD = new Vector(39, 25, 13);
+ public static final Vector DS_LEFT_ESCAPE = new Vector(19, 26, 13);
+ public static final Cannon DS_LEFT = new Cannon("Downstäb Links", DS_LEFT_TNT, DS_LEFT_BUTTON, DS_LEFT_LOAD, DS_LEFT_ESCAPE);
+
+ public static final Vector[] DS_RIGHT_TNT = new Vector[] {
+ new Vector(12, 24, 12),
+ new Vector(11, 24, 12),
+ new Vector(10, 23, 12),
+ new Vector(10, 24, 12),
+ new Vector(10, 23, 15),
+ new Vector(10, 23, 14),
+ new Vector(10, 24, 15),
+ new Vector(10, 24, 14),
+ new Vector(12, 23, 14),
+ new Vector(12, 24, 14),
+ new Vector(12, 23, 15),
+ new Vector(12, 24, 15),
+ new Vector(12, 23, 12),
+ };
+ public static final Vector DS_RIGHT_BUTTON = new Vector(11, 25, 11);
+ public static final Vector DS_RIGHT_LOAD = new Vector(11, 25, 13);
+ public static final Vector DS_RIGHT_ESCAPE = new Vector(31, 26, 13);
+ public static final Cannon DS_RIGHT = new Cannon("Downstäb Rechts", DS_RIGHT_TNT, DS_RIGHT_BUTTON, DS_RIGHT_LOAD, DS_RIGHT_ESCAPE);
+
+ public static final Vector[] STATIC_LEFT_TNT = new Vector[] {
+ new Vector(37, 17, 15),
+ new Vector(37, 17, 14),
+ new Vector(37, 18, 16),
+ new Vector(37, 18, 15),
+ new Vector(37, 18, 14),
+ new Vector(36, 17, 16),
+ new Vector(36, 17, 15),
+ new Vector(36, 17, 14),
+ new Vector(36, 18, 16),
+ new Vector(36, 18, 15),
+ new Vector(36, 18, 14),
+ new Vector(37, 17, 16),
+ };
+ public static final Vector STATIC_LEFT_BUTTON = new Vector(38, 18, 11);
+ public static final Vector STATIC_LEFT_LOAD = new Vector(37, 16, 12);
+ public static final Vector STATIC_LEFT_ESCAPE = new Vector(30, 13, 9);
+ public static final Cannon STATIC_LEFT = new Cannon("Lupf Links", STATIC_LEFT_TNT, STATIC_LEFT_BUTTON, STATIC_LEFT_LOAD, STATIC_LEFT_ESCAPE);
+
+ public static final Vector[] STATIC_RIGHT_TNT = new Vector[] {
+ new Vector(14, 17, 15),
+ new Vector(14, 18, 16),
+ new Vector(14, 18, 15),
+ new Vector(14, 17, 14),
+ new Vector(14, 18, 14),
+ new Vector(13, 17, 16),
+ new Vector(13, 17, 15),
+ new Vector(13, 17, 14),
+ new Vector(13, 18, 16),
+ new Vector(13, 18, 15),
+ new Vector(13, 18, 14),
+ new Vector(14, 17, 16),
+ };
+ public static final Vector STATIC_RIGHT_BUTTON = new Vector(12, 18, 11);
+ public static final Vector STATIC_RIGHT_LOAD = new Vector(13, 17, 12);
+ public static final Vector STATIC_RIGHT_ESCAPE = new Vector(20, 13, 9);
+ public static final Cannon STATIC_RIGHT = new Cannon("Lupf Rechts", STATIC_RIGHT_TNT, STATIC_RIGHT_BUTTON, STATIC_RIGHT_LOAD, STATIC_RIGHT_ESCAPE);
+
+ public static final Vector[] AK_TNT = new Vector[] {
+ new Vector(10, 7, 17),
+ new Vector(10, 11, 17),
+ new Vector(10, 10, 17),
+ new Vector(10, 8, 17),
+ new Vector(10, 9, 17),
+ new Vector(10, 7, 15),
+ new Vector(11, 7, 15),
+ new Vector(12, 7, 15),
+ new Vector(10, 10, 15),
+ new Vector(11, 10, 15),
+ new Vector(12, 10, 15),
+ new Vector(12, 8, 15),
+ new Vector(12, 9, 15),
+ new Vector(11, 8, 15),
+ new Vector(11, 9, 15),
+ new Vector(10, 8, 15),
+ new Vector(10, 9, 15),
+ new Vector(10, 7, 19),
+ new Vector(11, 7, 19),
+ new Vector(12, 7, 19),
+ new Vector(12, 8, 19),
+ new Vector(11, 8, 19),
+ new Vector(10, 8, 19),
+ new Vector(10, 10, 19),
+ new Vector(11, 10, 19),
+ new Vector(12, 10, 19),
+ new Vector(12, 9, 19),
+ new Vector(11, 9, 19),
+ new Vector(10, 9, 19),
+ new Vector(10, 6, 17),
+ };
+ public static final Vector AK_BUTTON = new Vector(9, 9, 16);
+ public static final Vector AK_LOAD = new Vector(11, 8, 17);
+ public static final Cannon AK = new Cannon("Arschkratzer", AK_TNT, AK_BUTTON, AK_LOAD, null);
+
+ public static final Vector[] HA_RIGHT_TNT = new Vector[] {
+ new Vector(23, 6, 9),
+ new Vector(23, 7, 9),
+ new Vector(23, 8, 9),
+ new Vector(23, 5, 9),
+ };
+
+ public static final Vector[] HA_LEFT_TNT = new Vector[] {
+ new Vector(27, 6, 9),
+ new Vector(27, 7, 9),
+ new Vector(27, 8, 9),
+ new Vector(27, 5, 9),
+ };
+
+ public static final Vector HA_RIGHT_LOAD = new Vector(23, 8, 8);
+ public static final Vector HA_LEFT_LOAD = new Vector(27, 8, 8);
+
+ public static final Cannon HA_LEFT = new Cannon("Halbautomatik Links", HA_LEFT_TNT, null, HA_LEFT_LOAD, null);
+ public static final Cannon HA_RIGHT = new Cannon("Halbautomatik Rechts", HA_RIGHT_TNT, null, HA_RIGHT_LOAD, null);
+}
diff --git a/FightSystem_Core/src/de/steamwar/fightsystem/ai/chaos/ChaosAI.java b/FightSystem_Core/src/de/steamwar/fightsystem/ai/chaos/ChaosAI.java
new file mode 100644
index 0000000..cf251b6
--- /dev/null
+++ b/FightSystem_Core/src/de/steamwar/fightsystem/ai/chaos/ChaosAI.java
@@ -0,0 +1,168 @@
+/*
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2023 SteamWar.de-Serverteam
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package de.steamwar.fightsystem.ai.chaos;
+
+import de.steamwar.fightsystem.FightSystem;
+import de.steamwar.fightsystem.ai.AI;
+import de.steamwar.fightsystem.ai.LixfelPathplanner;
+import de.steamwar.fightsystem.fight.FightTeam;
+import de.steamwar.fightsystem.states.FightState;
+import de.steamwar.sql.SchematicNode;
+import de.steamwar.sql.SteamwarUser;
+import org.bukkit.Bukkit;
+import org.bukkit.util.Vector;
+
+import java.util.Random;
+
+public class ChaosAI extends AI {
+ private final LixfelPathplanner pathplanner = new LixfelPathplanner(chooseSchematic());
+ private State state = State.PRE_PREPARE;
+ private static final Cannon[] cannons = new Cannon[] {
+ Cannon.DS_LEFT,
+ Cannon.DS_RIGHT,
+ Cannon.STATIC_LEFT,
+ Cannon.STATIC_RIGHT,
+ Cannon.HA_LEFT,
+ Cannon.HA_RIGHT,
+ };
+ private Cannon currentCannon = randomCannon();
+ private boolean igniteMg = false;
+ private static final Random random = new Random();
+
+
+ public ChaosAI(FightTeam team) {
+ this(team, SteamwarUser.get(14533));
+ }
+
+
+ public ChaosAI(FightTeam team, SteamwarUser user) {
+ super(team, user);
+ }
+
+ @Override
+ public SchematicNode chooseSchematic() {
+ return SchematicNode.getSchematicNode(111476);
+ }
+
+ @Override
+ protected void plan() {
+ switch (state) {
+ case PRE_PREPARE:
+ Bukkit.getScheduler().runTaskLater(FightSystem.getPlugin(), () -> {
+ state = State.PREPARE;
+ }, 20 * 15);
+ state = State.PREPARING_PREPARE;
+ break;
+ case PREPARING_PREPARE:
+ break;
+ case PREPARE:
+ prepare();
+ state = State.PREPARE_READY;
+ break;
+ case PREPARE_READY:
+ setReady();
+ state = State.WAIT_TILL_START;
+ break;
+ case WAIT_TILL_START:
+ if (FightState.ingame()) {
+ state = State.IGNITE_MG;
+ startFight();
+ }
+ break;
+ case IGNITE_MG:
+ if(igniteMg) {
+ interact(Bridge.BRIDGE_MG);
+ chat("Die MG ist angezündet!");
+ state = State.FIGHT;
+ currentCannon = randomCannon();
+ }
+ break;
+ case FIGHT:
+ fireCannon(currentCannon);
+ break;
+ case ESCAPE:
+ if (currentCannon.escape != null) {
+ pathplanner.planToAnywhere(getPosition(), currentCannon.escape).forEach(this::move);
+ }
+
+ Cannon nextCannon = randomCannon();
+ while (nextCannon == currentCannon) {
+ nextCannon = randomCannon();
+ }
+
+ currentCannon = nextCannon;
+
+ state = State.FIGHT;
+ break;
+ }
+ }
+
+ public void fireCannon(Cannon cannon) {
+ chat("Ich feuere " + cannon.name + " an!");
+ pathplanner.planToAnywhere(getPosition(), cannon.load).forEach(this::move);
+ if (cannon.button == null) {
+ for (int i = 0; i < 20; i++) {
+ for (Vector vector : cannon.tnt) {
+ setTNT(vector);
+ }
+ for (int j = 0; j < 30; j++) {
+ getBlock(Bridge.BRIDGE_MG);
+ }
+ }
+ } else {
+ for (Vector vector : cannon.tnt) {
+ setTNT(vector);
+ }
+ interact(cannon.button);
+ }
+
+ state = State.ESCAPE;
+ }
+
+ private Cannon randomCannon() {
+ return cannons[random.nextInt(cannons.length)];
+ }
+
+ public void startFight() {
+ chat("gl&hf");
+ chat("Ich zünde die MG an!");
+ Bukkit.getScheduler().runTaskLater(FightSystem.getPlugin(), () -> {
+ igniteMg = true;
+ }, 20 * 21);
+ }
+
+ public void prepare() {
+ chat("Prepare your fkin 4nus");
+ pathplanner.planToAnywhere(getPosition(), Bridge.BRIDGE_POS).forEach(this::move);
+ interact(Bridge.BRIDGE_SHIELDS);
+ }
+
+ private enum State {
+ PRE_PREPARE,
+ PREPARING_PREPARE,
+ PREPARE,
+ PREPARE_READY,
+ WAIT_TILL_START,
+ IGNITE_MG,
+ FIGHT,
+ ESCAPE,
+
+ }
+}
diff --git a/FightSystem_Core/src/de/steamwar/fightsystem/ai/chaos/recorder.lua b/FightSystem_Core/src/de/steamwar/fightsystem/ai/chaos/recorder.lua
new file mode 100644
index 0000000..e821361
--- /dev/null
+++ b/FightSystem_Core/src/de/steamwar/fightsystem/ai/chaos/recorder.lua
@@ -0,0 +1,25 @@
+event(events.PlaceBlock, function(e)
+ if storage.player.get("recording") then
+ pos = {math.floor(e.x), math.floor(e.y) - 100, math.floor(e.z)}
+ storage.player.get("recordingPos")[storage.player.get("recordingCount")] = pos
+ storage.player.set("recordingCount", storage.player.get("recordingCount") + 1)
+ end
+end)
+
+command("recorder", function(args)
+ if storage.player.get("recording") then
+ storage.player.set("recording", false)
+ storage.player.set("recordingCount", 0)
+ print("private static final Vector[] positions = new Vector[] {")
+ for k, v in pairs(storage.player.get("recordingPos")) do
+ print("new Vector(" .. v[1] .. ", " .. v[2] .. ", " .. v[3] .. "),")
+ end
+ print("};")
+ print("Stopped recording")
+ else
+ storage.player.set("recording", true)
+ storage.player.set("recordingCount", 0)
+ storage.player.set("recordingPos", {})
+ print("Started recording")
+ end
+end)
\ No newline at end of file
diff --git a/FightSystem_Core/src/de/steamwar/fightsystem/ai/chaos/sw.def.lua b/FightSystem_Core/src/de/steamwar/fightsystem/ai/chaos/sw.def.lua
new file mode 100644
index 0000000..d1570fd
--- /dev/null
+++ b/FightSystem_Core/src/de/steamwar/fightsystem/ai/chaos/sw.def.lua
@@ -0,0 +1,343 @@
+-- This file is a part of the SteamWar software.
+--
+-- Copyright (C) 2021 SteamWar.de-Serverteam
+--
+-- This program is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU Affero General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-- GNU Affero General Public License for more details.
+--
+-- You should have received a copy of the GNU Affero General Public License
+-- along with this program. If not, see .
+
+---
+--- This file contains the definitions for the SteamWar.de script API.
+--- It is used by the IDE to provide code completion and type checking.
+--- Created by Chaoscaot
+---
+
+inventory = {}
+
+---@param title string
+---@param size number
+---@return Inventory
+function inventory.create(title, size) return nil end
+
+---@alias InventoryClick 'LEFT' | 'SHIFT_LEFT' | 'RIGHT' | 'SHIFT_RIGHT' | 'MIDDLE' | 'NUMBER_KEY'
+
+---@class Inventory
+local Inventory = {}
+
+---@overload fun(slot: number, material: string, name: string, handler: fun(click: InventoryClick)): void
+---@overload fun(slot: number, material: string, name: string, handler: fun(click: InventoryClick), lore: string[]): void
+---@overload fun(slot: number, material: string, name: string, handler: fun(click: InventoryClick), lore: string[], enchanted: boolean): void
+---@param slot number
+---@param material string
+---@param name string
+---@param handler fun(click: InventoryClick): void
+---@param lore string[]
+---@param enchanted boolean
+---@param amount number
+---@return void
+function Inventory.item(slot, material, name, handler, lore, enchanted, amount) end
+
+---@param handler fun(): void
+---@return void
+function Inventory.setCloseHandler(handler) end
+
+---@return void
+function Inventory.open() end
+
+player = {}
+
+---@return string
+---Get the name of the player.
+function player.name() return "" end
+
+---@return void
+function player.chat(...) end
+
+---@return void
+---Send a message to the actionbar of the player.
+function player.actionbar(...) end
+
+---@overload fun(): number
+---@param newX number
+function player.x(newX) end
+
+---@overload fun(): number
+---@param newY number
+function player.y(newY) end
+
+---@overload fun(): number
+---@param newZ number
+function player.z(newZ) end
+
+---@overload fun(): number
+---@param newYaw number
+function player.yaw(newYaw) end
+
+---@overload fun(): number
+---@param newPitch number
+function player.pitch(newPitch) end
+
+---@return boolean
+function player.sneaking() return nil end
+
+---@return boolean
+function player.sprinting() return nil end
+
+---@overload fun(): number
+---@param newSlot number
+function player.slot(newSlot) end
+
+---@return string
+function player.item() return nil end
+
+---@return string
+function player.offHandItem() return nil end
+
+---@return void
+function player.closeInventory() end
+
+---@field nextBool fun(): boolean
+random = {}
+
+---@overload fun(): number
+---@overload fun(bound: number): number
+---@param origin number
+---@param bound number
+---@return number
+function random.nextInt(origin, bound) return nil end
+
+---@overload fun(): number
+---@overload fun(bound: number): number
+---@param origin number
+---@param bound number
+---@return number
+function random.nextDouble(origin, bound) return nil end
+
+---@return boolean
+function random.nextBool() return nil end
+
+---@alias RegionType 'wg' | 'mwg' | 'as' | 'ws' | 'ws_inner' | 'ws_rumpf' | 'ws_rahmen' | 'spawn'
+
+---@class iregion
+---@field tnt tnt
+---@field trace trace
+local iregion = {}
+
+---@class region: iregion
+region = {}
+
+---@return string
+function iregion.name() return nil end
+
+---@return RegionType
+function iregion.type() return nil end
+
+---@return boolean
+function iregion.fire() return nil end
+
+---@return boolean
+function iregion.freeze() return nil end
+
+---@return boolean
+function iregion.protect() return nil end
+
+---@return string
+function iregion.loader() return nil end
+
+---@alias TNTMode 'ALLOW' | 'DENY' | 'ONLY_TB'
+
+---@class tnt
+local tnt = {}
+
+---@return TNTMode
+function tnt.mode() return nil end
+
+---@return boolean
+function tnt.enabled() return nil end
+
+---@return boolean
+function tnt.onlyTb() return nil end
+
+---@class trace
+local trace = {}
+
+---@return boolean
+function trace.active() return nil end
+
+---@return boolean
+function trace.auto() return nil end
+
+---@return string
+function trace.status() return nil end
+
+---@return number
+function trace.time() return nil end
+
+---@param name string
+---@return iregion
+function region.get(name) return nil end
+
+---@return iregion[]
+function region.list() return nil end
+
+---@class Position
+---@field x number
+---@field y number
+---@field z number
+
+---@class server
+---@field tps tps
+server = {}
+
+---@return string
+function server.time() return nil end
+
+---@return number
+function server.ticks() return nil end
+
+---@param position Position
+---@return string
+function getBlockAt(position) return nil end
+
+---@param position Position
+---@param material string
+---@return void
+function setBlockAt(position, material) return nil end
+
+---@class tps
+local tps = {}
+
+---@return number
+function tps.oneSecond() return nil end
+
+---@return number
+function tps.tenSecond() return nil end
+
+---@return number
+function tps.oneMinute() return nil end
+
+---@return number
+function tps.fiveMinute() return nil end
+
+---@return number
+function tps.tenMinute() return nil end
+
+---@return number
+function tps.current() return nil end
+
+---@return number
+function tps.limit() return nil end
+
+---@class storage
+---@field global storageLib
+---@field player storageLib
+---@field region storageLib
+storage = {}
+
+---@class storageLib
+local storageLib = {}
+
+---@param key string
+---@return any
+function storageLib.get(key) return nil end
+
+---@param key string
+---@param value any
+---@return void
+function storageLib.set(key, value) end
+
+---@param key string
+---@return boolean
+function storageLib.has(key) return nil end
+
+---@param key string
+---@return void
+function storageLib.remove(key) end
+
+---@param key string
+---@return Accessor
+function storageLib.accessor(key) return nil end
+
+---@class Accessor
+---@overload fun(): any
+---@overload fun(value: any)
+
+---@class Selection
+---@field max Position
+---@field min Position
+
+---@class _worldedit
+_worldedit = {}
+
+---@overload fun(pos: Position[]): void
+---@return Selection
+function _worldedit.selection() return nil end
+
+---@param msg string
+---@param callback fun(value: string): void
+---@return void
+function input(msg, callback) end
+
+---@param ticks number
+---@param callback fun(): void
+---@return void
+function delayed(ticks, callback) end
+
+---@param x number
+---@param y number
+---@param z number
+---@return Position
+function pos(x, y, z) return nil end
+
+---@return void
+function exec(...) end
+
+---@param obj any
+---@return number
+function length(obj) return 0 end
+
+---@param separator string
+---@param table any[]
+---@return string
+function join(separator, table) return "" end
+
+---@class EventType
+---@class events
+---@field DoubleSwap EventType
+---@field PlaceBlock EventType
+---@field BreakBlock EventType
+---@field RightClick EventType
+---@field LeftClick EventType
+---@field TNTSpawn EventType
+---@field TNTExplode EventType
+---@field TNTExplodeInBuild EventType
+---@field SelfJoin EventType
+---@field SelfLeave EventType
+---@field DropItem EventType
+---@field EntityDeath EventType
+events = {}
+
+
+---@param id EventType
+---@param handler fun(params: any): void
+---@return void
+function event(id, handler) end
+
+---@param command string
+---@param handler fun(params: string[]): void
+---@return void
+function command(command, handler) end
+
+---@param trigger string
+---@param handler fun(pressed: boolean): void
+---@return void
+function hotkey(trigger, handler) end