Trace Refactor #233

Zusammengeführt
YoyoNow hat 121 Commits von TracerGUI nach master 2024-04-21 16:03:26 +02:00 zusammengeführt
45 geänderte Dateien mit 3356 neuen und 3385 gelöschten Zeilen

8
.gitignore vendored
Datei anzeigen

@ -1,5 +1,7 @@
# Package Files
# Build files
*.jar
**/bin
**/build
# Gradle
.gradle
@ -10,6 +12,10 @@ steamwar.properties
# IntelliJ IDEA
.idea
*.iml
plugin.yml
# Other
lib
#linkage
LinkageUtils.java

Datei anzeigen

@ -1,39 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.tracer.record;
import net.minecraft.server.v1_15_R1.EntityTNTPrimed;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_15_R1.CraftWorld;
import org.bukkit.entity.TNTPrimed;
import java.util.stream.Stream;
public class TNTPrimedIterator15 implements TNTPrimedIterator {
private static final CraftWorld WORLD = (CraftWorld) Bukkit.getWorlds().get(0);
@Override
public Stream<TNTPrimed> iterator() {
return WORLD.getHandle().entitiesById.values().stream()
.filter(EntityTNTPrimed.class::isInstance)
.map(entity -> (TNTPrimed) entity.getBukkitEntity());
}
}

Datei anzeigen

@ -1,46 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.tracer.record;
import com.comphenix.tinyprotocol.Reflection;
import net.minecraft.server.level.WorldServer;
import net.minecraft.world.level.entity.LevelEntityGetter;
import org.bukkit.Bukkit;
import org.bukkit.entity.TNTPrimed;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
public class TNTPrimedIterator18 implements TNTPrimedIterator {
private static final Reflection.MethodInvoker getWorld = Reflection.getMethod(Reflection.getClass("{obc}.CraftWorld"), "getHandle");
private static final Reflection.MethodInvoker getWorldEntities = Reflection.getTypedMethod(WorldServer.class, null, LevelEntityGetter.class);
private static final Reflection.MethodInvoker getIterable = Reflection.getTypedMethod(LevelEntityGetter.class, null, Iterable.class);
private static final Reflection.MethodInvoker getBukkitEntity = Reflection.getTypedMethod(Reflection.getClass("{nms.world.entity}.Entity"), "getBukkitEntity", null);
@Override
public Stream<TNTPrimed> iterator() {
return StreamSupport.stream(((Iterable<?>) getIterable.invoke(getWorldEntities.invoke(getWorld.invoke(Bukkit.getWorlds().get(0))))).spliterator(), false)
.map(getBukkitEntity::invoke)
.filter(TNTPrimed.class::isInstance)
.map(TNTPrimed.class::cast);
}
}

Datei anzeigen

@ -16,21 +16,17 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
PREFIX=§eBau§8System§8»
TIME=HH:mm:ss
DATE=........
COMMAND_HELP_HEAD=§7---=== (§e{0}§7) ===---
ONLY_SCHEMS=§cFolders are unselectable
PAGE_LIST=§e Page ({0}/{1}) »»
LIST_PREVIOUS_PAGE=§ePrevious page
LIST_NEXT_PAGE=§eNext page
# Permissions
NO_PERMISSION=You are not allowed to use that here
SPECTATOR=§fSpectator
# Scoreboard
SCOREBOARD_TIME=Time
SCOREBOARD_REGION=Region
@ -38,17 +34,13 @@ SCOREBOARD_TRACE = Trace
SCOREBOARD_LOADER=Loader
SCOREBOARD_TPS=TPS
SCOREBOARD_TPS_FROZEN=§eFrozen
SCOREBOARD_TRACE_TICKS=Ticks
SCOREBOARD_TECHHIDER=TechHider§8: §aOn
SCOREBOARD_XRAY=XRay§8: §aOn
SCOREBOARD_LOCK_TEAM=Bau Lock§8: §eTeam
SCOREBOARD_LOCK_TEAM_AND_SERVERTEAM=Bau Lock§8: §e(Server) Team
SCOREBOARD_LOCK_SERVERTEAM=Bau Lock§8: §eServer Team
SCOREBOARD_LOCK_NOBODY=Bau Lock§8: §cNobody
# Flags
FLAG_COLOR=Color
FLAG_TNT=TNT
@ -56,24 +48,18 @@ FLAG_FIRE = Fire
FLAG_FREEZE=Freeze
FLAG_PROTECT=Protect
FLAG_ITEMS=Items
FLAG_FIRE_ALLOW=§con
FLAG_FIRE_DENY=§aoff
FLAG_FREEZE_ACTIVE=§aon
FLAG_FREEZE_INACTIVE=§coff
FLAG_PROTECT_ACTIVE=§aon
FLAG_PROTECT_INACTIVE=§coff
FLAG_TNT_ALLOW=§aon
FLAG_TNT_DENY=§coff
FLAG_TNT_ONLY_TB=§7no §ebuild area
FLAG_TNT_ONLY_BUILD=§7no §etestblock area
FLAG_ITEMS_ACTIVE=§aon
FLAG_ITEMS_INACTIVE=§coff
FLAG_COLOR_WHITE=§fWhite
FLAG_COLOR_ORANGE=§6Orange
FLAG_COLOR_MAGENTA=§dMagenta
@ -92,22 +78,18 @@ FLAG_COLOR_BROWN = §eBrown
FLAG_COLOR_GREEN=§2Green
FLAG_COLOR_RED=§cRed
FLAG_COLOR_BLACK=§0Black
# Region
REGION_TYPE_NORMAL=Normal
REGION_TYPE_BUILD=Build area
REGION_TYPE_ONLY_TB=Dummy
# AttributesCopy
ATTRIBUTES_CANT_COPY=§cYou need to hold the same item type and hover over the same block to copy.
ATTRIBUTES_NO_COPY=§cNo attributes to copy.
ATTRIBUTES_COPIED=§eAttributes copied.
ATTRIBUTE_REMOVE_COMMAND_HELP=§8/§eattributeremove §8[§eattribute§8|§7all§8|§7*§8]
ATTRIBUTE_REMOVE_ALL=§eAll attributes removed.
ATTRIBUTE_REMOVE_SINGLE=§eAttribute §7{0}§e removed.
ATTRIBUTE_REMOVE_NOT_FOUND=§cAttribute not found
# AutoStart
AUTOSTART_COMMAND_HELP=§8/§etimer §8- §7Retrieve AutostartTimer Tool
AUTOSTART_ITEM_NAME=§eAutostartTimer
@ -118,7 +100,6 @@ AUTOSTART_MESSAGE_START = §eAutostartTimer started
AUTOSTART_MESSAGE_RESULT1=§eTime §7until §eexplosion §7at enemy§8:§e {0}§7 game ticks
AUTOSTART_MESSAGE_RESULT2=§7Time difference in §egame-ticks §7until {0} seconds§8:§e {1}
AUTOSTART_MESSAGE_RESULT3=§7positive, if too few, negative if too many
# Backup
BACKUP_HELP_CREATE=§8/§ebackup create §8- §7Create a region backup
BACKUP_HELP_LOAD=§8/§ebackup load §8[§7BackupName§8] §8- §7Load a region backup
@ -135,10 +116,8 @@ BACKUP_LOAD=§7Backup loaded
BACKUP_INV_NAME=§eBackup
BACKUP_ITEM_NAME=§eBackup §7from §e{0}
BACKUP_LORE=§eClick to load
# Bau
BAU_COMMAND_HELP_INFO=§8/§ebau info §8- §7Alias for §8/§ebauinfo
BAU_INFO_ITEM_NAME=§eBau-Management
## This is used in BauInfoBauGuiItem.java
BAU_INFO_ITEM_LORE_TNT=§7TNT§8: §e{0}
@ -147,13 +126,11 @@ BAU_INFO_ITEM_LORE_FIRE = §7Fire§8: §e{0}
BAU_INFO_ITEM_LORE_COLOR=§7Color§8: §e{0}
BAU_INFO_ITEM_LORE_PROTECT=§7Protect§8: §e{0}
BAU_INFO_ITEM_LORE_ITEMS=§7Items§8: §e{0}
BAU_INFO_COMMAND_HELP=§8/§ebauinfo §8- §7Information regarding this build server
BAU_INFO_COMMAND_OWNER=§7Owner§8: §e{0}
BAU_INFO_COMMAND_MEMBER=§7{0} §8[§7{1}§8]§8: §e{2}
BAU_INFO_COMMAND_FLAG=§7{0}§8: §7{1}
BAU_INFO_COMMAND_TPS=§7TPS§8:§e
# Countingwand
COUNTINGWAND_COMMAND_HELP=§8/§ecountingwand §8- §7Receive a CountingWand
COUNTINGWAND_ITEM_NAME=§eMeterstick
@ -163,13 +140,11 @@ COUNTINGWAND_MESSAGE_RCLICK = §7First position at: §8[§7{0}§8, §7{1}§8, §
COUNTINGWAND_MESSAGE_LCLICK=§7Second position at: §8[§7{0}§8, §7{1}§8, §7{2}§8] ({3}§8) ({4}§8)
COUNTINGWAND_MESSAGE_VOLUME=§e{0}
COUNTINGWAND_MESSAGE_DIMENSION=§e{0}§8, §e{1}§8, §e{2}
# Design Endstone
DESIGN_ENDSTONE_COMMAND_HELP=§8/§edesignendstone §8- §7Highlight endstone in design
DESIGN_ENDSTONE_REGION_ERROR=§cThis region has no build area
DESIGN_ENDSTONE_ENABLE=§aEndstone is highlighted
DESIGN_ENDSTONE_DISABLE=§cEndstone is no longer hightlighted
# Detonator
DETONATOR_LOC_REMOVE=§e{0} removed
DETONATOR_LOC_ADD=§e{0} added
@ -219,19 +194,16 @@ GUI_EDITOR_ITEM_TRASH_LORE=§7Drop item here
GUI_EDITOR_ITEM_MORE=§eMore items
GUI_EDITOR_ITEM_CLOSE=§eClose
GUI_EDITOR_TITLE_MORE=Select item
# Script
## Errors
SCRIPT_ERROR_GUI=§cError in parsing script: Line {0}
SCRIPT_ERROR_GLOBAL=§cError in global script: Line {0}
SCRIPT_ERROR_CLICK=§cError in script: Line {0}
SCRIPT_ERROR_ONLY_IN_GLOBAL=§cThis function is only available in global scripts
## CustomScript
SCRIPT_HOTKEY_ITEM_NAME=§7Hotkey§8: §e{0}
SCRIPT_EVENT_ITEM_NAME=§7Event§8: §e{0}
SCRIPT_COMMAND_ITEM_NAME=§7Command§8: §e/{0}
## Script Menu GUI
SCRIPT_MENU_GUI_ITEM_LORE_1=§7Click to retrieve
SCRIPT_MENU_GUI_ITEM_LORE_2=§7Shift-Click to copy
@ -240,10 +212,8 @@ SCRIPT_MENU_GUI_ITEM_LORE_4 = §7Middle-Click to preview
SCRIPT_MENU_GUI_NAME=§eScript-Menu
SCRIPT_MENU_GUI_ITEM_ADD_NAME=§eInsert
SCRIPT_MENU_GUI_ITEM_ADD_LORE=§7Click with a book to insert
SCRIPT_MENU_GUI_ENTER_NAME=§eEnter a name
SCRIPT_DEPRECATED=§cThe function §8\'§e{0}§8\'§c is deprecated and will be removed in the future. Please use §8\'§e{1}§8\'§c instead.
# Shield Printing
SHIELD_PRINTING_HELP_START=§8/§eshieldprinting start §8- §7Starts the shield printing
SHIELD_PRINTING_HELP_COPY=§8/§eshieldprinting copy §8- §7Copies the shield configuration
@ -256,12 +226,10 @@ SHIELD_PRINTING_HELP_STEP_4 = §84. §7Edit the shields if necessary
SHIELD_PRINTING_HELP_STEP_5=§85. §7Copy the shields printing with §8/§eshieldprinting copy
SHIELD_PRINTING_HELP_STEP_6=§86. §7Paste the original schematic
SHIELD_PRINTING_HELP_STEP_7=§87. §7Apply the shield printing with §8/§eshieldprinting apply
SHIELD_PRINTING_NO_REGION=§cYou are not in a region.
SHIELD_PRINTING_NOT_RUNNING=§cThe shield printing is not running.
SHIELD_PRINTING_BOSSBAR=§fMovements: {0}
SHIELD_PRINTING_BOSSBAR_COPIED=§fMovements: {0} Copied: {1}
SHIELD_PRINTING_GUI_NAME=§7Shield Printing
SHIELD_PRINTING_GUI_APPLY=§aApply
SHIELD_PRINTING_GUI_STATE_PREVIOUS=§7R-Click§8: §7Previous
@ -279,15 +247,12 @@ SHIELD_PRINTING_GUI_STATE_OPENABLE = §7{0} §fOpened
SHIELD_PRINTING_GUI_STATE_PISTON=§7{0} §fExtended
SHIELD_PRINTING_GUI_STATE_POWERABLE=§7{0} §fPowered
SHIELD_PRINTING_GUI_STATE_WALL=§7{0} §fWall Connections
SHIELD_PRINTING_START=§aThe shield printing has been started.
SHIELD_PRINTING_COPY=§aThe shield has been copied.
SHIELD_PRINTING_APPLY=§aThe shield has been applied.
SHIELD_PRINTING_STOP=§aThe shield printing has been stopped.
# Unsign Book
UNSIGN_HELP=§8/§eunsign §8- §7Make a signed book writable again
# Simulator
SIMULATOR_HELP=§8/§esimulator §8-§7 Gives you the simulator wand
SIMULATOR_CREATE_HELP=§8/§esimulator create §8[§7name§8] §8-§7 Create a new simulator
@ -295,9 +260,7 @@ SIMULATOR_CHANGE_HELP = §8/§esimulator change §8-§7 Change your simulator wa
SIMULATOR_DELETE_HELP=§8/§esimulator delete §8[§7name§8] §8-§7 Deletes the simulator
SIMULATOR_START_HELP=§8/§esimulator start §8[§7name§8] §8-§7 Starts the simulator
SIMULATOR_COPY_HELP=§8/§esimulator copy §8[§7to-copy§8] §8[§7name§8] §8-§7 Copy the simulator
SIMULATOR_GUI_ITEM_NAME=§eTNT Simulator
SIMULATOR_NO_SIM_IN_HAND=§cNo simulator item selected
SIMULATOR_GUI_SELECT_SIM=Simulator selection
SIMULATOR_GUI_CREATE_SIM=§eCreate simulator
@ -311,9 +274,7 @@ SIMULATOR_EDIT_LOCATION = §7Edit position
SIMULATOR_EDIT_PROPERTIES=§7Edit properties
SIMULATOR_EDIT_OTHER=§7Edit other
SIMULATOR_EDIT_GROUP=§7Edit group
SIMULATOR_EDIT_GROUP_MENU=§eEdit group
SIMULATOR_WAND_NAME=§eSimulator
SIMULATOR_WAND_NAME_SELECTED=§7Simulator §8- §e{0}
SIMULATOR_WAND_LORE_1=§eRight click §8- §7Adds a position
@ -321,9 +282,7 @@ SIMULATOR_WAND_LORE_2 = §eSneaking §8- §7Free movement
SIMULATOR_WAND_LORE_3=§eLeft click §8- §7Start the simulation
SIMULATOR_WAND_LORE_4=§eRight click in air §8- §7Opens the gui
SIMULATOR_WAND_LORE_5=§eDouble Sneak §8- §7Swap between TNT and Redstone Block
SIMULATOR_REGION_FROZEN=§cSimulator cannot be used inside frozen regions
## Other
SIMULATOR_PLUS_ONE=§7+1
SIMULATOR_PLUS_PIXEL_SHIFT=§eShift §7Click for §e+0,0625
@ -335,11 +294,8 @@ SIMULATOR_POSITION_X = §7x-Position
SIMULATOR_POSITION_Y=§7y-Position
SIMULATOR_POSITION_Z=§7z-Position
SIMULATOR_BACK=§eBack
SIMULATOR_GUI_TOTAL_TNT=§7Total TNT§8: §e{0}
SIMULATOR_DELETED=§cSimulator deleted
## GUI
SIMULATOR_POSITION_EDIT=§eEdit position
SIMULATOR_POSITION_ADD=§eSet position
@ -363,15 +319,12 @@ SIMULATOR_GUI_NAME = Simulator
SIMULATOR_GUI_DELETE=§cDelete TNT
SIMULATOR_GUI_AUTO_TRACE=§eAutoTrace§8: §7{0}
SIMULATOR_GUI_MOVE_ALL=§eMove all
SIMULATOR_ALIGNMENT_CENTER=§7Alignment§8: §eCenter
SIMULATOR_ALIGNMENT_POSITIVE_X=§7Alignment§8: §ePositive X
SIMULATOR_ALIGNMENT_NEGATIVE_X=§7Alignment§8: §eNegative X
SIMULATOR_ALIGNMENT_POSITIVE_Z=§7Alignment§8: §ePositive Z
SIMULATOR_ALIGNMENT_NEGATIVE_Z=§7Alignment§8: §eNegative Z
SIMULATOR_MOVE_ALL_GUI_NAME=Move TNT
SIMULATOR_TNT_SPAWN_GUI_NAME=Configure TNT {0}
SIMULATOR_TNT_SPAWN_EDIT_LOCATION=- Location
SIMULATOR_TNT_SPAWN_EDIT_PROPERTIES=- Properties
@ -413,19 +366,16 @@ SIMULATOR_TNT_SPAWN_ADD_IGNITION_PHASE = §eAdd prime phase
SIMULATOR_TNT_SPAWN_ADD_TNT=§eAdd TNT
SIMULATOR_TNT_SPAWN_REMOVE_TNT=§cRemove
SIMULATOR_TNT_SPAWN_POSITION_ANVIL_GUI_NAME=Position
# SmartPlace
SMART_PLACE_HELP=§8/§esmartplace §8-§7 Toggles SmartPlace
SMART_PLACE_INFO=§7Places rotatable blocks §eaway§7 from you when §esneaking§7.
SMART_PLACE_ENABLE=§aSmartPlace activated
SMART_PLACE_DISABLE=§cSmartPlace deactivated
# InventoryFiller
INVENTORY_FILL_HELP=§8/§einventoryfill §8- §7Toggles InventoryFill
INVENTORY_FILL_INFO=§7Helps you fill containers by looking at them while sneaking and dropping the item. Or just scroll on a container to change the amount of the item inside.
INVENTORY_FILL_ENABLE=§aInventoryFiller activated
INVENTORY_FILL_DISABLE=§cInventoryFiller deactivated
# Killchecker
KILLCHECKER_HELP_ENABLE=§8/§ekillchecker enable §8- §7Enables Killchecker / Recalculates kills
KILLCHECKER_HELP_DISABLE=§8/§ekillchecker disable §8- §7Disables Killchecker
@ -434,7 +384,6 @@ KILLCHECKER_INFO2 = §7Only colorable blocks like Wool, Terractotta, Stained Gla
KILLCHECKER_ENABLE=§aKillchecker activated
KILLCHECKER_DISABLE=§cKillchecker deactivated
KILLCHECKER_BOSSBAR=§e§l{0} §7(§e{1}%§7) §e§l{2}§7 cannons
# BlockCounter
BLOCK_COUNTER_HELP_TOGGLE=§8/§eblockcounter §8- §7Toggle on/off
BLOCK_COUNTER_HELP_ENABLE=§8/§eblockcounter enable §8- §7Toggles BlockCounter on
@ -443,20 +392,17 @@ BLOCK_COUNTER_MESSAGE = §7Damage §8> §e{0} §7Blocks §e{1} §7TNT §e{2}
BLOCK_COUNTER_MESSAGE_SECOND=§7Damage §8> §e{0} §7Blocks §e{1} §7TNT §e{2} §7Blocks/TNT §e{3} §7Blocks/s
BLOCK_COUNTER_ENABLE=§7BlockCounter activated
BLOCK_COUNTER_DISABLE=§7BlockCounter deactivated
# DepthCounter
DEPTH_COUNTER_MESSAGE=§7Depth §8> §7
DEPTH_COUNTER_COUNT={0}{1}§8×{2}{3}§8×{4}{5}
DEPTH_COUNTER_HOVER=§7X§8ק7Y§8ק7Z
DEPTH_COUNTER_TNT=§7 TNT§8: §e{0}
# TPSLimit
TPSLIMIT_FREEZE_HELP=§8/§etpslimit 0 §8-§7 Freeze TPS
TPSLIMIT_LIMIT_HELP=§8/§etpslimit §8[§720>x>0.5§8] §8-§7 Slow TPS down
TPSLIMIT_WARP_HELP=§8/§etpslimit §8[§7x>20§8] §8-§7 Speed TPS up
TPSLIMIT_DEFAULT_HELP=§8/§etpslimit default §8-§7 Set TPS to 20
TPSLIMIT_HELP=§8/§etpslimit §8-§7 Show current TPS
TICK_FREEZE_HELP=§8/§etick rate 0 §8-§7 Freeze TPS
TICK_FREEZE_HELP_2=§8/§etick freeze §8-§7 Freeze TPS
TICK_UNFREEZE_HELP=§8/§etick unfreeze §8-§7 Set TPS to 20
@ -464,10 +410,8 @@ TICK_LIMIT_HELP = §8/§etick rate §8[§720>x>0.5§8] §8-§7 Slow TPS down
TICK_WARP_HELP=§8/§etick rate §8[§7x>20§8] §8-§7 Speed TPS up
TICK_DEFAULT_HELP=§8/§etick rate default §8-§7 Set TPS to 20
TICK_HELP=§8/§etick rate §8-§7 Show current TPS
TICK_STEPPING_HELP=§8/§etick step §8<§7Ticks§8> §8-§7 Step n ticks or 1 forward
TICK_WARPING_HELP=§8/§etick warp §8<§7Ticks§8> §8<§7TPS§8> §8-§7 Warp n ticks or 1 forward
TICK_BOSSBAR=§7Skipped §e{0}§8/§7{1}
TPSLIMIT_GUI_ITEM_NAME=§eTPS limiter
TPSLIMIT_GUI_ITEM_LORE=§7Currently: §e{0}
@ -475,46 +419,45 @@ TPSLIMIT_ANVIL_GUI = New TPS limit
TPSLIMIT_CURRENT=§7Current TPS limit§8: §e{0}
TPSLIMIT_SET=§eSet TPS limit to {0}
TPSLIMIT_FROZEN=§eTPS frozen
# Trace
TRACE_RECORD=§aon
TRACE_HAS_TRACES=§ehas Traces
TRACE_IDLE_SINGLE=§esingle
TRACE_IDLE_AUTO_EXPLODE=§eauto §8(§7explode§8)
TRACE_IDLE_AUTO_IGNITE=§eauto §8(§7ignite§8)
TRACE_MESSAGE_AUTO_IDLE_EXPLODE = §aAuto-Tracer explode started
TRACE_MESSAGE_AUTO_IDLE_IGNITE = §aAuto-Tracer ignite started
TRACE_MESSAGE_AUTO_DELETE_INVALID = §cAuto delete cannot be used currently
TRACE_MESSAGE_AUTO_DELETE_ALWAYS = §7Last Shot will §ealways §7be deleted
TRACE_MESSAGE_AUTO_DELETE_NEVER = §7Last Shot will §enever §7be deleted
TRACE_MESSAGE_AUTO_DELETE_NO_BUILD_DESTROY = §7Last Shot will be deleted if §eno build §7block was destroyed
TRACE_MESSAGE_AUTO_DELETE_BUILD_DESTROY = §7Last Shot will be deleted if §ea build §7block was destroyed
TRACE_MESSAGE_AUTO_DELETE_NO_TESTBLOCK_DESTROY = §7Last Shot will be deleted if §eno testblock §7block was destroyed
TRACE_MESSAGE_AUTO_DELETE_TESTBLOCK_DESTROY = §7Last Shot will be deleted if §ea testlblock §7block was destroyed
TRACE_IDLE_AUTO=§eauto
TRACE_MESSAGE_START=§aTNT-Tracer started
TRACE_MESSAGE_SINGLE = §aSingle-Tracer started
TRACE_MESSAGE_AUTO_START=§eAuto TNT-Tracer started
TRACE_MESSAGE_AUTO_STOP=§cAuto TNT-Tracer stopped
TRACE_MESSAGE_STOP=§cTNT-Tracer stopped
TRACE_MESSAGE_DELETE = §cAll TNT-positions deleted
TRACE_MESSAGE_CLEAR=§cAll TNT-positions deleted
TRACE_MESSAGE_DELETE=§cTrace TNT-positions deleted
TRACE_MESSAGE_SHOW=§aAll TNT-positions shown
TRACE_MESSAGE_HIDE=§cAll TNT-positions hidden
TRACE_MESSAGE_CLICK_ISOLATE = §eClick to §aisolate§8/§cunisolate
TRACE_MESSAGE_SHOW_AT = §aTNT-positions shown with {0} at {1}
TRACE_MESSAGE_SHOW_FROM = §aAll TNT-positions shown with {0} from {1}
TRACE_MESSAGE_SHOW_FROM_TO = §aAll TNT-positions shown with {0} from {1} to {2}
TRACE_MESSAGE_SHOW_AT=§aTNT-positions shown at {0}
TRACE_MESSAGE_SHOW_FROM=§aAll TNT-positions shown from {0}
TRACE_MESSAGE_SHOW_FROM_TO=§aAll TNT-positions shown from {0} to {1}
TRACE_MESSAGE_SHOW_TO_SMALLER=§cTo must be bigger then from
TRACE_MESSAGE_CLICK_ISOLATE=§eClick to §aisolate§8/§cunisolate
TRACE_MESSAGE_ISOLATE=§eTNT Positions have been isolated
TRACE_MESSAGE_SHARE=§e{0} shared his trace show state.
TRACE_MESSAGE_SHARE_HOVER=§eClick to view
TRACE_MESSAGE_FOLLOW=§aYou are now following {0} Trace show state
TRACE_MESSAGE_FOLLOW_SELF=§cYou cannot follow yourself!
TRACE_MESSAGE_UNFOLLOW=§cYou are no longer following a Trace show state
TRACE_COMMAND_HELP_START=§8/§etrace start §8- §7Starts recording of all TNT-positions
TRACE_COMMAND_HELP_SINGLE = §8/§etrace single §8- §7Starts a single recording of all TNT-positions
TRACE_COMMAND_HELP_STOP=§8/§etrace stop §8- §7Stops the TNT-Tracer
TRACE_COMMAND_HELP_AUTO=§8/§etrace toggleauto §8- §7Automatic start of recording
TRACE_COMMAND_HELP_AUTO_REMOVE = §8/§etrace autoremove §8<§eParameter§8> §8- §7Remove last Trace Record automatically
TRACE_COMMAND_HELP_SHOW=§8/§etrace show §8<§eParameter§8> - §7Shows all TNT-positions
TRACE_COMMAND_HELP_SHOW_AT = §8/§etrace show §8(§etime§8|§7fuse§8) §7at §8<§eTIME§8> - §7Shows all Trace Positions at §8<§eTIME§8>
TRACE_COMMAND_HELP_SHOW_FROM = §8/§etrace show §8(§etime§8|§7fuse§8) §7from §8<§eFROM§8> - §7Shows all Trace Positions from §8<§eFROM§8>
TRACE_COMMAND_HELP_SHOW_FROM_TO = §8/§etrace show §8(§etime§8|§7fuse§8) §7from §8<§eFROM§8> §7to §8<§eTO§8> - §7Shows all Trace Positions from §8<§eFROM§8> to §8<§eTO§8>
TRACE_COMMAND_HELP_SHOW_AT=§8/§etrace show §7at §8<§eTIME§8> - §7Shows all Trace Positions at §8<§eTIME§8>
TRACE_COMMAND_HELP_SHOW_AT_WITH=§8/§etrace show §7at §8<§eTIME§8> §7with §8<§eParameter§8> - §7Shows all Trace Positions at §8<§eTIME§8>
TRACE_COMMAND_HELP_SHOW_FROM=§8/§etrace show §7from §8<§eFROM§8> - §7Shows all Trace Positions from §8<§eFROM§8>
TRACE_COMMAND_HELP_SHOW_FROM_WITH=§8/§etrace show §7from §8<§eFROM§8> §7with §8<§eParameter§8> - §7Shows all Trace Positions from §8<§eFROM§8>
TRACE_COMMAND_HELP_SHOW_FROM_TO=§8/§etrace show §7from §8<§eFROM§8> §7to §8<§eTO§8> - §7Shows all Trace Positions from §8<§eFROM§8> to §8<§eTO§8>
TRACE_COMMAND_HELP_SHOW_FROM_TO_WITH=§8/§etrace show §7from §8<§eFROM§8> §7to §8<§eTO§8> §7with §8<§eParameter§8> - §7Shows all Trace Positions from §8<§eFROM§8> to §8<§eTO§8>
TRACE_COMMAND_HELP_HIDE=§8/§etrace hide §8- §7Hides all TNT-positions
TRACE_COMMAND_HELP_DELETE = §8/§etrace delete §8- §7Deletes all TNT-positions
TRACE_COMMAND_HELP_DELETE=§8/§etrace delete §8[§eTrace§8] §8- §7Deletes all TNT-positions or a Trace
TRACE_COMMAND_HELP_ISOLATE=§8/§etrace isolate §8[§eTrace§8] §8[§eTNT§8] §8- §7Isolates specific TNTs from the Trace
TRACE_COMMAND_HELP_SHARE=§8/§etrace share §8- §7Share your current Trace show state with others
TRACE_COMMAND_HELP_FOLLOW=§8/§etrace follow §8[§ePlayer§8] §8- §7Follow a players Trace show state
TRACE_COMMAND_HELP_UNFOLLOW=§8/§etrace unfollow §8- §7Unfollow the Trace show state
TRACE_GUI_ITEM_NAME=§eTracer
TRACE_GUI_ITEM_LORE=§7Status§8: {0}
TRACE_GUI_NAME=Trace Gui
@ -524,13 +467,12 @@ TRACE_GUI_TRACE_ACTIVE_AUTO = §eAuto-Trace is active
TRACE_GUI_AUTO_TRACE_INACTIVE=§eacitvate Auto-Tracer
TRACE_GUI_AUTO_TRACE_ACTIVE=§edeactivate Auto-Tracer
TRACE_GUI_DELETE=§eDelete trace
# Loader
LOADER_SETUP=§eSetup
LOADER_RUNNING=§aRunning
LOADER_PAUSE=§7Pause
LOADER_END=§8Finished
LOADER_SINGLE=§aSingle
LOADER_MESSAGE_INTERACT=§e{0} added {1}
LOADER_MESSAGE_UNINTERACT=§eRemoved Element
LOADER_BUTTON_TNT=TNT
@ -548,10 +490,10 @@ LOADER_BUTTON_LECTERN=Lectern
LOADER_BUTTON_TRAPDOOR=Trapdoor
LOADER_BUTTON_DOOR=Door
LOADER_BUTTON_FENCEGATE=Fencegate
LOADER_HELP_SETUP=§8/§eloader setup §8- §7Starts recording actions
LOADER_SETUP_STOP_FIRST=§cPlease stop the current loader first!
LOADER_HELP_START=§8/§eloader start §8- §7Playback of previously recorded action
LOADER_HELP_START=§8/§eloader start §8- §7Playback of previously recorded actions
LOADER_HELP_SINGLE=§8/§7loader single - §7Single playback of previously recoded actions
LOADER_HELP_PAUSE=§8/§7loader pause §8- §7Pauses Loader
LOADER_HELP_GUI=§8/§7loader gui §8- §7Shows Loader gui
LOADER_HELP_STOP=§8/§eloader stop §8- §7Stops recording/playback
@ -562,11 +504,11 @@ LOADER_NEW=§7Load your cannon and fire it once, to initialise the loader.
LOADER_HOW_TO_START=§7Then, execute /§eloader start§7 to start the Loader
LOADER_ACTIVE=§7The Loader is now active.
LOADER_STOP=§7The Loader has been stopped.
LOADER_SINGLE_CMD=§7The Loader does a single playback.
LOADER_PAUSED=§7The Loader is now paused.
LOADER_SMALL_TIME=§cThe wait time is too small
LOADER_NEW_TIME=§7The wait time is now: {0}
LOADER_NEW_LOAD_TIME=§7The action wait time is now: {0}
LOADER_NOTHING_RECORDED=§cYou have not recorded anything yet!
LOADER_GUI_TITLE=Loader GUI
LOADER_GUI_SHOW_ALL=Show all
@ -583,7 +525,6 @@ LOADER_GUI_SETTINGS_COPY=§7Copy
LOADER_GUI_SETTINGS_DELETE=§cDelete
LOADER_GUI_WAIT_TITLE=Settings
LOADER_GUI_WAIT_BACK=§8Back
LOADER_GUI_CLICK_TO_EDIT=§7Click to edit
LOADER_GUI_ITEM_NAME=§7{0}§8: §e{1}
LOADER_SETTING_NAME=§7{0}
@ -618,7 +559,6 @@ LOADER_INTERACTION_OPEN=Open
LOADER_INTERACTION_CLOSED=Closed
LOADER_INTERACTION_COMPARE=Compare
LOADER_INTERACTION_SUBTRACT=Subtract
# Loadtimer
LOADTIMER_HELP_OVERVIEW=§7Compete with your friends loading your cannon and get information about the cannon
LOADTIMER_HELP_START_1=§8/§eloadtimer start §8-§7 Starts the simple Loadtimer
@ -648,7 +588,6 @@ LOADTIMER_SUMARY_TIMES_LAST=§7\\/
LOADTIMER_SUMARY_STATS_HEAD=§7Cannon-Stats§8:
LOADTIMER_SUMARY_STATS_TNT=§7TNT: §e{0}
LOADTIMER_SUMARY_STATS_FREQ=§7Loading frequency: §e{0}/m§8, §7Shot frequency: §e{1}/m
# Observer
OBSERVER_HELP=§7Right-Click an Observer to get the Trace. Flame particles have to be enabled. The Particles will be shown in the block.
OBSERVER_HELP_ENABLE=§8/§eobserver enable §8-§7 Activates the Observer-Tracer
@ -660,7 +599,6 @@ OBSERVER_DISABLE = §7Observer trace stopped
OBSERVER_DELETE=§7Observer trace deleted
OBSERVER_RETRACE_DONE=§7Observer trace retraced
OBSERVER_RETRACE_NO_TRACE=§7No Observer trace to retrace
# Other
OTHER_ITEMS_TELEPORT_NAME=§eTeleporter
OTHER_ITEMS_TELEPORT_GUI_NAME=Teleport
@ -728,7 +666,6 @@ NIGHT_VISION_OFF=§eNightvision deactivated
NIGHT_VISION_ON=§eNightvision activated
NIGHT_VISION_ITEM_ON=§7Nightvision: §eActivated
NIGHT_VISION_ITEM_OFF=§7Nightvision: §eDeactivated
#Navigation Wand
NAVIGATION_WAND=§eNavigation Wand
NAVIGATION_WAND_LEFT_CLICK=§eLeft click: jump to location
@ -853,16 +790,13 @@ REGION_TNT_TB=§aTNT-Damage activated outside the building area
REGION_TNT_BUILD=§aTNT-Damage activated outside the testblok area
REGION_TNT_BUILD_DESTROY=§cAn explosion would have destroyed blocks in the building area
REGION_TNT_TB_DESTROY=§cAn explosion would have destroyed blocks in the testblock area
AFK_KICK_MESSAGE=§cNothing happened on this server for 15 minutes.
AFK_WARNING_MESSAGE=§cThis server will stop in one minute if you remain inactive
SKIN_HELP=§8/§eskin §8[§7Shortform§8] §8[§7Creator§8|§epublic§8] §8[§7Name...§8] §8- §7Creates the skin schematic. Use 'public' as creator to have no creator, then copy the message to YoyoNow by clicking
SKIN_NO_REGION=§7You are not in a region with a changealbe skin
SKIN_ALREADY_EXISTS=§cThis skin already exists like this
SKIN_MESSAGE=§7Skin created
SKIN_MESSAGE_HOVER=§eClick to copy for YoyoNow and send
# Panzern
PANZERN_HELP=§8/§epanzern §8[§7Block§8] §8[§7Slab§8] §8- §7Armor your WorldEdit selection
PANZERN_PREPARE1=§71. Check, if barrels reach until border of armor.
@ -872,7 +806,6 @@ PANZERN_PREPARE4 = §74. Standing in the region that is being armored can improv
PANZERN_NO_WORLDEDIT=§cYou have no WorldEdit selcetion
PANZERN_PROGRESS=§e{0} §7Blocks left, §e{1} §7Blocks per second, §e{2} §7block delta
PANZERN_DONE=§aDone
# Laufbau
LAUFBAU_HELP=§8/§elaufbau §8[§7smallest§8|§7blastresistant§8] §8- §7Build a barrel in your WorldEdit selection using the traces
LAUFBAU_HELP_SETTINGS=§8/§elaufbau settings §8- §7Opens the settings GUI
@ -884,16 +817,13 @@ LAUFBAU_STATE_PROCESSING_TRACES = Connnecting traces
LAUFBAU_STATE_CREATE_LAUF=Create Barrel
LAUFBAU_SIMPLE_PROGRESS=§e{0}§8: §e{1}§8/§e{2} §7Time left§8: §e{3}
LAUFBAU_DONE=§aDone
LAUFBAU_SETTINGS_GUI_NAME=§eLaufbau
LAUFBAU_SETTINGS_ACTIVE=§aActive
LAUFBAU_SETTINGS_INACTIVE=§cInactive
LAUFBAU_SETTINGS_MIXED=§e{0}§8/§e{1} §aActive
LAUFBAU_SETTINGS_GUI_BACK=§eBack
LAUFBAU_SETTINGS_TOGGLE=§eClick §8-§7 Toggle
LAUFBAU_SETTINGS_ADVANCED=§eMiddle-Click §8-§7 Advanced settings
LAUFBAU_BLOCK_COBWEB=§eCobweb
LAUFBAU_BLOCK_GRASS_PATH=§eGrass Path
LAUFBAU_BLOCK_SOUL_SAND=§eSoul Sand
@ -936,39 +866,31 @@ LAUFBAU_BLOCK_AZALEA = §eAzalea
LAUFBAU_BLOCK_CANDLE=§eCandle
LAUFBAU_BLOCK_CANDLE_CAKE=§eCake with Candle
LAUFBAU_BLOCK_LECTERN=§eLectern
LAUFBAU_FACING_NORTH=§8-§7 Facing North
LAUFBAU_FACING_SOUTH=§8-§7 Facing South
LAUFBAU_FACING_WEST=§8-§7 Facing West
LAUFBAU_FACING_EAST=§8-§7 Facing East
LAUFBAU_FACING_UP=§8-§7 Facing Up
LAUFBAU_FACING_DOWN=§8-§7 Facing Down
LAUFBAU_COUNT_1=§8-§7 Count 1
LAUFBAU_COUNT_2=§8-§7 Count 2
LAUFBAU_COUNT_3=§8-§7 Count 3
LAUFBAU_COUNT_4=§8-§7 Count 4
LAUFBAU_LAYERS_8=§8-§7 Layers 8
LAUFBAU_LAYERS_7=§8-§7 Layers 7
LAUFBAU_LAYERS_6=§8-§7 Layers 6
LAUFBAU_LAYERS_3=§8-§7 Layers 3
LAUFBAU_LAYERS_2=§8-§7 Layers 2
LAUFBAU_TYPE_BOTTOM=§8-§7 Type bottom
LAUFBAU_TYPE_TOP=§8-§7 Type top
LAUFBAU_HALF_BOTTOM=§8-§7 Half bottom
LAUFBAU_HALF_TOP=§8-§7 Half top
LAUFBAU_OPEN=§8-§7 Opened
LAUFBAU_ATTACHMENT_CEILING=§8-§7 Attachment Ceiling
LAUFBAU_ATTACHMENT_FLOOR=§8-§7 Attachment Floor
LAUFBAU_ATTACHMENT_DOUBLE_WALL=§8-§7 Attachment double Wall
LAUFBAU_ATTACHMENT_SINGLE_WALL=§8-§7 Attachment single Wall
LAUFBAU_ATTACHMENT_WALL=§8-§7 Attachment Wall
LAUFBAU_CONNECTION_FLOOR=§8-§7 Connection Floor
LAUFBAU_CONNECTION_NORTH=§8-§7 Connection North
LAUFBAU_CONNECTION_SOUTH=§8-§7 Connection South
@ -976,16 +898,12 @@ LAUFBAU_CONNECTION_EAST = §8-§7 Connection East
LAUFBAU_CONNECTION_WEST=§8-§7 Connection West
LAUFBAU_CONNECTION_DOWN=§8-§7 Connection Bottom
LAUFBAU_CONNECTION_UP=§8-§7 Connection Top
LAUFBAU_HANGING=§8-§7 hanging
LAUFBAU_SHAPE_STRAIGHT=§8-§7 Shape straight
LAUFBAU_SHAPE_OUTER_LEFT=§8-§7 Shape outer links
LAUFBAU_SHAPE_INNER_LEFT=§8-§7 Shape inner left
LAUFBAU_TILT_NONE=§8-§7 Tilt none
LAUFBAU_TILT_PARTIAL=§8-§7 Tilt partial
# UTILS
SELECT_HELP=§8/§eselect §8[§7RegionsTyp§8] §8- §7Select a region type
SELECT_EXTENSION_HELP=§8/§eselect §8[§7RegionsTyp§8] §8[§7Extension§8] §8- §7Select a region type with or without extension
@ -993,11 +911,9 @@ SELECT_GLOBAL_REGION = §cThe global region cannot be selected
SELECT_NO_TYPE=§cThis region has no {0}
SELECT_NO_EXTENSION=§cThis region has no extension
SELECT_MESSAGE=§7WorldEdit selection set to {0}, {1}, {2} and {3}, {4}, {5}
SKULL_HELP=§8/§eskull §8[§eplayer§8] §8-§7 Receive a player head
SKULL_INVALID=§cInvalid player name
SKULL_ITEM=§e{0}§8s Head
SPEED_HELP=§8/§espeed §8[§71§8-§710§8|§edefault§8] §8-§7 Set your flight and walking speed.
SPEED_CURRENT=§7Current speed§8: §e{0}
SPEED_TOO_SMALL=§c{0} is too small
@ -1005,11 +921,9 @@ SPEED_TOO_HIGH = §c{0} is too big
SPEED_ITEM=§eSpeed
SPEED_ITEM_LORE=§7Currently: §e
SPEED_TAB_NAME=Input speed
WORLDEDIT_WAND=WorldEdit Wand
WORLDEDIT_LEFTCLICK=Left click: select pos #1
WORLDEDIT_RIGHTCLICK=Right click: select pos #2
TNT_CLICK_HEADER=§8---=== §eTNT §8===---
TNT_CLICK_ORDER=§eEntity Order§8: §e{0}
TNT_CLICK_FUSE_TIME=§eFuseTime§8: §e{0}
@ -1021,7 +935,6 @@ TNT_CLICK_VELOCITY_Y = §7Velocity §eY§8: §e{0}
TNT_CLICK_VELOCITY_Z=§7Velocity §eZ§8: §e{0}
TNT_CLICK_COUNT=§7Count §8: §e{0}
TNT_CLICK_ISOLATE=§eIsolate
SELECT_ITEM_CHOOSE_EXTENSION=Choose extension
SELECT_ITEM_CHOOSE_SELECTION=Choose selection
SELECT_ITEM_NORMAL_EXTENSION=§eNormal
@ -1032,15 +945,12 @@ SELECT_ITEM_RIGHT_CLICK=§7Right-Click to change
SELECT_ITEM_BAURAHMEN=§eBuild area
SELECT_ITEM_BAUPLATTFORM=§eBuild platform
SELECT_ITEM_TESTBLOCK=§eDummy
CHESTFILLER_FILLED=§eChest filled
CHESTFILLER_COUNT=§7{0}§8: §e§l{1}
PISTON_HELP_1=§7Right click on piston with a slime ball to calculate the moved blocks.
PISTON_HELP_2=§7Count is red, if one unmoveable block is present.
PISTON_HELP_3=§7Count is yellow, if too many blocks are present.
PISTON_INFO=§7Moved Blocks {0}{1}§8/§712
# Warp
WARP_LOC_X=§7X§8: §e{0}
WARP_LOC_Y=§7Y§8: §e{0}
@ -1064,30 +974,22 @@ WARP_HELP_INFO=§8/§ewarp info §8[§7name§8] §8- §7Information regarding on
WARP_HELP_DELETE=§8/§ewarp delete §8[§7name§8] §8- §7Delete a warp
WARP_HELP_GUI=§8/§ewarp gui §8- §7Open the Warp-GUI
WARP_HELP_LIST=§8/§ewarp list §8- §7List all warps
# WORLD
STOP_HELP=§8/§estop §8- §7Stops the server
STOP_MESSAGE=§eServer is stopping
KICKALL_HELP=§8/§ekickall §8- §7Kick all players from the server except the owner
# Techhider
TECHHIDER_HELP=§8/§etechhider §8- §7Toggle Techhider
TECHHIDER_GLOBAL=§cNo techhider in global region
TECHHIDER_ON=§aTechhider activated
TECHHIDER_OFF=§cTechhider deactivated
# XRAY
XRAY_HELP=§8/§exray §8- §7Toggle Xray
XRAY_GLOBAL=§cNo xray in global region
XRAY_ON=§aXray activated
XRAY_OFF=§cXray deactivated
# WorldEdit
COLORREPLACE_HELP=§8//§ecolorreplace §8[§7color§8] §8[§7color§8] §8- §7Replace all blocks of one color with another
TYPEREPLACE_HELP=§8//§etyreplace §8[§7type§8] §8[§7type§8] §8- §7Replace all blocks of one type with another
# Schematic
SCHEMATIC_GUI_ITEM=§eSchematics

Datei anzeigen

@ -16,21 +16,17 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
PREFIX=§eBau§8System§8»
TIME=HH:mm:ss
DATE=........
COMMAND_HELP_HEAD=§7---=== (§e{0}§7) ===---
ONLY_SCHEMS=§cDu kannst hier keinen Ordner angeben
PAGE_LIST=§e Seite ({0}/{1}) »»
LIST_PREVIOUS_PAGE=§eVorherige Seite
LIST_NEXT_PAGE=§eNächste Seite
# Permission
NO_PERMISSION=Du darfst dies hier nicht nutzen
SPECTATOR=§fZuschauer
# Scoreboard
SCOREBOARD_TIME=Uhrzeit
SCOREBOARD_REGION=Region
@ -38,17 +34,13 @@ SCOREBOARD_TRACE = Trace
SCOREBOARD_LOADER=Loader
SCOREBOARD_TPS=TPS
SCOREBOARD_TPS_FROZEN=§eEingefroren
SCOREBOARD_TRACE_TICKS=Ticks
SCOREBOARD_TECHHIDER=TechHider§8: §aAn
SCOREBOARD_XRAY=XRay§8: §aAn
SCOREBOARD_LOCK_TEAM=Bau Lock§8: §eTeam
SCOREBOARD_LOCK_TEAM_AND_SERVERTEAM=Bau Lock§8: §e(Server-) Team
SCOREBOARD_LOCK_SERVERTEAM=Bau Lock§8: §eServerteam
SCOREBOARD_LOCK_NOBODY=Bau Lock§8: §cNiemand
# Flags
FLAG_COLOR=Color
FLAG_TNT=TNT
@ -56,24 +48,18 @@ FLAG_FIRE = Fire
FLAG_FREEZE=Freeze
FLAG_PROTECT=Protect
FLAG_ITEMS=Items
FLAG_FIRE_ALLOW=§can
FLAG_FIRE_DENY=§aaus
FLAG_FREEZE_ACTIVE=§aan
FLAG_FREEZE_INACTIVE=§caus
FLAG_PROTECT_ACTIVE=§aan
FLAG_PROTECT_INACTIVE=§caus
FLAG_TNT_ALLOW=§aan
FLAG_TNT_DENY=§caus
FLAG_TNT_ONLY_TB=§7Kein §eBaurahmen
FLAG_TNT_ONLY_BUILD=§7Kein §eTestblock
FLAG_ITEMS_ACTIVE=§aan
FLAG_ITEMS_INACTIVE=§caus
FLAG_COLOR_WHITE=§fWeiß
FLAG_COLOR_ORANGE=§6Orange
FLAG_COLOR_MAGENTA=§dMagenta
@ -92,21 +78,17 @@ FLAG_COLOR_BROWN = §eBraun
FLAG_COLOR_GREEN=§2Grün
FLAG_COLOR_RED=§cRot
FLAG_COLOR_BLACK=§0Schwarz
# Region
REGION_TYPE_NORMAL=Normal
REGION_TYPE_BUILD=Baubereich
REGION_TYPE_ONLY_TB=Testblock
# AttributesCopy
ATTRIBUTES_CANT_COPY=§cDu musst den Item Type in der Hand halten wo du auch drauf guckst.
ATTRIBUTES_NO_COPY=§cKeine Attribute kopiert.
ATTRIBUTES_COPIED=§eAttribute kopiert.
ATTRIBUTE_REMOVE_ALL=§eAlle Attribute entfernt.
ATTRIBUTE_REMOVE_SINGLE=§eAttribut §7{0}§e entfernt.
ATTRIBUTE_REMOVE_NOT_FOUND=§cAttribut nicht gefunden
# AutoStart
AUTOSTART_COMMAND_HELP=§8/§etimer §8- §7Legt den AutostartTimer ins Inventar
AUTOSTART_ITEM_NAME=§eAutostartTimer
@ -117,7 +99,6 @@ AUTOSTART_MESSAGE_START = §eAutostartTimer gestartet
AUTOSTART_MESSAGE_RESULT1=§eZeit §7bis zur §eExplosion §7am Gegner§8:§e {0}§7 in game ticks
AUTOSTART_MESSAGE_RESULT2=§7Zeitdifferenz in §egame ticks §7bis {0} Sekunden§8:§e {1}
AUTOSTART_MESSAGE_RESULT3=§7Positiv, wenn zu wenig, negativ wenn zu viel
# Backup
BACKUP_HELP_CREATE=§8/§ebackup create §8- §7Erstelle ein Backup der Region
BACKUP_HELP_LOAD=§8/§ebackup load §8[§7BackupName§8] §8- §7 Lade ein Backup
@ -134,10 +115,8 @@ BACKUP_LOAD=§7Backup geladen
BACKUP_INV_NAME=§eBackup
BACKUP_ITEM_NAME=§eBackup §7von §e{0}
BACKUP_LORE=§eKlicken zum Laden
# Bau
BAU_COMMAND_HELP_INFO=§8/§ebau info §8- §7Alias für §8/§ebauinfo
BAU_INFO_ITEM_NAME=§eBau-Management
## This is used in BauInfoBauGuiItem.java
BAU_INFO_ITEM_LORE_TNT=§7TNT§8: §e{0}
@ -146,13 +125,11 @@ BAU_INFO_ITEM_LORE_DAMAGE = §7Damage§8: §e{0}
BAU_INFO_ITEM_LORE_FIRE=§7Feuer§8: §e{0}
BAU_INFO_ITEM_LORE_COLOR=§7Farbe§8: §e{0}
BAU_INFO_ITEM_LORE_PROTECT=§7Protect§8: §e{0}
BAU_INFO_COMMAND_HELP=§8/§ebauinfo §8- §7Gibt Informationen über den Bau
BAU_INFO_COMMAND_OWNER=§7Besitzer§8: §e{0}
BAU_INFO_COMMAND_MEMBER=§7{0} §8[§7{1}§8]§8: §e{2}
BAU_INFO_COMMAND_FLAG=§7{0}§8: §7{1}
BAU_INFO_COMMAND_TPS=§7TPS§8:§e
# Countingwand
COUNTINGWAND_COMMAND_HELP=§8/§ecountingwand §8- §7Gibt dir ein CountingWand
COUNTINGWAND_ITEM_NAME=§eZollstock
@ -162,13 +139,11 @@ COUNTINGWAND_MESSAGE_RCLICK = §7Erste Position bei: §8[§7{0}§8, §7{1}§8,
COUNTINGWAND_MESSAGE_LCLICK=§7Zweite Position bei: §8[§7{0}§8, §7{1}§8, §7{2}§8] ({3}§8) ({4}§8)
COUNTINGWAND_MESSAGE_VOLUME=§e{0}
COUNTINGWAND_MESSAGE_DIMENSION=§e{0}§8, §e{1}§8, §e{2}
# Design Endstone
DESIGN_ENDSTONE_COMMAND_HELP=§8/§edesign endstone §8- §7Zeige End Stone im Design
DESIGN_ENDSTONE_REGION_ERROR=§cDiese Region hat keinen Baubereich
DESIGN_ENDSTONE_ENABLE=§aEndstone im Design ist angezeigt
DESIGN_ENDSTONE_DISABLE=§cEndstone im Design ist versteckt
# Detonator
DETONATOR_LOC_REMOVE=§e{0} entfernt
DETONATOR_LOC_ADD=§e{0} hinzugefügt
@ -218,14 +193,12 @@ GUI_EDITOR_ITEM_TRASH_LORE=§7Item hier rein Legen
GUI_EDITOR_ITEM_MORE=§eMehr Items
GUI_EDITOR_ITEM_CLOSE=§eSchließen
GUI_EDITOR_TITLE_MORE=Item auswählen
# Script
## CustomScript
SCRIPT_HOTKEY_ITEM_NAME=§7Hotkey§8: §e{0}
SCRIPT_EVENT_ITEM_NAME=§7Event§8: §e{0}
SCRIPT_COMMAND_ITEM_NAME=§7Befehl§8: §e/{0}
SCRIPT_ERROR_ONLY_IN_GLOBAL=§cDieses Skript kann nur als globales Skript ausgeführt werden
## Script Menu GUI
SCRIPT_MENU_GUI_ITEM_LORE_1=§7Klicke zum rausnehmen
SCRIPT_MENU_GUI_ITEM_LORE_2=§7Shiftklick zum kopieren
@ -235,7 +208,6 @@ SCRIPT_MENU_GUI_NAME = §eSkript-Menü
SCRIPT_MENU_GUI_ITEM_ADD_NAME=§eHinzufügen
SCRIPT_MENU_GUI_ITEM_ADD_LORE=§7Klicke mit einem Buch zum hinzufügen
SCRIPT_DEPRECATED=§cDie Funktion §e{0}§c ist veraltet und wird demnächst entfernt. Bitte benutze §e{1}§c.
# Shield Printing
SHIELD_PRINTING_HELP_START=§8/§eshieldprinting start §8- §7Starte das Schild drucken
SHIELD_PRINTING_HELP_COPY=§8/§eshieldprinting copy §8- §7Kopiert die Schilder
@ -248,12 +220,10 @@ SHIELD_PRINTING_HELP_STEP_4 = §84. §7Editiere die Schilde wenn nötig
SHIELD_PRINTING_HELP_STEP_5=§85. §7Kopiere das gedruckte mit §8/§eshieldprinting copy
SHIELD_PRINTING_HELP_STEP_6=§86. §7Füge die originale Schematic wieder ein
SHIELD_PRINTING_HELP_STEP_7=§87. §7Wende das gedruckte mit §8/§eshieldprinting apply§7 an
SHIELD_PRINTING_NO_REGION=§cDu bist in keiner Region.
SHIELD_PRINTING_NOT_RUNNING=§cShield printing ist nicht aktiv.
SHIELD_PRINTING_BOSSBAR=§fBewegungen: {0}
SHIELD_PRINTING_BOSSBAR_COPIED=§fBewegungen: {0} Kopiert: {1}
SHIELD_PRINTING_GUI_NAME=§7Schild Drucken
SHIELD_PRINTING_GUI_APPLY=§aAnwenden
SHIELD_PRINTING_GUI_STATE_PREVIOUS=§7R-Click§8: §7Vorherige
@ -271,15 +241,12 @@ SHIELD_PRINTING_GUI_STATE_OPENABLE = §7{0} §fGeöffnet
SHIELD_PRINTING_GUI_STATE_PISTON=§7{0} §fAusgefahren
SHIELD_PRINTING_GUI_STATE_POWERABLE=§7{0} §fAktiviert
SHIELD_PRINTING_GUI_STATE_WALL=§7{0} §fWand Verbindungen
SHIELD_PRINTING_START=§aShield printing wurde gestartet.
SHIELD_PRINTING_COPY=§aSchilde wurden kopiert.
SHIELD_PRINTING_APPLY=§aSchilde wurden angewendet.
SHIELD_PRINTING_STOP=§aShield printing wurde gestoppt.
# Unsign Book
UNSIGN_HELP=§8/§eunsign §8- §7Mache ein Buch beschreibbar
# Simulator
SIMULATOR_HELP=§8/§esimulator §8-§7 Legt dir den Simulatorstab ins Inventar
SIMULATOR_CREATE_HELP=§8/§esimulator create §8[§7name§8] §8-§7 Erstelle einen neuen Simulator
@ -287,9 +254,7 @@ SIMULATOR_CHANGE_HELP = §8/§esimulator change §8-§7 Wechsel zu einem anderen
SIMULATOR_DELETE_HELP=§8/§esimulator delete §8[§7name§8] §8-§7 Löscht den Simulator
SIMULATOR_START_HELP=§8/§esimulator start §8[§7name§8] §8-§7 Startet die Simulation
SIMULATOR_COPY_HELP=§8/§esimulator copy §8[§7to-copy§8] §8[§7name§8] §8-§7 Kopiert einen Simulator
SIMULATOR_GUI_ITEM_NAME=§eTNT Simulator
SIMULATOR_NO_SIM_IN_HAND=§cKein Simulator Item gewählt
SIMULATOR_GUI_SELECT_SIM=Simulator wählen
SIMULATOR_GUI_CREATE_SIM=§eSimulator erstellen
@ -303,9 +268,7 @@ SIMULATOR_EDIT_LOCATION = §7Editiere Positionen
SIMULATOR_EDIT_PROPERTIES=§7Editiere Eigenschaften
SIMULATOR_EDIT_OTHER=§7Editiere Andere
SIMULATOR_EDIT_GROUP=§7Editiere Gruppe
SIMULATOR_EDIT_GROUP_MENU=§eEditiere Gruppe
SIMULATOR_WAND_NAME=§eKanonensimulator
SIMULATOR_WAND_NAME_SELECTED=§7Kanonensimulator §8- §e{0}
SIMULATOR_WAND_LORE_1=§eRechtsklick §8- §7Füge eine Position hinzu
@ -313,9 +276,7 @@ SIMULATOR_WAND_LORE_2 = §eSneaken §8- §7Freie Bewegung
SIMULATOR_WAND_LORE_3=§eLinksklick §8- §7Starte die Simulation
SIMULATOR_WAND_LORE_4=§eRechtsklick Luft §8- §7Öffne die GUI
SIMULATOR_WAND_LORE_5=§eDoppel Shift §8- §7Wechsel zwischen TNT und Redstone Block
SIMULATOR_REGION_FROZEN=§cSimulator kann nicht in eingefrorenen Regionen genutzt werden
## Other
SIMULATOR_PLUS_ONE=§7+1
SIMULATOR_PLUS_PIXEL_SHIFT=§eShift §7Click für §e+0,0625
@ -327,11 +288,8 @@ SIMULATOR_POSITION_X = §7x-Position
SIMULATOR_POSITION_Y=§7y-Position
SIMULATOR_POSITION_Z=§7z-Position
SIMULATOR_BACK=§eZurück
SIMULATOR_GUI_TOTAL_TNT=§7Gesamt TNT§8: §e{0}
SIMULATOR_DELETED=§cSimulator gelöscht
## GUI
SIMULATOR_POSITION_EDIT=§ePosition bearbeiten
SIMULATOR_POSITION_ADD=§ePosition setzen
@ -345,15 +303,12 @@ SIMULATOR_GUI_NAME = Kanonensimulator
SIMULATOR_GUI_DELETE=§cTNT löschen
SIMULATOR_GUI_AUTO_TRACE=§eAutoTrace§8: §7{0}
SIMULATOR_GUI_MOVE_ALL=§eAlle Verschieben
SIMULATOR_ALIGNMENT_CENTER=§7Verschiebung§8: §eMitte
SIMULATOR_ALIGNMENT_POSITIVE_X=§7Verschiebung§8: §ePositive X
SIMULATOR_ALIGNMENT_NEGATIVE_X=§7Verschiebung§8: §eNegative X
SIMULATOR_ALIGNMENT_POSITIVE_Z=§7Verschiebung§8: §ePositive Z
SIMULATOR_ALIGNMENT_NEGATIVE_Z=§7Verschiebung§8: §eNegative Z
SIMULATOR_MOVE_ALL_GUI_NAME=TNT Verschieben
SIMULATOR_TNT_SPAWN_GUI_NAME=TNT konfigurieren {0}
SIMULATOR_TNT_SPAWN_LORE=§eZum Ändern klicken
SIMULATOR_TNT_SPAWN_COUNT=§7TNT-Anzahl §8- §e{0}
@ -385,19 +340,16 @@ SIMULATOR_TNT_SPAWN_ADD_IGNITION_PHASE = §eZündphase hinzufügen
SIMULATOR_TNT_SPAWN_ADD_TNT=§eTNT hinzufügen
SIMULATOR_TNT_SPAWN_REMOVE_TNT=§cEntfernen
SIMULATOR_TNT_SPAWN_POSITION_ANVIL_GUI_NAME=Position
# SmartPlace
SMART_PLACE_HELP=§8/§esmartplace §8-§7 Toggled SmartPlace
SMART_PLACE_INFO=§7Plaziert rotierbare Blöcke beim §esneaken§7 von dir §eweg§7.
SMART_PLACE_ENABLE=§aSmartPlace aktiviert
SMART_PLACE_DISABLE=§cSmartPlace deaktiviert
# InventoryFiller
INVENTORY_FILL_HELP=§8/§einventoryfill §8- §7Toggled InventoryFill
INVENTORY_FILL_INFO=§7Hilft dir, Behälter zu füllen, indem du sie beim sneaken ansiehst und den Gegenstand fallen lässt. Oder scrolle einfach auf einen Behälter, um die Menge des gehaltenen Gegenstandes darin zu ändern.
INVENTORY_FILL_ENABLE=§aInventoryFiller activated
INVENTORY_FILL_DISABLE=§cInventoryFiller deactivated
# Killchecker
KILLCHECKER_HELP_ENABLE=§8/§ekillchecker enable §8- §7Aktiviert Killchecker / Berechnet kills neu
KILLCHECKER_HELP_DISABLE=§8/§ekillchecker disable §8- §7Deaktiviert Killchecker
@ -406,7 +358,6 @@ KILLCHECKER_INFO2 = §7Nur farbige Blöcke wie Wolle, Terracotta, Stained Glass
KILLCHECKER_ENABLE=§aKillchecker aktiviert
KILLCHECKER_DISABLE=§cKillchecker deaktiviert
KILLCHECKER_BOSSBAR=§e§l{0} §7(§e{1}%§7) §e§l{2}§7 Kanonnen
# BlockCounter
BLOCK_COUNTER_HELP_TOGGLE=§8/§eblockcounter §8- §7Wechsel zwischen an und aus
BLOCK_COUNTER_HELP_ENABLE=§8/§eblockcounter enable §8- §7Schalte den BlockCounter an
@ -415,17 +366,14 @@ BLOCK_COUNTER_MESSAGE = §7Schaden §8> §e{0} §7Blöcke §e{1} §7TNT §e{2}
BLOCK_COUNTER_MESSAGE_SECOND=§7Schaden §8> §e{0} §7Blöcke §e{1} §7TNT §e{2} §7Blöcke/TNT §e{3} §7Blöcke/s
BLOCK_COUNTER_ENABLE=§7BlockCounter angemacht
BLOCK_COUNTER_DISABLE=§7BlockCounter ausgemacht
# DepthCounter
DEPTH_COUNTER_MESSAGE=§7Tiefe §8> §7
# TPSLimit
TPSLIMIT_FREEZE_HELP=§8/§etpslimit 0 §8-§7 Friere TPS ein
TPSLIMIT_LIMIT_HELP=§8/§etpslimit §8[§720>x>0.5§8] §8-§7 Verlangsame die TPS
TPSLIMIT_WARP_HELP=§8/§etpslimit §8[§7x>20§8] §8-§7 Beschleunige die TPS
TPSLIMIT_DEFAULT_HELP=§8/§etpslimit default §8-§7 Setze die TPS auf 20
TPSLIMIT_HELP=§8/§etpslimit §8-§7 Zeige die jetzige TPS
TICK_FREEZE_HELP=§8/§etick rate 0 §8-§7 Friere TPS ein
TICK_FREEZE_HELP_2=§8/§etick freeze §8-§7 Friere TPS ein
TICK_UNFREEZE_HELP=§8/§etick unfreeze §8-§7 Setze die TPS auf 20
@ -433,10 +381,8 @@ TICK_LIMIT_HELP = §8/§etick rate §8[§720>x>0.5§8] §8-§7 Verlangsame die T
TICK_WARP_HELP=§8/§etick rate §8[§7x>20§8] §8-§7 Beschleunige die TPS
TICK_DEFAULT_HELP=§8/§etick rate default §8-§7 Setze die TPS auf 20
TICK_HELP=§8/§etick rate §8-§7 Zeige die jetzige TPS
TICK_STEPPING_HELP=§8/§etick step §8<§7Ticks§8> §8-§7 Spule n ticks oder 1 vor
TICK_WARPING_HELP=§8/§etick warp §8<§7Ticks§8> §8<§7TPS§8> §8-§7 Warpe n ticks oder 1 vor
TICK_BOSSBAR=§e{0}§8/§7{1} gesprungen
TPSLIMIT_GUI_ITEM_NAME=§eTPS Limiter
TPSLIMIT_GUI_ITEM_LORE=§7Aktuell: §e{0}
@ -444,46 +390,38 @@ TPSLIMIT_ANVIL_GUI = Neues TPS Limit
TPSLIMIT_CURRENT=§7Jetziges TPS limit§8: §e{0}
TPSLIMIT_SET=§eTPS limit auf {0} gesetzt.
TPSLIMIT_FROZEN=§eTPS eingefroren.
# Trace
TRACE_RECORD=§aan
TRACE_HAS_TRACES=§ehat Traces
TRACE_IDLE_SINGLE=§esingle
TRACE_IDLE_AUTO_EXPLODE=§eauto §8(§7explode§8)
TRACE_IDLE_AUTO_IGNITE=§eauto §8(§7ignite§8)
TRACE_MESSAGE_AUTO_IDLE_EXPLODE = §aAuto-Tracer explode gestartet
TRACE_MESSAGE_AUTO_IDLE_IGNITE = §aAuto-Tracer ignite gestartet
TRACE_MESSAGE_AUTO_DELETE_INVALID = §cAuto delete kann aktuell nicht genutzt werden
TRACE_MESSAGE_AUTO_DELETE_ALWAYS = §7Der letzte Schuss wird §eimmer§7 gelöscht
TRACE_MESSAGE_AUTO_DELETE_NEVER = §7Der letzte Schuss wird §enie§7 gelöscht
TRACE_MESSAGE_AUTO_DELETE_NO_BUILD_DESTROY = §7Der letzte Schuss wird gelöscht, wenn §ekein§7 Block aus dem §eBaubereich§7 zerstört wurde
TRACE_MESSAGE_AUTO_DELETE_BUILD_DESTROY = §7Der letzte Schuss wird gelöscht, wenn §eein§7 Block aus dem §eBaubereich§7 zerstört wurde
TRACE_MESSAGE_AUTO_DELETE_NO_TESTBLOCK_DESTROY = §7Der letzte Schuss wird gelöscht, wenn §ekein§7 Block aus dem §eTestblock§7 zerstört wurde
TRACE_MESSAGE_AUTO_DELETE_TESTBLOCK_DESTROY = §7Der letzte Schuss wird gelöscht, wenn §eein§7 Block aus dem §eTestblock§7 zerstört wurde
TRACE_MESSAGE_START=§aTNT-Tracer gestartet
TRACE_MESSAGE_SINGLE = §aSingle-Tracer gestartet
TRACE_MESSAGE_AUTO_START=§eAuto TNT-Tracer gestartet
TRACE_MESSAGE_AUTO_STOP=§cAuto TNT-Tracer gestoppt
TRACE_MESSAGE_STOP=§cTNT-Tracer gestoppt
TRACE_MESSAGE_DELETE = §cAlle TNT-Positionen gelöscht
TRACE_MESSAGE_SHOW = §aAlle TNT-Positionen angezeigt
TRACE_MESSAGE_HIDE = §cAlle TNT-Positionen ausgeblendet
TRACE_MESSAGE_CLEAR=§cAlle TNT-Positionen gelöscht
TRACE_MESSAGE_CLICK_ISOLATE=§eKlicken zum §aisolieren§8/§causblenden
TRACE_MESSAGE_SHOW_AT = §aTNT-positions angezeigt mit {0} bei {1}
TRACE_MESSAGE_SHOW_FROM = §aAll TNT-positions angezeigt mit {0} von {1}
TRACE_MESSAGE_SHOW_FROM_TO = §aAll TNT-positions angezeigt mit {0} von {1} bis {2}
TRACE_MESSAGE_SHOW_AT=§aTNT-positions angezeigt bei {0}
TRACE_MESSAGE_SHOW_FROM=§aAll TNT-positions angezeigt von {0}
TRACE_MESSAGE_SHOW_FROM_TO=§aAll TNT-positions angezeigt von {0} bis {1}
TRACE_MESSAGE_SHARE=§e{0} teilte seinen Trace-Show-Status.
TRACE_MESSAGE_SHARE_HOVER=§eZum Ansehen klicken.
TRACE_MESSAGE_FOLLOW=§aSie folgen nun {0} Trace show state
TRACE_MESSAGE_FOLLOW_SELF=§cSie können sich selbst nicht folgen!
TRACE_MESSAGE_UNFOLLOW=§cSie folgen nicht mehr dem Status einer Trace-Show
TRACE_MESSAGE_SHOW_TO_SMALLER=§cBis muss größer als von sein
TRACE_MESSAGE_ISOLATE=§eTNT Positionen wurden isoliert
TRACE_COMMAND_HELP_SHARE=§8/§etrace share §8- §7Teilt den aktuellen Trace-Show-Status mit anderen
TRACE_COMMAND_HELP_FOLLOW=§8/§etrace follow §8[§ePlayer§8] §8- §7Verfolgen eines Spielers Status anzeigen
TRACE_COMMAND_HELP_UNFOLLOW=§8/§etrace unfollow §8- §7Den Status der Trace-Anzeige aufheben
TRACE_COMMAND_HELP_START=§8/§etrace start §8- §7Startet die Aufnahme aller TNT-Positionen
TRACE_COMMAND_HELP_SINGLE = §8/§etrace single §8- §7Startet eine einzelne Aufnahme aller TNT-Positionen
TRACE_COMMAND_HELP_STOP=§8/§etrace stop §8- §7Stoppt den TNT-Tracer
TRACE_COMMAND_HELP_AUTO=§8/§etrace toggleauto §8- §7Automatischer Aufnahmenstart
TRACE_COMMAND_HELP_AUTO_REMOVE = §8/§etrace autoremove §8<§eParameter§8> §8- §7Löscht den letzten Trace automatisch
TRACE_COMMAND_HELP_SHOW=§8/§etrace show §8<§eParameter§8> - §7Zeigt alle TNT-Positionen
TRACE_COMMAND_HELP_SHOW_AT=§8/§etrace show §8(§etime§8|§7fuse§8) §7at §8<§eTIME§8> - §7Zeigt alle TNT-Positionen bei §8<§eTIME§8> an
TRACE_COMMAND_HELP_SHOW_FROM=§8/§etrace show §8(§etime§8|§7fuse§8) §7from §8<§eFROM§8> - §7Zeigt alle TNT-Positionen von §8<§eFROM§8>
TRACE_COMMAND_HELP_SHOW_FROM_TO=§8/§etrace show §8(§etime§8|§7fuse§8) §7from §8<§eFROM§8> §7to §8<§eTO§8> - §7Zeigt alle TNT-Positionen zwischen §8<§eFROM§8> und §8<§eTO§8>
TRACE_COMMAND_HELP_HIDE=§8/§etrace hide §8- §7Versteckt alle TNT-Positionen
TRACE_COMMAND_HELP_DELETE=§8/§etrace delete §8- §7Löscht alle TNT-Positionen
TRACE_COMMAND_HELP_ISOLATE=§8/§etrace isolate §8[§eTrace§8] §8[§eTNT§8] §8- §7Isoliert spezifische TNTs des Traces
TRACE_GUI_ITEM_NAME=§eTracer
TRACE_GUI_ITEM_LORE=§7Status§8: {0}
TRACE_GUI_NAME=Tracer Gui
@ -493,13 +431,12 @@ TRACE_GUI_TRACE_ACTIVE_AUTO = §eAuto-Trace ist Aktiv
TRACE_GUI_AUTO_TRACE_INACTIVE=§eAuto-Tracer Aktivieren
TRACE_GUI_AUTO_TRACE_ACTIVE=§eAuto-Tracer Deaktivieren
TRACE_GUI_DELETE=§eTrace Löschen
# Loader
LOADER_SETUP=§eEinrichtung
LOADER_RUNNING=§aLaufend
LOADER_PAUSE=§7Pausiert
LOADER_END=§8Beendet
LOADER_SINGLE=§aEinmal
LOADER_MESSAGE_INTERACT=§e{0} hinzugefügt {1}
LOADER_BUTTON_TNT=TNT
LOADER_BUTTON_SWITCH=Hebel
@ -516,10 +453,10 @@ LOADER_BUTTON_LECTERN=Lectern
LOADER_BUTTON_TRAPDOOR=Trapdoor
LOADER_BUTTON_DOOR=Door
LOADER_BUTTON_FENCEGATE=Fencegate
LOADER_HELP_SETUP=§8/§eloader setup §8- §7Startet die Aufnahme der Aktionen
LOADER_SETUP_STOP_FIRST=§cBitte stoppe zuerst den Loader
LOADER_HELP_START=§8/§eloader start §8- §7Spielt die zuvor aufgenommenen Aktionen ab
LOADER_HELP_SINGLE=§8/§eloader single §8- §7Spielt die zuvor aufgenommenen Aktionen einmal ab
LOADER_HELP_PAUSE=§8/§7loader pause §8- §7Pausiert das Abspielen
LOADER_HELP_GUI=§8/§7loader settings §8- §7Zeigt die Einstellungen an
LOADER_HELP_STOP=§8/§eloader stop §8- §7Stoppt die Aufnahme bzw. das Abspielen
@ -530,11 +467,11 @@ LOADER_NEW=§7Belade und feuer einmal die Kanone ab, um den Loader zu initialisi
LOADER_HOW_TO_START=§7Führe dann /§eloader start§7 um den Loader zu starten
LOADER_ACTIVE=§7Der Loader ist nun aktiviert.
LOADER_STOP=§7Der Loader ist nun gestoppt.
LOADER_SINGLE_CMD=§7Der Loader spielt nun einmal ab.
LOADER_PAUSED=§7Der Loader ist nun pausiert.
LOADER_SMALL_TIME=§cDie Wartezeit ist zu klein
LOADER_NEW_TIME=§7Die Schusswartezeit ist nun: {0}
LOADER_NEW_LOAD_TIME=§7Die Setzwartezeit ist nun: {0}
LOADER_NOTHING_RECORDED=§cEs wurden keine Elemente aufgenommen!
LOADER_GUI_TITLE=Loader Einstellungen
LOADER_GUI_SHOW_ALL=Zeige alles
@ -551,7 +488,6 @@ LOADER_GUI_SETTINGS_COPY=§7Kopieren
LOADER_GUI_SETTINGS_DELETE=§cLöschen
LOADER_GUI_WAIT_TITLE=Wartezeit
LOADER_GUI_WAIT_BACK=§8Zurück
LOADER_GUI_CLICK_TO_EDIT=§7Klicke zum editieren
LOADER_GUI_ITEM_NAME=§7{0}§8: §e{1}
LOADER_SETTING_NAME=§7{0}
@ -586,7 +522,6 @@ LOADER_INTERACTION_OPEN=Geöffnet
LOADER_INTERACTION_CLOSED=Geschlossen
LOADER_INTERACTION_COMPARE=Vergleichen
LOADER_INTERACTION_SUBTRACT=Subtrahieren
# Loadtimer
LOADTIMER_HELP_OVERVIEW=§7Messe dich und deine Freunde beim Beladen einer Kanone und bekomme informationen über die Kanone
LOADTIMER_HELP_START_1=§8/§eloadtimer start §8-§7 Startet den einfachen Loadtimer
@ -616,7 +551,6 @@ LOADTIMER_SUMARY_TIMES_LAST=§7\\/
LOADTIMER_SUMARY_STATS_HEAD=§7Kanonen-Stats§8:
LOADTIMER_SUMARY_STATS_TNT=§7TNT: §e{0}
LOADTIMER_SUMARY_STATS_FREQ=§7Belade Frequenz: §e{0}/m§8, §7Schuss Frequenz: §e{1}/m
# Observer
OBSERVER_HELP=§7Rechts-Klicke einen Observer um den Trace zu bekommen. Hierfür müssen Flammenpartikel an sein. Die Partikel werden im Block angezeigt.
OBSERVER_HELP_ENABLE=§8/§eobserver enable §8-§7 Aktiviere den Observer Tracer
@ -628,7 +562,6 @@ OBSERVER_DISABLE = §7Observer Trace gestoppt
OBSERVER_DELETE=§7Observer Trace gelöscht
OBSERVER_RETRACE_DONE=§7Observer Trace neu berechnet
OBSERVER_RETRACE_NO_TRACE=§7Kein Observer Trace zum neu berechnen
# Other
OTHER_ITEMS_TELEPORT_NAME=§eTeleporter
OTHER_ITEMS_TELEPORT_GUI_NAME=Teleportieren
@ -693,7 +626,6 @@ NIGHT_VISION_OFF=§eNightvision deaktiviert
NIGHT_VISION_ON=§eNightvision aktiviert
NIGHT_VISION_ITEM_ON=§7Nightvision: §eAktiviert
NIGHT_VISION_ITEM_OFF=§7Nightvision: §eDeaktiviert
#Navigation Wand
NAVIGATION_WAND=§eNavigation Wand
NAVIGATION_WAND_LEFT_CLICK=§eLeft click: jump to location
@ -817,13 +749,11 @@ REGION_TNT_BUILD_DESTROY=§cEine Explosion hätte Blöcke im Baubereich zerstör
REGION_TNT_TB_DESTROY=§cEine Explosion hätte Blöcke im Testblockbereich zerstört
AFK_KICK_MESSAGE=§cAuf diesem Server ist seit 15 Minuten nichts passiert.
AFK_WARNING_MESSAGE=§cDieser Server wird bei weiterer Inaktivität in einer Minute gestoppt
SKIN_HELP=§8/§eskin §8[§7Kuerzel§8] §8[§7Creator§8|§epublic§8] §8[§7Name...§8] §8- §7Erstellt die Skin Schematics. 'public' als Creator nutzen für keinen Creator, danach die nachricht an YoyoNow kopieren (mit Click kopieren)
SKIN_NO_REGION=§7Du steht in keiner Region, welche mit einem Skin versehen werden kann
SKIN_ALREADY_EXISTS=§cDieser Skin existiert in der Form bereits
SKIN_MESSAGE=§7Skin erstellt
SKIN_MESSAGE_HOVER=§eKlicken zum kopieren für YoyoNow und an diesen senden
# Panzern
PANZERN_HELP=§8/§epanzern §8[§7Block§8] §8[§7Slab§8] §8- §7Panzer deine WorldEdit Auswahl
PANZERN_PREPARE1=§71. Gucke nochmal nach, ob Läufe auch bis zur Panzergrenze führen.
@ -833,7 +763,6 @@ PANZERN_PREPARE4 = §74. Innerhalb der zu panzernden Region zu stehen, beim Befe
PANZERN_NO_WORLDEDIT=§cDu hast keine WorldEdit Selection
PANZERN_PROGRESS=§e{0} §7Blöcke übrig, §e{1} §7Blöcke pro Sekunde, §e{2} §7Block Delta
PANZERN_DONE=§aZuende gepanzert
# Laufbau
LAUFBAU_HELP=§8/§elaufbau §8[§7smallest§8|§7blastresistant§8] §8- §7Baue einen Lauf in deiner WorldEdit Auswahl mit den Traces
LAUFBAU_HELP_SETTINGS=§8/§elaufbau settings §8- §7Öffnet die Settings GUI
@ -845,16 +774,13 @@ LAUFBAU_STATE_PROCESSING_TRACES = Traces verbinden
LAUFBAU_STATE_CREATE_LAUF=Lauf erstellen
LAUFBAU_SIMPLE_PROGRESS=§e{0}§8: §e{1}§8/§e{2} §7Übrige Zeit §8: §e{3}
LAUFBAU_DONE=§aZuende gebaut
LAUFBAU_SETTINGS_GUI_NAME=§eLaufbau
LAUFBAU_SETTINGS_ACTIVE=§aAktiv
LAUFBAU_SETTINGS_INACTIVE=§cInaktiv
LAUFBAU_SETTINGS_MIXED=§e{0}§8/§e{1} §aAktiv
LAUFBAU_SETTINGS_GUI_BACK=§eBack
LAUFBAU_SETTINGS_TOGGLE=§eClick §8-§7 Toggle
LAUFBAU_SETTINGS_ADVANCED=§eMiddle-Click §8-§7 Erweiterte Einstellung
LAUFBAU_BLOCK_COBWEB=§eCobweb
LAUFBAU_BLOCK_GRASS_PATH=§eGrass Path
LAUFBAU_BLOCK_SOUL_SAND=§eSoul Sand
@ -893,39 +819,31 @@ LAUFBAU_BLOCK_AZALEA = §eAzalea
LAUFBAU_BLOCK_CANDLE=§eKerze
LAUFBAU_BLOCK_CANDLE_CAKE=§eKuchen mit Kerze
LAUFBAU_BLOCK_LECTERN=§eLectern
LAUFBAU_FACING_NORTH=§8-§7 Richtung Norden
LAUFBAU_FACING_SOUTH=§8-§7 Richtung Süden
LAUFBAU_FACING_WEST=§8-§7 Richtung Westen
LAUFBAU_FACING_EAST=§8-§7 Richtung Osten
LAUFBAU_FACING_UP=§8-§7 Richtung Oben
LAUFBAU_FACING_DOWN=§8-§7 Richtung Unten
LAUFBAU_COUNT_1=§8-§7 Anzahl 1
LAUFBAU_COUNT_2=§8-§7 Anzahl 2
LAUFBAU_COUNT_3=§8-§7 Anzahl 3
LAUFBAU_COUNT_4=§8-§7 Anzahl 4
LAUFBAU_LAYERS_8=§8-§7 Ebenen 8
LAUFBAU_LAYERS_7=§8-§7 Ebenen 7
LAUFBAU_LAYERS_6=§8-§7 Ebenen 6
LAUFBAU_LAYERS_3=§8-§7 Ebenen 3
LAUFBAU_LAYERS_2=§8-§7 Ebenen 2
LAUFBAU_TYPE_BOTTOM=§8-§7 Type Unten
LAUFBAU_TYPE_TOP=§8-§7 Type Oben
LAUFBAU_HALF_BOTTOM=§8-§7 Hälfte Unten
LAUFBAU_HALF_TOP=§8-§7 Hälfte Oben
LAUFBAU_OPEN=§8-§7 Geöffnet
LAUFBAU_ATTACHMENT_CEILING=§8-§7 Befestigung Decke
LAUFBAU_ATTACHMENT_FLOOR=§8-§7 Befestigung Boden
LAUFBAU_ATTACHMENT_DOUBLE_WALL=§8-§7 Befestigung beidseitige Wand
LAUFBAU_ATTACHMENT_SINGLE_WALL=§8-§7 Befestigung einseitige Wand
LAUFBAU_ATTACHMENT_WALL=§8-§7 Befestigung Wand
LAUFBAU_CONNECTION_FLOOR=§8-§7 Verbindung Boden
LAUFBAU_CONNECTION_NORTH=§8-§7 Verbindung Norden
LAUFBAU_CONNECTION_SOUTH=§8-§7 Verbindung Süden
@ -933,16 +851,12 @@ LAUFBAU_CONNECTION_EAST = §8-§7 Verbindung Osten
LAUFBAU_CONNECTION_WEST=§8-§7 Verbindung Westen
LAUFBAU_CONNECTION_DOWN=§8-§7 Verbindung Unten
LAUFBAU_CONNECTION_UP=§8-§7 Verbindung Oben
LAUFBAU_HANGING=§8-§7 hängend
LAUFBAU_SHAPE_STRAIGHT=§8-§7 Form gerade
LAUFBAU_SHAPE_OUTER_LEFT=§8-§7 Form äußere links
LAUFBAU_SHAPE_INNER_LEFT=§8-§7 Form innere links
LAUFBAU_TILT_NONE=§8-§7 Neigung keine
LAUFBAU_TILT_PARTIAL=§8-§7 Neigung teilweise
# UTILS
SELECT_HELP=§8/§eselect §8[§7RegionsTyp§8] §8- §7Wähle einen RegionsTyp aus
SELECT_EXTENSION_HELP=§8/§eselect §8[§7RegionsTyp§8] §8[§7Extension§8] §8- §7Wähle einen RegionsTyp aus mit oder ohne Extension
@ -950,11 +864,9 @@ SELECT_GLOBAL_REGION = §cDie globale Region kannst du nicht auswählen
SELECT_NO_TYPE=§cDiese Region hat keinen {0}
SELECT_NO_EXTENSION=§cDiese Region hat keine Ausfahrmaße
SELECT_MESSAGE=§7WorldEdit auswahl auf {0}, {1}, {2} und {3}, {4}, {5} gesetzt
SKULL_HELP=§8/§eskull §8[§eSpieler§8] §8-§7 Gibt einen SpielerKopf
SKULL_INVALID=§cUngültiger Spieler
SKULL_ITEM=§e{0}§8s Kopf
SPEED_HELP=§8/§espeed §8[§71§8-§710§8|§edefault§8] §8-§7 Setzte deine Flug- und Laufgeschindigkeit.
SPEED_CURRENT=§7Aktuelle geschwindigkeit§8: §e{0}
SPEED_TOO_SMALL=§c{0} ist zu klein
@ -962,11 +874,9 @@ SPEED_TOO_HIGH = §c{0} ist zu hoch
SPEED_ITEM=§eGeschwindigkeit
SPEED_ITEM_LORE=§7Aktuell: §e
SPEED_TAB_NAME=Geschwindigkeit eingeben
WORLDEDIT_WAND=WorldEdit Wand
WORLDEDIT_LEFTCLICK=Left click: select pos #1
WORLDEDIT_RIGHTCLICK=Right click: select pos #2
TNT_CLICK_HEADER=§8---=== §eTNT §8===---
TNT_CLICK_ORDER=§eEntity Order§8: §e{0}
TNT_CLICK_FUSE_TIME=§eFuseTime§8: §e{0}
@ -988,14 +898,11 @@ SELECT_ITEM_RIGHT_CLICK=§7Rechtklick zum ändern
SELECT_ITEM_BAURAHMEN=§eBaurahmen
SELECT_ITEM_BAUPLATTFORM=§eBauplattform
SELECT_ITEM_TESTBLOCK=§eTestblock
CHESTFILLER_FILLED=§eKiste gefüllt
PISTON_HELP_1=§7Rechts Klick auf Piston mit einem Slime Ball berechnet dir die bewegten Blöcke.
PISTON_HELP_2=§7Die Anzahl ist Rot, wenn ein unmovable Block vorhanden ist.
PISTON_HELP_3=§7Die Anzahl ist Gelb, wenn zu viele Blöcke vorhanden sind.
PISTON_INFO=§7Bewegte Blöcke {0}{1}§8/§712
# Warp
WARP_LOC_X=§7X§8: §e{0}
WARP_LOC_Y=§7Y§8: §e{0}
@ -1019,30 +926,22 @@ WARP_HELP_INFO=§8/§ewarp info §8[§7Name§8] §8- §7Infos zu einem Punkt
WARP_HELP_DELETE=§8/§ewarp delete §8[§7Name§8] §8- §7Lösche einen Warp
WARP_HELP_GUI=§8/§ewarp gui §8- §7Öffne die Warp-GUI
WARP_HELP_LIST=§8/§ewarp list §8- §7Liste alle Warp-Punkt auf
# WORLD
STOP_HELP=§8/§estop §8- §7Stoppt den Server
STOP_MESSAGE=§eDer Server wird gestoppt
KICKALL_HELP=§8/§ekickall §8- §7Kickt alle Spieler vom Server außer den Owner
# Techhider
TECHHIDER_HELP=§8/§etechhider §8- §7Techhider umschalten
TECHHIDER_GLOBAL=§cKein Techhider in der globalen region
TECHHIDER_ON=§aTechhider aktiviert
TECHHIDER_OFF=§cTechHider deaktiviert
# XRAY
XRAY_HELP=§8/§exray §8- §7Xray umschalten
XRAY_GLOBAL=§cKein Xray in der globalen region
XRAY_ON=§aXray aktiviert
XRAY_OFF=§cXray deaktiviert
# WorldEdit
COLORREPLACE_HELP=§8//§ecolorreplace §8[§7color§8] §8[§7color§8] §8- §7Ersetzt eine Farbe mit einer anderen
TYPEREPLACE_HELP=§8//§etyreplace §8[§7type§8] §8[§7type§8] §8- §7Ersetzt einen Blockgruppe mit einer anderen
# Schematics
SCHEMATIC_GUI_ITEM=§eSchematics

Datei anzeigen

@ -39,7 +39,10 @@ import org.bukkit.event.Listener;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.player.PlayerQuitEvent;
import java.util.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
public class Loader implements Listener {
@ -78,6 +81,10 @@ public class Loader implements Listener {
}
if (currentElement >= elements.size()) {
currentElement = 0;
if (stage == Stage.SINGLE) {
stage = Stage.PAUSE;
return;
}
}
while (currentElement < elements.size()) {
@ -92,6 +99,20 @@ public class Loader implements Listener {
}, 0, 1);
}
public void single() {
if (stage == Stage.END) return;
if (stage == Stage.RUNNING) return;
stage = Stage.SINGLE;
if (recorder != null) {
recorder.stop();
recorder = null;
}
if (elements.isEmpty()) {
BauSystem.MESSAGE.send("LOADER_NOTHING_RECORDED", p);
stop();
}
}
public void start() {
if (stage == Stage.END) return;
if (stage == Stage.RUNNING) return;
@ -349,6 +370,7 @@ public class Loader implements Listener {
public enum Stage implements EnumDisplay {
SETUP("LOADER_SETUP"),
RUNNING("LOADER_RUNNING"),
SINGLE("LOADER_SINGLE"),
PAUSE("LOADER_PAUSE"),
END("LOADER_END");

Datei anzeigen

@ -20,10 +20,8 @@
package de.steamwar.bausystem.features.loader;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.Permission;
import de.steamwar.bausystem.utils.BauMemberUpdateEvent;
import de.steamwar.command.SWCommand;
import de.steamwar.command.TypeValidator;
import de.steamwar.linkage.Linked;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@ -105,6 +103,14 @@ public class LoaderCommand extends SWCommand implements Listener {
loader.setTicksBetweenBlocks(delay);
}
@Register(value = "single", description = "LOADER_HELP_SINGLE")
public void singleLoader(@Validator Player p) {
Loader loader = Loader.getLoader(p);
if (loaderNullCheck(loader, p)) return;
loader.single();
BauSystem.MESSAGE.send("LOADER_SINGLE_CMD", p);
}
@EventHandler
public void onBauMemberUpdate(BauMemberUpdateEvent event) {
event.getNewSpectator().forEach(player -> {

Datei anzeigen

@ -20,9 +20,6 @@
package de.steamwar.bausystem.features.script.lua.libs;
import de.steamwar.bausystem.features.loader.Loader;
import de.steamwar.bausystem.features.tracer.record.ActiveTracer;
import de.steamwar.bausystem.features.tracer.record.AutoTraceRecorder;
import de.steamwar.bausystem.features.tracer.record.Recorder;
import de.steamwar.bausystem.region.GlobalRegion;
import de.steamwar.bausystem.region.Region;
import de.steamwar.bausystem.region.flags.Flag;
@ -71,13 +68,13 @@ public class RegionLib implements LuaLib {
table.set("freeze", getter(() -> region.get().getPlain(Flag.FREEZE, FreezeMode.class) == FreezeMode.ACTIVE));
table.set("protect", getter(() -> region.get().getPlain(Flag.PROTECT, ProtectMode.class) == ProtectMode.ACTIVE));
LuaValue traceLib = LuaValue.tableOf();
traceLib.set("active", getter(() -> !region.get().isGlobal() && Recorder.INSTANCE.get(region.get()) instanceof ActiveTracer));
traceLib.set("auto", getter(() -> !region.get().isGlobal() && Recorder.INSTANCE.get(region.get()) instanceof AutoTraceRecorder));
traceLib.set("status", getter(() -> Recorder.INSTANCE.get(region.get()).scriptState()));
traceLib.set("time", getter(() -> Recorder.INSTANCE.get(region.get()).scriptTime()));
//LuaValue traceLib = LuaValue.tableOf();
//traceLib.set("active", getter(() -> !region.get().isGlobal() && Recorder.INSTANCE.get(region.get()) instanceof ActiveTracer));
//traceLib.set("auto", getter(() -> !region.get().isGlobal() && Recorder.INSTANCE.get(region.get()) instanceof AutoTraceRecorder));
//traceLib.set("status", getter(() -> Recorder.INSTANCE.get(region.get()).scriptState()));
//traceLib.set("time", getter(() -> Recorder.INSTANCE.get(region.get()).scriptTime()));
table.set("trace", traceLib);
//table.set("trace", traceLib);
Loader loader = Loader.getLoader(player);
table.set("loader", getter(() -> loader == null ? "OFF" : loader.getStage().name()));

Datei anzeigen

@ -23,8 +23,7 @@ import de.steamwar.bausystem.features.simulator.data.Simulator;
import de.steamwar.bausystem.features.simulator.data.SimulatorElement;
import de.steamwar.bausystem.features.simulator.data.SimulatorGroup;
import de.steamwar.bausystem.features.tpslimit.TPSUtils;
import de.steamwar.bausystem.features.tracer.record.Recorder;
import de.steamwar.bausystem.features.tracer.record.SingleTraceRecorder;
import de.steamwar.bausystem.features.tracer.TraceRecorder;
import de.steamwar.bausystem.region.Region;
import de.steamwar.bausystem.utils.TickEndEvent;
import de.steamwar.bausystem.utils.TickStartEvent;
@ -69,6 +68,20 @@ public class SimulatorExecutor implements Listener {
@Override
public void accept(World world) {
currentlyRunning.remove(simulator);
if (simulator.isAutoTrace()) {
simulator.getGroups()
.stream()
.map(SimulatorGroup::getElements)
.flatMap(List::stream)
.map(SimulatorElement::getPosition)
.map(pos -> pos.toLocation(WORLD))
.map(Region::getRegion)
.distinct()
.forEach(region -> {
TraceRecorder.instance.stopRecording(region);
});
}
}
});
@ -82,9 +95,7 @@ public class SimulatorExecutor implements Listener {
.map(Region::getRegion)
.distinct()
.forEach(region -> {
if (Recorder.INSTANCE.isDisabled(region)) {
Recorder.INSTANCE.set(region, new SingleTraceRecorder(region));
}
TraceRecorder.instance.startRecording(region);
});
}
return true;

Datei anzeigen

@ -20,9 +20,7 @@
package de.steamwar.bausystem.features.slaves.laufbau;
import com.sk89q.worldedit.EditSession;
import de.steamwar.bausystem.features.slaves.laufbau.states.FilteringTracesState;
import de.steamwar.bausystem.features.slaves.laufbau.states.LaufbauState;
import de.steamwar.bausystem.features.slaves.laufbau.states.CreatingLaufState;
import de.steamwar.bausystem.features.slaves.laufbau.states.ProcessingTracesState;
import de.steamwar.bausystem.utils.WorldEditUtils;
import lombok.Getter;
@ -40,9 +38,7 @@ public class Laufbau {
private Location pos1;
private Location pos2;
private FilteringTracesState filteringTracesState = null;
private ProcessingTracesState processingTracesState = null;
private CreatingLaufState creatingLaufState = null;
private LaufbauState active;
private List<BlockBoundingBox> elements;
@ -62,8 +58,6 @@ public class Laufbau {
int zFactor = (int) (Math.abs(selectionSize.getZ()) / 9.875);
factor = Math.max(Math.max(xFactor, Math.max(yFactor, zFactor)), 8);
filteringTracesState = new FilteringTracesState(world, this::inRegion);
editSession = WorldEditUtils.getEditSession(player);
elements = BlockBoundingBox.elements.stream().filter(blockBoundingBox -> {
@ -86,49 +80,32 @@ public class Laufbau {
return -Double.compare(o1.blockData.getMaterial().getBlastResistance(), o2.blockData.getMaterial().getBlastResistance());
});
}
}
private LaufbauState getActive() {
if (creatingLaufState != null) {
return creatingLaufState;
}
if (processingTracesState != null) {
return processingTracesState;
}
return filteringTracesState;
active = new ProcessingTracesState(world, this::inRegion, editSession, elements, factor);
}
private void createNextState() {
if (creatingLaufState != null) {
return;
}
if (processingTracesState != null) {
creatingLaufState = new CreatingLaufState(processingTracesState.getBlocks(), processingTracesState.getCuboidIntersectionCache(), world, editSession, elements, factor);
return;
}
processingTracesState = new ProcessingTracesState(filteringTracesState.getTntPositions(), this::inRegion, factor);
if (active == null) return;
active = active.getNextState();
}
public String actionBarMessage(Player p) {
return getActive().actionBarMessage(p);
return active.actionBarMessage(p);
}
public boolean hasNext() {
return getActive().hasNext();
if (active == null) return false;
return active.hasNext();
}
public void next() {
LaufbauState state = getActive();
LaufbauState state = active;
state.next();
if (!state.hasNext()) {
createNextState();
}
}
private boolean inRegion(Location location, int expansion) {
return inRegion(location.toVector(), expansion);
}
private boolean inRegion(Vector location, int expansion) {
if (location.getBlockX() >= pos1.getBlockX() - expansion) {
if (location.getBlockY() >= pos1.getBlockY() - expansion) {

Datei anzeigen

@ -196,4 +196,9 @@ public class CreatingLaufState implements LaufbauState {
}
}
}
@Override
public LaufbauState getNextState() {
return null;
}
}

Datei anzeigen

@ -1,91 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.slaves.laufbau.states;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.features.tracer.TNTPosition;
import de.steamwar.bausystem.features.tracer.show.Record;
import de.steamwar.bausystem.features.tracer.show.StoredRecords;
import de.steamwar.bausystem.utils.FlatteningWrapper;
import lombok.Getter;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiPredicate;
public class FilteringTracesState implements LaufbauState {
private long start = System.currentTimeMillis();
private World world;
private BiPredicate<Location, Integer> inRegionCheck;
private int totalRecord;
private List<Record> recordList;
private List<Record.TNTRecord> tntRecords = new ArrayList<>();
@Getter
private List<TNTPosition> tntPositions = new ArrayList<>();
public FilteringTracesState(World world, BiPredicate<Location, Integer> inRegionCheck) {
recordList = new ArrayList<>(StoredRecords.getRecords());
totalRecord = recordList.size();
this.world = world;
this.inRegionCheck = inRegionCheck;
}
@Override
public String actionBarMessage(Player p) {
return BauSystem.MESSAGE.parse("LAUFBAU_SIMPLE_PROGRESS", p, BauSystem.MESSAGE.parse("LAUFBAU_STATE_FILTERING_TRACES", p), totalRecord - recordList.size(), totalRecord, eta(p, start, totalRecord - recordList.size(), totalRecord));
}
@Override
public boolean hasNext() {
return !recordList.isEmpty() || !tntRecords.isEmpty();
}
@Override
public void next() {
if (tntRecords.isEmpty()) {
Record record = recordList.remove(0);
tntRecords.addAll(record.getTnt());
}
if (tntRecords.isEmpty()) {
return;
}
Record.TNTRecord tntRecord = tntRecords.remove(0);
tntRecord.getPositions().forEach(tntPosition -> {
if (FlatteningWrapper.impl.inWater(world, tntPosition.getLocation())) {
return;
}
if (inRegionCheck.test(tntPosition.getLocation().toLocation(world), 1)) {
tntPositions.add(tntPosition);
}
if (tntPosition.getPreviousLocation() != null && inRegionCheck.test(tntPosition.getPreviousLocation().toLocation(world), 1)) {
tntPositions.add(tntPosition);
}
});
}
}

Datei anzeigen

@ -45,4 +45,6 @@ public interface LaufbauState {
}
return LocalTime.ofNanoOfDay(eta).format(DateTimeFormatter.ofPattern(BauSystem.MESSAGE.parse("TIME", p)));
}
LaufbauState getNextState();
}

Datei anzeigen

@ -1,7 +1,7 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2022 SteamWar.de-Serverteam
* Copyright (C) 2024 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
@ -19,97 +19,110 @@
package de.steamwar.bausystem.features.slaves.laufbau.states;
import com.sk89q.worldedit.EditSession;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.features.slaves.laufbau.BlockBoundingBox;
import de.steamwar.bausystem.features.slaves.laufbau.Cuboid;
import de.steamwar.bausystem.features.tracer.TNTPosition;
import de.steamwar.bausystem.features.tracer.TNTPoint;
import de.steamwar.bausystem.features.tracer.TraceManager;
import de.steamwar.bausystem.region.Point;
import lombok.Getter;
import de.steamwar.bausystem.utils.FlatteningWrapper;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import java.util.*;
import java.util.function.BiPredicate;
import java.util.stream.Collectors;
public class ProcessingTracesState implements LaufbauState {
private long start = System.currentTimeMillis();
private final long start = System.currentTimeMillis();
private final World world;
private final BiPredicate<Vector, Integer> inRegionCheck;
private final EditSession editSession;
private final List<BlockBoundingBox> elements;
private final int factor;
private int totalCuboids;
private List<TNTPosition> tntPositionList;
private BiPredicate<Vector, Integer> inRegionCheck;
private int factor;
private final List<TNTPoint> TNTPoints;
private final int totalTntRecords;
private List<Cuboid> toExpand = new ArrayList<>();
private final Set<Point> affectedBlocks = new HashSet<>();
private final Map<Point, Set<Cuboid>> cuboidsPerChunk = new HashMap<>();
private int cuboidsDone = 0;
@Getter
private Set<Point> blocks = new HashSet<>();
@Getter
private Map<Point, Set<Cuboid>> cuboidIntersectionCache = new HashMap<>();
public ProcessingTracesState(List<TNTPosition> tntPositionList, BiPredicate<Vector, Integer> inRegionCheck, int factor) {
this.tntPositionList = tntPositionList;
this.totalCuboids = tntPositionList.stream().mapToInt(tntPosition -> tntPosition.getPreviousLocation() == null ? 1 : 3).sum();
public ProcessingTracesState(World world, BiPredicate<Vector, Integer> inRegionCheck, EditSession editSession, List<BlockBoundingBox> elements, int factor) {
this.world = world;
this.inRegionCheck = inRegionCheck;
this.editSession = editSession;
this.elements = elements;
this.factor = factor;
// TODO: Optimize only retrieving traces inside of the affected regions!
TNTPoints = TraceManager.instance.getAll()
.stream()
.flatMap(trace -> trace.getHistories().stream())
.flatMap(Collection::stream)
.collect(Collectors.toList());
totalTntRecords = TNTPoints.size();
}
@Override
public String actionBarMessage(Player p) {
return BauSystem.MESSAGE.parse("LAUFBAU_SIMPLE_PROGRESS", p, BauSystem.MESSAGE.parse("LAUFBAU_STATE_PROCESSING_TRACES", p), cuboidsDone, totalCuboids, eta(p, start, cuboidsDone, totalCuboids));
return BauSystem.MESSAGE.parse("LAUFBAU_SIMPLE_PROGRESS", p, BauSystem.MESSAGE.parse("LAUFBAU_STATE_PROCESSING_TRACES", p), totalTntRecords - TNTPoints.size(), totalTntRecords, eta(p, start, totalTntRecords - TNTPoints.size(), totalTntRecords));
}
private boolean inRegion(Vector location, int expansion) {
return inRegionCheck.test(location, expansion);
}
@Override
public boolean hasNext() {
return !tntPositionList.isEmpty() || !toExpand.isEmpty();
return !TNTPoints.isEmpty();
}
@Override
public void next() {
if (!toExpand.isEmpty()) {
Cuboid cuboid = toExpand.remove(0);
expandCuboid(cuboid);
TNTPoint current = TNTPoints.remove(0);
if (FlatteningWrapper.impl.inWater(world, current.getLocation().toVector())) return;
if (!(inRegion(current.getLocation().toVector(), 1) || (current.getPrevious().isPresent() && inRegion(current.getPrevious().get().getLocation().toVector(), 1))))
return;
Location location = current.getLocation();
if (current.getPrevious().isPresent()) {
Vector velocity = current.getPrevious().get().getVelocity();
Location previousLocation = current.getPrevious().get().getLocation();
Location movement = location.clone().subtract(previousLocation);
calculateCuboid(new Cuboid(previousLocation.getX() - 0.49, Math.min(previousLocation.getY(), location.getY()), previousLocation.getZ() - 0.49, 0.98, Math.abs(movement.getY()) + 0.98, 0.98));
if (velocity.getX() >= velocity.getZ()) {
calculateCuboid(new Cuboid(Math.min(previousLocation.getX(), location.getX()) - 0.49, location.getY(), previousLocation.getZ() - 0.49, Math.abs(movement.getX()) + 0.98, 0.98, 0.98));
calculateCuboid(new Cuboid(location.getX() - 0.49, location.getY(), Math.min(previousLocation.getZ(), location.getZ()) - 0.49, 0.98, 0.98, Math.abs(movement.getZ()) + 0.98));
} else {
TNTPosition tntPosition = tntPositionList.remove(0);
createCuboid(tntPosition);
calculateCuboid(new Cuboid(previousLocation.getX() - 0.49, location.getY(), Math.min(previousLocation.getZ(), location.getZ()) - 0.49, 0.98, 0.98, Math.abs(movement.getZ()) + 0.98));
calculateCuboid(new Cuboid(Math.min(previousLocation.getX(), location.getX()) - 0.49, location.getY(), location.getZ() - 0.49, Math.abs(movement.getX()) + 0.98, 0.98, 0.98));
}
} else {
calculateCuboid(new Cuboid(location.getX() - 0.49, location.getY(), location.getZ() - 0.49, 0.98, 0.98, 0.98));
}
}
private void createCuboid(TNTPosition tntPosition) {
Vector location = tntPosition.getLocation();
Vector previousLocation = tntPosition.getPreviousLocation();
if (previousLocation == null) {
toExpand.add(new Cuboid(location.getX() - 0.49, location.getY(), location.getZ() - 0.49, 0.98, 0.98, 0.98));
} else {
Vector movement = location.clone().subtract(previousLocation);
toExpand.add(new Cuboid(previousLocation.getX() - 0.49, Math.min(previousLocation.getY(), location.getY()), previousLocation.getZ() - 0.49, 0.98, Math.abs(movement.getY()) + 0.98, 0.98));
if (Math.abs(tntPosition.getUpdateVelocity().getX()) >= Math.abs(tntPosition.getUpdateVelocity().getZ())) {
toExpand.add(new Cuboid(Math.min(previousLocation.getX(), location.getX()) - 0.49, location.getY(), previousLocation.getZ() - 0.49, Math.abs(movement.getX()) + 0.98, 0.98, 0.98));
toExpand.add(new Cuboid(location.getX() - 0.49, location.getY(), Math.min(previousLocation.getZ(), location.getZ()) - 0.49, 0.98, 0.98, Math.abs(movement.getZ()) + 0.98));
} else {
toExpand.add(new Cuboid(previousLocation.getX() - 0.49, location.getY(), Math.min(previousLocation.getZ(), location.getZ()) - 0.49, 0.98, 0.98, Math.abs(movement.getZ()) + 0.98));
toExpand.add(new Cuboid(Math.min(previousLocation.getX(), location.getX()) - 0.49, location.getY(), location.getZ() - 0.49, Math.abs(movement.getX()) + 0.98, 0.98, 0.98));
}
}
}
private void expandCuboid(Cuboid cuboid) {
cuboidsDone++;
private void calculateCuboid(Cuboid cuboid) {
for (double x = cuboid.getX() - 2; x < cuboid.getX() + cuboid.getDx() + 2; x++) {
for (double y = cuboid.getY() - 2; y < cuboid.getY() + cuboid.getDy() + 2; y++) {
for (double z = cuboid.getZ() - 2; z < cuboid.getZ() + cuboid.getDz() + 2; z++) {
Vector location = new Vector(x, y, z);
if (inRegionCheck.test(location, 0)) {
Point point = new Point(location.getBlockX(), location.getBlockY(), location.getBlockZ());
blocks.add(point);
cuboidIntersectionCache.computeIfAbsent(point.divide(factor), __ -> new HashSet<>())
if (inRegion(location, 0)) {
affectedBlocks.add(new Point(location.getBlockX(), location.getBlockY(), location.getBlockZ()));
cuboidsPerChunk.computeIfAbsent(new Point(location.getBlockX() / factor, location.getBlockY() / factor, location.getBlockZ() / factor), __ -> new HashSet<>())
.add(cuboid);
}
}
}
}
}
@Override
public LaufbauState getNextState() {
return new CreatingLaufState(affectedBlocks, cuboidsPerChunk, world, editSession, elements, factor);
}
}

Datei anzeigen

@ -0,0 +1,227 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.tracer;
import de.steamwar.bausystem.region.Region;
import de.steamwar.bausystem.region.utils.RegionExtensionType;
import de.steamwar.bausystem.region.utils.RegionType;
import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.entity.TNTPrimed;
import org.bukkit.util.Vector;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.List;
import java.util.Optional;
/**
* Recording of a tnt at a specific tick
*/
@Getter
public class TNTPoint implements Externalizable {
/**
* Unique number to identify records being of the same tnt
*/
private int tntId;
/**
* Whether this is a record of a tnt explosion or an entity
*/
private boolean explosion;
/**
* Whether this is a record of a tnt that was in water
*/
private boolean inWater;
/**
* Whether this record was taken after the first tnt exploded
*/
private boolean afterFirstExplosion;
/**
* Whether this record has destroyed blocks in build area
*/
private boolean destroyedBuildArea;
/**
* Whether this record has destroyed blocks in testblock area
*/
private boolean destroyedTestBlock;
/**
* Tick offset, from this record being taken to the start of the trace
*/
private long ticksSinceStart;
/**
* Fuse ticks of the recorded tnt (0 if this is an explosion)
*/
private int fuse;
/**
* Location of the recorded tnt
*/
private Location location;
/**
* Velocity of the recorded tnt
*/
private Vector velocity;
/**
* List of all tnt records, that are represent the same tnt
*/
private List<TNTPoint> history;
/**
* Constructor for deserialization only !! Do not Call !!
*/
public TNTPoint() {
}
public TNTPoint(int tntId, TNTPrimed tnt, boolean explosion, boolean afterFirstExplosion, long ticksSinceStart,
List<TNTPoint> history, List<Block> destroyedBlocks) {
this.tntId = tntId;
this.explosion = explosion;
this.inWater = tnt.isInWater();
this.afterFirstExplosion = afterFirstExplosion;
this.ticksSinceStart = ticksSinceStart;
fuse = tnt.getFuseTicks();
location = tnt.getLocation();
velocity = tnt.getVelocity();
this.history = history;
boolean buildDestroy = false;
boolean testblockDestroy = false;
for (Block destroyedBlock : destroyedBlocks) {
if (Region.getRegion(destroyedBlock.getLocation()).inRegion(destroyedBlock.getLocation(), RegionType.BUILD,
RegionExtensionType.EXTENSION)) {
buildDestroy = true;
}
if (Region.getRegion(destroyedBlock.getLocation()).inRegion(destroyedBlock.getLocation(),
RegionType.TESTBLOCK, RegionExtensionType.EXTENSION)) {
testblockDestroy = true;
}
}
destroyedBuildArea = buildDestroy;
destroyedTestBlock = testblockDestroy;
}
/**
* Method for getting the next record of the tnt represented by this record
*
* @return the next record
*/
public Optional<TNTPoint> getNext() {
int index = history.indexOf(this);
return index == history.size() - 1 ? Optional.empty() : Optional.of(history.get(index + 1));
}
/**
* Method for getting the previous record of the tnt represented by this record
*
* @return the previous record
*/
public Optional<TNTPoint> getPrevious() {
int index = history.indexOf(this);
return index == 0 ? Optional.empty() : Optional.of(history.get(index - 1));
}
/**
* Internal methode for setting the history of this record
* during deserialization.
*
* @param history
*/
void setHistory(List<TNTPoint> history) {
this.history = history;
}
@Override
public void writeExternal(ObjectOutput objectOutput) throws IOException {
objectOutput.writeInt(tntId);
objectOutput.writeBoolean(explosion);
objectOutput.writeBoolean(inWater);
objectOutput.writeBoolean(afterFirstExplosion);
objectOutput.writeBoolean(destroyedBuildArea);
objectOutput.writeBoolean(destroyedTestBlock);
objectOutput.writeLong(ticksSinceStart);
objectOutput.writeInt(fuse);
objectOutput.writeDouble(location.getX());
objectOutput.writeDouble(location.getY());
objectOutput.writeDouble(location.getZ());
objectOutput.writeDouble(velocity.getX());
objectOutput.writeDouble(velocity.getY());
objectOutput.writeDouble(velocity.getZ());
}
@Override
public void readExternal(ObjectInput objectInput) throws IOException {
tntId = objectInput.readInt();
explosion = objectInput.readBoolean();
inWater = objectInput.readBoolean();
afterFirstExplosion = objectInput.readBoolean();
destroyedBuildArea = objectInput.readBoolean();
destroyedTestBlock = objectInput.readBoolean();
ticksSinceStart = objectInput.readLong();
fuse = objectInput.readInt();
double locX = objectInput.readDouble();
double locY = objectInput.readDouble();
double locZ = objectInput.readDouble();
location = new Location(Bukkit.getWorlds().get(0), locX, locY, locZ);
double velX = objectInput.readDouble();
double velY = objectInput.readDouble();
double velZ = objectInput.readDouble();
velocity = new Vector(velX, velY, velZ);
}
@Override
public String toString() {
return "TNTPoint{" +
"tntId=" + tntId +
", explosion=" + explosion +
", inWater=" + inWater +
", afterFirstExplosion=" + afterFirstExplosion +
", destroyedBuildArea=" + destroyedBuildArea +
", destroyedTestBlock=" + destroyedTestBlock +
", ticksSinceStart=" + ticksSinceStart +
", fuse=" + fuse +
", location=" + location +
", velocity=" + velocity +
'}';
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof TNTPoint)) return false;
TNTPoint record = (TNTPoint) obj;
if (record.isExplosion() != explosion) return false;
if (!record.getLocation().equals(location)) return false;
if (!record.getVelocity().equals(velocity)) return false;
return true;
}
}

Datei anzeigen

@ -1,62 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.tracer;
import de.steamwar.bausystem.features.tracer.show.Record;
import de.steamwar.bausystem.shared.Position;
import lombok.Getter;
import lombok.Setter;
import org.bukkit.entity.TNTPrimed;
import org.bukkit.util.Vector;
@Getter
public class TNTPosition extends Position {
private final Record.TNTRecord record;
private final int fuseTicks;
private final long timeTicks;
private final Vector previousLocation;
private final Vector velocity;
private final Vector updateVelocity;
private final boolean source;
private final boolean exploded;
@Setter
private boolean microMotion;
public TNTPosition(Record.TNTRecord record, TNTPrimed entity, long timeTicks, Vector previousLocation, Vector velocity, Vector updateVelocity, boolean source, boolean exploded) {
super(entity.getLocation().toVector());
this.record = record;
this.fuseTicks = entity.getFuseTicks();
this.timeTicks = timeTicks;
this.previousLocation = previousLocation;
this.velocity = velocity;
this.updateVelocity = updateVelocity;
this.source = source;
this.exploded = exploded;
}
@Override
public String toString() {
return "Position{" +
"location=" + super.getLocation() +
'}';
}
}

Datei anzeigen

@ -0,0 +1,339 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.tracer;
import de.steamwar.bausystem.features.tracer.rendering.BundleFilter;
import de.steamwar.bausystem.features.tracer.rendering.PlayerTraceShowData;
import de.steamwar.bausystem.features.tracer.rendering.TraceEntity;
import de.steamwar.bausystem.features.tracer.rendering.ViewFlag;
import de.steamwar.bausystem.region.Region;
import de.steamwar.entity.REntity;
import de.steamwar.entity.REntityServer;
import lombok.Cleanup;
import lombok.Getter;
import lombok.SneakyThrows;
import org.bukkit.entity.Player;
import java.io.*;
import java.lang.ref.SoftReference;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.zip.GZIPInputStream;
public class Trace {
/**
* UUID of the trace used for
*/
@Getter
private final UUID uuid;
/**
* File the records are saved in
*/
@Getter
private final File recordsSaveFile;
/**
* File the metadata are saved in
*/
@Getter
private final File metadataSaveFile;
/**
* Region the trace was recorded in
*/
@Getter
private final Region region;
/**
* Date the trace was recorded at
*/
@Getter
private final Date date;
/**
* Records of TNTs, making up the trace
*/
private SoftReference<List<TNTPoint>> records;
/**
* A map of all REntityServers rendering this trace
*/
private final Map<Player, REntityServer> entityServerMap = new HashMap<>();
/**
* Constructor for the creation of a new trace
*
* @param region the region the trace is created at
* @param recordList the list for the records making up this trace
*/
@SneakyThrows
public Trace(Region region, List<TNTPoint> recordList) {
this.uuid = UUID.randomUUID();
recordsSaveFile = new File(TraceManager.tracesFolder, uuid + ".records");
this.region = region;
this.date = new Date();
records = new SoftReference<>(recordList);
metadataSaveFile = new File(TraceManager.tracesFolder, uuid + ".meta");
@Cleanup
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(metadataSaveFile));
outputStream.writeUTF(uuid.toString());
outputStream.writeUTF(region.getName());
outputStream.writeObject(date);
}
/**
* Constructor for serialising a trace from the file system
*
* @param metadataSaveFile the file for this traces metadata
*/
@SneakyThrows
public Trace(File metadataSaveFile) {
String uuid = null;
Region region = null;
Date date = null;
this.metadataSaveFile = metadataSaveFile;
try {
@Cleanup
ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(metadataSaveFile));
uuid = inputStream.readUTF();
region = Region.getREGION_MAP().get(inputStream.readUTF());
date = (Date) inputStream.readObject();
inputStream.close();
} finally {
this.uuid = UUID.fromString(uuid);
this.region = region;
this.date = date;
recordsSaveFile = new File(TraceManager.tracesFolder, uuid + ".records");
this.records = new SoftReference<>(null);
}
}
/**
* Gets the histories of all tnts in this trace
*
* @return the histories of this trace
*/
public Set<List<TNTPoint>> getHistories() {
Set<List<TNTPoint>> histories = new HashSet<>();
for (TNTPoint record : getRecords()) {
histories.add(record.getHistory());
}
return histories;
}
/**
* List of all used ids
*/
public List<String> getUsedIds() {
return getRecords()
.stream()
.map(TNTPoint::getTntId)
.map(i -> i + "")
.collect(Collectors.toList());
}
/**
* Renders this traces
*
* @param player The player the trace is rendered to
* @param playerTraceShowData The showData for modifying the rendering
*/
public void render(Player player, PlayerTraceShowData playerTraceShowData) {
REntityServer entityServer = entityServerMap.get(player);
if (entityServer != null) {
entityServer.getEntities().forEach(REntity::die);
} else {
entityServer = new REntityServer();
entityServer.addPlayer(player);
entityServer.setCallback((p, rEntity, entityAction) -> {
if (entityAction != REntityServer.EntityAction.INTERACT) return;
if (rEntity instanceof TraceEntity) {
((TraceEntity) rEntity).printIntoChat(p);
}
});
entityServerMap.put(player, entityServer);
}
render(getRecords(), entityServer, playerTraceShowData);
}
/**
* Renders specific records to this trace rendering
*
* @param records The records to be rendered
* @param player The player the records are rendered to
* @param playerTraceShowData The showData for modifying the rendering
*/
protected void render(List<TNTPoint> records, Player player, PlayerTraceShowData playerTraceShowData) {
render(records, entityServerMap.get(player), playerTraceShowData);
}
/**
* Internal methode to render records to a REntityServer
*
* @param records Records to render
* @param entityServer The show server the trace will be renderd to
* @param playerTraceShowData The showData for modifying the rendering
*/
private void render(List<TNTPoint> records, REntityServer entityServer, PlayerTraceShowData playerTraceShowData) {
if (records.isEmpty()) {
return;
}
Set<ViewFlag> flagList = playerTraceShowData.getEffectiveViewFlags();
// Apply filters
Stream<TNTPoint> workingRecordsStream = records.stream();
for (ViewFlag flag : flagList) {
workingRecordsStream = flag.filter(workingRecordsStream);
}
List<TNTPoint> workingRecords = workingRecordsStream.collect(Collectors.toList());
// Bundle records at unique positions
List<List<TNTPoint>> bundles = bundleRecords(workingRecords, playerTraceShowData.getBundleFilter());
// Render bundled records
List<TraceEntity> entities = new LinkedList<>();
for (List<TNTPoint> bundle : bundles) {
entities.add(new TraceEntity(entityServer, bundle.get(0).getLocation(), bundle.get(0).isExplosion(), bundle, this));
}
// Apply modifiers
for (ViewFlag flag : flagList) {
flag.modify(entityServer, entities);
}
}
/**
* Bundles the passed TNTRecords based on whether they are at the same location
*
* @param records The TNTRecords that are supposed to be bundled
* @param filter A filter specefieng whether records can be bundled
* @return A list of bundles
*/
private List<List<TNTPoint>> bundleRecords(List<TNTPoint> records, BundleFilter filter) {
if (filter == BundleFilter.NONE) {
return records.stream().map(List::of).collect(Collectors.toList());
}
List<List<TNTPoint>> bundles = new ArrayList<>();
recordsLoop:
for (TNTPoint record : records) {
for (int i = bundles.size() - 1; i >= 0; i--) {
List<TNTPoint> bundle = bundles.get(i);
Boolean filterResult = filter.function.apply(record, bundle.get(0));
if (filterResult == null) {
ArrayList<TNTPoint> newBundle = new ArrayList<>();
newBundle.add(record);
bundles.add(newBundle);
continue recordsLoop;
} else if (filterResult) {
bundle.add(record);
continue recordsLoop;
}
}
ArrayList<TNTPoint> newBundle = new ArrayList<>();
newBundle.add(record);
bundles.add(newBundle);
}
return bundles;
}
/**
* Hides this trail for the given player
*
* @param player
*/
public void hide(Player player) {
REntityServer entityServer = entityServerMap.remove(player);
if (entityServer == null) {
return;
}
entityServer.removePlayer(player);
if (entityServer.getPlayers().isEmpty()) {
entityServer.close();
}
}
/**
* Hides this trace for all players
*/
public void hide() {
entityServerMap.forEach((player, entityServer) -> {
entityServer.close();
});
entityServerMap.clear();
}
/**
* Loads the records of this trace from storage to memory
*/
@SneakyThrows
private void loadRecords() {
List<TNTPoint> records = new ArrayList<>();
FileInputStream fileInputStream = new FileInputStream(recordsSaveFile);
@Cleanup
ObjectInputStream inputStream = new ObjectInputStream(new GZIPInputStream(fileInputStream));
while (fileInputStream.getChannel().position() < recordsSaveFile.length()) {
records.add((TNTPoint) inputStream.readObject());
}
Map<Integer, List<TNTPoint>> histories = new HashMap<>();
for (TNTPoint record : records) {
int tntId = record.getTntId();
List<TNTPoint> history = histories.computeIfAbsent(tntId, id -> new ArrayList<>());
history.add(record);
record.setHistory(history);
}
this.records = new SoftReference<>(records);
}
public List<TNTPoint> getRecords() {
if (records.get() == null) {
loadRecords();
}
return records.get();
}
@Override
public String toString() {
return "Trace{" +
"uuid=" + uuid +
", region=" + region +
", creationTime=" + date +
", recordsSaveFile=" + recordsSaveFile.getName() +
", records=" + getRecords() +
'}';
}
}

Datei anzeigen

@ -1,7 +1,7 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2022 SteamWar.de-Serverteam
* 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
@ -20,25 +20,24 @@
package de.steamwar.bausystem.features.tracer;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.Permission;
import de.steamwar.bausystem.features.tracer.record.*;
import de.steamwar.bausystem.features.tracer.show.*;
import de.steamwar.bausystem.features.tracer.rendering.BundleFilter;
import de.steamwar.bausystem.features.tracer.rendering.PlayerTraceShowData;
import de.steamwar.bausystem.features.tracer.rendering.ViewFlag;
import de.steamwar.bausystem.features.tracer.rendering.dynamicflags.AtFlag;
import de.steamwar.bausystem.region.Region;
import de.steamwar.bausystem.shared.ShowMode;
import de.steamwar.command.PreviousArguments;
import de.steamwar.command.SWCommand;
import de.steamwar.command.TypeMapper;
import de.steamwar.command.TypeValidator;
import de.steamwar.linkage.Linked;
import de.steamwar.linkage.LinkedInstance;
import lombok.AllArgsConstructor;
import net.md_5.bungee.api.chat.ClickEvent;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Supplier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Linked
public class TraceCommand extends SWCommand {
@ -47,199 +46,226 @@ public class TraceCommand extends SWCommand {
super("trace", "trail");
}
@LinkedInstance
public Recorder recorder;
@Register(value = {"start"}, description = "TRACE_COMMAND_HELP_START")
public void startCommand(@Validator Player p) {
Region region = Region.getRegion(p.getLocation());
recorder.set(region, new SimpleTraceRecorder());
BauSystem.MESSAGE.send("TRACE_MESSAGE_START", p);
@Register(value = "start", description = "TRACE_COMMAND_HELP_START")
public void start(@Validator Player player) {
Region region = Region.getRegion(player.getLocation());
TraceRecorder.instance.startRecording(region);
BauSystem.MESSAGE.send("TRACE_MESSAGE_START", player);
}
@Register(value = {"single"}, description = "TRACE_COMMAND_HELP_SINGLE")
public void singleCommand(@Validator Player p) {
Region region = Region.getRegion(p.getLocation());
recorder.set(region, new SingleTraceRecorder(region));
BauSystem.MESSAGE.send("TRACE_MESSAGE_SINGLE", p);
@Register(value = "stop", description = "TRACE_COMMAND_HELP_STOP")
public void stop(@Validator Player player) {
Region region = Region.getRegion(player.getLocation());
TraceRecorder.instance.stopRecording(region);
BauSystem.MESSAGE.send("TRACE_MESSAGE_STOP", player);
}
@Register(value = {"stop"}, description = "TRACE_COMMAND_HELP_STOP")
public void stopCommand(@Validator Player p) {
Region region = Region.getRegion(p.getLocation());
recorder.remove(region);
BauSystem.MESSAGE.send("TRACE_MESSAGE_STOP", p);
}
@Register(value = {"auto"}, description = "TRACE_COMMAND_HELP_AUTO")
@Register({"toggleauto"})
public void autoCommand(@Validator Player p, @OptionalValue("-explode") @StaticValue({"-explode", "-ignite"}) String type) {
Region region = Region.getRegion(p.getLocation());
switch (type) {
case "-explode":
recorder.set(region, new AutoExplodeTraceRecorder());
BauSystem.MESSAGE.send("TRACE_MESSAGE_AUTO_IDLE_EXPLODE", p);
break;
case "-ignite":
recorder.set(region, new AutoIgniteTraceRecorder());
BauSystem.MESSAGE.send("TRACE_MESSAGE_AUTO_IDLE_IGNITE", p);
break;
default:
break;
}
}
@Register(value = {"autoremove"}, description = "TRACE_COMMAND_HELP_AUTO_REMOVE")
@Register(value = {"autodelete"})
public void setAutoDeleteMode(@Validator Player p, @StaticValue({"-always", "-never", "-no_build_destroy", "-build_destroy", "-no_testblock_destroy", "-testblock_destroy"}) String destroyMode) {
Region region = Region.getRegion(p.getLocation());
TraceRecorder recorder = this.recorder.get(region);
if (!(recorder instanceof AutoTraceRecorder) || recorder instanceof SingleTraceRecorder) {
BauSystem.MESSAGE.send("TRACE_MESSAGE_AUTO_DELETE_INVALID", p);
return;
}
AutoTraceRecorder autoTraceRecorder = (AutoTraceRecorder) recorder;
switch (destroyMode) {
case "-always":
autoTraceRecorder.setTraceRecordAutoDeletion(TraceRecordAutoDeletion.ALWAYS);
break;
case "-never":
autoTraceRecorder.setTraceRecordAutoDeletion(TraceRecordAutoDeletion.NEVER);
break;
case "-no_build_destroy":
autoTraceRecorder.setTraceRecordAutoDeletion(TraceRecordAutoDeletion.NO_BUILD_DESTROY);
break;
case "-build_destroy":
autoTraceRecorder.setTraceRecordAutoDeletion(TraceRecordAutoDeletion.BUILD_DESTROY);
break;
case "-no_testblock_destroy":
autoTraceRecorder.setTraceRecordAutoDeletion(TraceRecordAutoDeletion.NO_TESTBLOCK_DESTROY);
break;
case "-testblock_destroy":
autoTraceRecorder.setTraceRecordAutoDeletion(TraceRecordAutoDeletion.TESTBLOCK_DESTROY);
break;
default:
return;
}
BauSystem.MESSAGE.send("TRACE_MESSAGE_AUTO_DELETE_" + autoTraceRecorder.getTraceRecordAutoDeletion().name(), p);
}
@Register(value = {"show"}, description = "TRACE_COMMAND_HELP_SHOW_AT")
public void showAtCommand(@Validator Player p, @OptionalValue("time") @StaticValue({"time", "fuse"}) String type, @StaticValue("at") String __, @Min(intValue = 0) int at) {
internalSetShowFilter(p, "TRACE_MESSAGE_SHOW_AT", type, at, at);
}
@Register(value = {"show"}, description = "TRACE_COMMAND_HELP_SHOW_FROM")
public void showFromCommand(@Validator Player p, @OptionalValue("time") @StaticValue({"time", "fuse"}) String type, @StaticValue("from") String __, @Min(intValue = 0) int from) {
if (from == 0) {
TraceShowManager.setShowFilter(p, null);
BauSystem.MESSAGE.send("TRACE_MESSAGE_SHOW", p);
return;
}
internalSetShowFilter(p, "TRACE_MESSAGE_SHOW_FROM", type, from, Integer.MAX_VALUE);
}
@Register(value = {"show"}, description = "TRACE_COMMAND_HELP_SHOW_FROM_TO")
public void showFromToCommand(@Validator Player p, @OptionalValue("time") @StaticValue({"time", "fuse"}) String type, @StaticValue("from") String __, @Min(intValue = 0) int from, @StaticValue("to") String ___, @Min(intValue = 0) int to) {
internalSetShowFilter(p, "TRACE_MESSAGE_SHOW_FROM_TO", type, from, to);
}
private void internalSetShowFilter(Player p, String message, String type, int from, int to) {
if (to < from) {
BauSystem.MESSAGE.send("TRACE_MESSAGE_SHOW_TO_SMALLER", p);
return;
}
TraceShowManager.setShowFilter(p, tntPosition -> {
switch (type) {
case "time":
return tntPosition.getTimeTicks() >= from && tntPosition.getTimeTicks() <= to;
case "fuse":
return tntPosition.getFuseTicks() >= from && tntPosition.getFuseTicks() <= to;
default:
return true;
}
});
BauSystem.MESSAGE.send(message, p, type, from, to);
}
// /trace show at 0
// /trace show raw -auto at 0
@Register(value = {"show"}, description = "TRACE_COMMAND_HELP_SHOW")
public void showCommand(@Validator Player p, @OptionalValue("entity") ShowModeType showModeType, ShowModeParameterType... showModeParameterTypes) {
Region region = Region.getRegion(p.getLocation());
ShowModeParameter showModeParameter = new ShowModeParameter();
if (region.getWaterLevel() != 0) { // Enable Water by default for regions with WaterLevel e.g. WarShip
showModeParameter.enableWater();
}
for (ShowModeParameterType showModeParameterType : showModeParameterTypes) {
if (showModeParameterType == ShowModeParameterType.WATER && region.getWaterLevel() != 0) {
showModeParameter.disableWater();
@Register(value = "auto", description = "TRACE_COMMAND_HELP_AUTO")
public void auto(@Validator Player player) {
Region region = Region.getRegion(player.getLocation());
if (TraceRecorder.instance.toggleAutoTrace(region)) {
BauSystem.MESSAGE.send("TRACE_MESSAGE_AUTO_START", player);
} else {
showModeParameterType.getShowModeParameterConsumer().accept(showModeParameter);
BauSystem.MESSAGE.send("TRACE_MESSAGE_AUTO_STOP", player);
}
}
TraceShowManager.show(p, showModeType.showModeBiFunction.apply(p, showModeParameter));
BauSystem.MESSAGE.send("TRACE_MESSAGE_SHOW", p);
@Register(value = "show", description = "TRACE_COMMAND_HELP_SHOW")
public void show(@Validator Player player, @OptionalValue("DEFAULT") BundleFilter bundleFilter, ViewFlag... flags) {
showInternal(player, bundleFilter, flags);
BauSystem.MESSAGE.send("TRACE_MESSAGE_SHOW", player);
}
@Register(value = {"hide"}, description = "TRACE_COMMAND_HELP_HIDE")
public void hideCommand(@Validator Player p) {
TraceShowManager.hide(p);
BauSystem.MESSAGE.send("TRACE_MESSAGE_HIDE", p);
@Register(value = {"show", "at"}, description = "TRACE_COMMAND_HELP_SHOW_AT_WITH")
public void showAt(@Validator Player player, @Min(intValue = 0) int time, @StaticValue("with") String with, @OptionalValue("DEFAULT") BundleFilter bundleFilter, ViewFlag... flags) {
showInternal(player, time, time, bundleFilter, flags);
BauSystem.MESSAGE.send("TRACE_MESSAGE_SHOW_AT", player, time);
}
@Register(value = {"delete"}, description = "TRACE_COMMAND_HELP_DELETE")
@Register({"clear"})
public void deleteCommand(@Validator Player p) {
Region region = Region.getRegion(p.getLocation());
StoredRecords.clear(region);
BauSystem.MESSAGE.send("TRACE_MESSAGE_DELETE", p);
@Register(value = {"show", "from"}, description = "TRACE_COMMAND_HELP_SHOW_FROM_WITH")
public void showFromTo(@Validator Player player, @Min(intValue = 0) int from, @StaticValue("with") String with, @OptionalValue("DEFAULT") BundleFilter bundleFilter, ViewFlag... flags) {
showInternal(player, from, Integer.MAX_VALUE, bundleFilter, flags);
BauSystem.MESSAGE.send("TRACE_MESSAGE_SHOW_FROM", player, from);
}
@AllArgsConstructor
private enum ShowModeType {
ENTITY((player, showModeParameter) -> new EntityShowMode(player, showModeParameter, 16)),
RAW((player, showModeParameter) -> new EntityShowMode(player, showModeParameter, -1));
private BiFunction<Player, ShowModeParameter, ShowMode<TNTPosition>> showModeBiFunction;
@Register(value = {"show", "from"}, description = "TRACE_COMMAND_HELP_SHOW_FROM_TO_WITH")
public void showFromTo(@Validator Player player, @Min(intValue = 0) int from, @StaticValue("to") String toString, int to, @StaticValue("with") String with, @OptionalValue("DEFAULT") BundleFilter bundleFilter, ViewFlag... flags) {
if (to < from) {
BauSystem.MESSAGE.send("TRACE_MESSAGE_SHOW_TO_SMALLER", player);
return;
}
showInternal(player, from, to, bundleFilter, flags);
BauSystem.MESSAGE.send("TRACE_MESSAGE_SHOW_FROM_TO", player, from, to);
}
@ClassMapper(value = ShowModeParameterType.class, local = true)
public TypeMapper<ShowModeParameterType> showModeParameterTypesTypeMapper() {
Map<ShowModeParameterType, List<String>> showModeParameterTypeListMap = new EnumMap<>(ShowModeParameterType.class);
for (ShowModeParameterType value : ShowModeParameterType.values()) {
showModeParameterTypeListMap.put(value, value.getTabCompletes());
@Register(value = {"show", "at"}, description = "TRACE_COMMAND_HELP_SHOW_AT")
public void showAt(@Validator Player player, @Min(intValue = 0) int time) {
TraceManager.instance.renderAt(player, time, time);
BauSystem.MESSAGE.send("TRACE_MESSAGE_SHOW_AT", player, time);
}
Map<String, ShowModeParameterType> showModeParameterTypesMap = new HashMap<>();
showModeParameterTypeListMap.forEach((k, v) -> v.forEach(s -> showModeParameterTypesMap.put(s, k)));
@Register(value = {"show", "from"}, description = "TRACE_COMMAND_HELP_SHOW_FROM")
public void showFrom(@Validator Player player, @Min(intValue = 0) int from) {
TraceManager.instance.renderAt(player, from, Integer.MAX_VALUE);
BauSystem.MESSAGE.send("TRACE_MESSAGE_SHOW_FROM", player, from);
}
return new TypeMapper<ShowModeParameterType>() {
@Register(value = {"show", "from"}, description = "TRACE_COMMAND_HELP_SHOW_FROM_TO")
public void showFromTo(@Validator Player player, @Min(intValue = 0) int from, @StaticValue("to") String toString, int to) {
TraceManager.instance.renderAt(player, from, to);
BauSystem.MESSAGE.send("TRACE_MESSAGE_SHOW_FROM_TO", player, from, to);
}
private void showInternal(Player player, BundleFilter bundleFilter, ViewFlag... flags) {
PlayerTraceShowData playerTraceShowData = new PlayerTraceShowData(bundleFilter, flags);
TraceManager.instance.show(player, playerTraceShowData);
}
private void showInternal(Player player, int from, int to, BundleFilter bundleFilter, ViewFlag... flags) {
PlayerTraceShowData playerTraceShowData = new PlayerTraceShowData(bundleFilter, flags);
playerTraceShowData.addViewFlag(new AtFlag(from, to));
TraceManager.instance.show(player, playerTraceShowData);
}
@Register(value = "hide", description = "TRACE_COMMAND_HELP_HIDE")
public void hide(@Validator Player player) {
TraceManager.instance.hide(player);
BauSystem.MESSAGE.send("TRACE_MESSAGE_HIDE", player);
}
@Register(value = "clear")
public void clear(@Validator Player player) {
TraceManager.instance.clear(Region.getRegion(player.getLocation()));
BauSystem.MESSAGE.send("TRACE_MESSAGE_CLEAR", player);
}
@Register(value = "delete", description = "TRACE_COMMAND_HELP_DELETE")
public void delete(@Validator Player player, Trace trace) {
TraceManager.instance.remove(trace);
BauSystem.MESSAGE.send("TRACE_MESSAGE_DELETE", player);
}
@Register(value = "isolate", description = "TRACE_COMMAND_HELP_ISOLATE")
public void isolate(@Validator Player player, Trace trace, @ErrorMessage("TRACE_RECORD_ID_INVALID") TNTPoint... records) {
TraceManager.instance.isolate(player, records);
BauSystem.MESSAGE.send("TRACE_MESSAGE_ISOLATE", player);
}
@Register(value = "share", description = "TRACE_COMMAND_HELP_SHARE")
public void share(@Validator Player player) {
BauSystem.MESSAGE.broadcast("TRACE_MESSAGE_SHARE", "TRACE_MESSAGE_SHARE_HOVER", new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/trace follow " + player.getName()), player.getName());
}
@Register(value = "follow", description = "TRACE_COMMAND_HELP_FOLLOW")
public void follow(@Validator Player player, Player toFollow) {
if (player == toFollow) {
BauSystem.MESSAGE.send("TRACE_MESSAGE_FOLLOW_SELF", player);
return;
}
TraceManager.instance.follow(player, toFollow);
BauSystem.MESSAGE.send("TRACE_MESSAGE_FOLLOW", player, toFollow.getName());
}
@Register(value = "unfollow", description = "TRACE_COMMAND_HELP_UNFOLLOW")
public void unfollow(@Validator Player player) {
TraceManager.instance.unfollow(player);
BauSystem.MESSAGE.send("TRACE_MESSAGE_UNFOLLOW", player);
}
@ClassMapper(value = Trace.class, local = true)
public TypeMapper<Trace> traceClassMapper() {
return new TypeMapper<>() {
@Override
public ShowModeParameterType map(CommandSender commandSender, PreviousArguments previousArguments, String s) {
return showModeParameterTypesMap.get(s);
public Trace map(CommandSender commandSender, String[] previousArguments, String s) {
return TraceManager.instance.get(Integer.parseInt(s)).orElse(null);
}
@Override
public List<String> tabCompletes(CommandSender commandSender, PreviousArguments previousArguments, String s) {
Set<ShowModeParameterType> showModeParameterTypeSet = new HashSet<>();
Arrays.stream(previousArguments.userArgs).map(showModeParameterTypesMap::get).forEach(showModeParameterTypeSet::add);
showModeParameterTypeSet.remove(null);
Set<ShowModeParameterType> removed = showModeParameterTypeSet.stream()
.map(ShowModeParameterType::getRemoved)
.map(Supplier::get)
.flatMap(Arrays::stream)
.collect(Collectors.toSet());
List<String> tabCompletes = new ArrayList<>();
for (Map.Entry<ShowModeParameterType, List<String>> entry : showModeParameterTypeListMap.entrySet()) {
if (removed.contains(entry.getKey()) || showModeParameterTypeSet.contains(entry.getKey())) {
continue;
public Collection<String> tabCompletes(CommandSender sender, PreviousArguments previousArguments, String s) {
return TraceManager.instance.getAllIds().stream()
.map(Object::toString)
.collect(Collectors.toList());
}
tabCompletes.addAll(entry.getValue());
};
}
return tabCompletes;
@ClassMapper(value = TNTPoint.class, local = true)
public TypeMapper<TNTPoint> recordMapper() {
return new TypeMapper<>() {
@Override
public TNTPoint map(CommandSender commandSender, PreviousArguments previousArguments, String s) {
Trace trace = previousArguments.getFirst(Trace.class).orElse(null);
if (trace == null) return null;
int id = Integer.parseInt(s);
return trace.getRecords().stream()
.filter(record -> record.getTntId() == id)
.findFirst()
.orElse(null);
}
// TODO change when new command framework update
@Override
public Collection<String> tabCompletes(CommandSender sender, PreviousArguments previousArguments, String s) {
Trace trace = previousArguments.getFirst(Trace.class).orElse(null);
if (trace == null) return null;
return trace.getUsedIds();
}
};
}
@ClassMapper(value = BundleFilter.class, local = true)
public TypeMapper<BundleFilter> bundleFilterClassMapper() {
return new TypeMapper<>() {
@Override
public BundleFilter map(CommandSender commandSender, String[] previousArguments, String s) {
for (BundleFilter filter : BundleFilter.values()) {
if (s.equals(filter.toString())) {
return filter;
}
}
return null;
}
@Override
public Collection<String> tabCompletes(CommandSender sender, PreviousArguments previousArguments, String s) {
if (s.length() == 0) {
return new ArrayList<>();
}
return Arrays.stream(BundleFilter.values())
.map(Enum::toString)
.collect(Collectors.toList());
}
};
}
@ClassMapper(value = ViewFlag.class, local = true)
public TypeMapper<ViewFlag> viewFlagClassMapper() {
return new TypeMapper<ViewFlag>() {
@Override
public ViewFlag map(CommandSender commandSender, String[] previousArguments, String s) {
for (ViewFlag flag : ViewFlag.flags) {
if (s.equals("--" + flag.name)) {
return flag;
}
for (String alias : flag.aliases) {
if (s.equals("-" + alias)) {
return flag;
}
}
}
return null;
}
@Override
public Collection<String> tabCompletes(CommandSender sender, PreviousArguments previousArguments, String s) {
return ViewFlag.flags.stream()
.flatMap(viewFlag -> Stream.concat(Stream.of("--" + viewFlag.name),
Arrays.stream(viewFlag.aliases).map(name -> "-" + name)))
.collect(Collectors.toList());
}
};
}

Datei anzeigen

@ -0,0 +1,388 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.tracer;
import de.steamwar.bausystem.features.tracer.rendering.BundleFilter;
import de.steamwar.bausystem.features.tracer.rendering.PlayerTraceShowData;
import de.steamwar.bausystem.features.tracer.rendering.dynamicflags.AtFlag;
import de.steamwar.bausystem.features.tracer.rendering.dynamicflags.IsolateFlag;
import de.steamwar.bausystem.region.Region;
import de.steamwar.linkage.Linked;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerQuitEvent;
import java.io.File;
import java.util.*;
import java.util.stream.Collectors;
@Linked
public class TraceManager implements Listener {
public static TraceManager instance;
{
instance = this;
}
public static File tracesFolder = new File(Bukkit.getWorlds().get(0).getWorldFolder(), "traces");
public TraceManager() {
if (!tracesFolder.exists())
tracesFolder.mkdir();
File[] traceFiles = tracesFolder.listFiles();
if (traceFiles == null)
return;
for (File traceFile : traceFiles) {
if (traceFile.getName().contains(".records"))
continue;
add(new Trace(traceFile));
}
}
/**
* List of all current traces
*/
private final Map<Region, Map<Integer, Trace>> tracesByRegion = new HashMap<>();
private final Map<Region, Map<Player, PlayerTraceShowData>> showDataPerRegionPerPlayer = new HashMap<>();
private final Map<Player, Set<Player>> followerMap = new HashMap<>();
/**
* Utility variable to keep track of the next open trace id;
*/
private int nextOpenId = 0;
/**
* Adds a new trace to the global record
*
* @param trace Trace to be added
* @return id of the created trace
*/
protected int add(Trace trace) {
showDataPerRegionPerPlayer.getOrDefault(trace.getRegion(), Collections.emptyMap()).forEach((player, playerTraceShowData) -> {
trace.render(player, playerTraceShowData);
followerMap.getOrDefault(player, Collections.emptySet()).forEach(follower -> {
trace.render(follower, playerTraceShowData);
});
});
tracesByRegion.computeIfAbsent(trace.getRegion(), region -> new HashMap<>()).put(nextOpenId, trace);
nextOpenId++;
return nextOpenId;
}
/**
* Get the id of the given trace
*
* @param trace
*/
public int getId(Trace trace) {
for (Map.Entry<Integer, Trace> entry : tracesByRegion.getOrDefault(trace.getRegion(), Collections.emptyMap()).entrySet()) {
if (entry.getValue() == trace) return entry.getKey();
}
return -1;
}
/**
* Renders only the given records to the specified trace
*
* @param trace
* @param recordsToAdd
*/
protected void showPartial(Trace trace, List<TNTPoint> recordsToAdd) {
showDataPerRegionPerPlayer.getOrDefault(trace.getRegion(), Collections.emptyMap()).forEach((player, playerTraceShowData) -> {
trace.render(recordsToAdd, player, playerTraceShowData);
followerMap.getOrDefault(player, Collections.emptySet()).forEach(follower -> {
trace.render(recordsToAdd, follower, playerTraceShowData);
});
});
}
protected Map<Player, PlayerTraceShowData> getTraceShowDataPlayerMapping(Region region) {
return showDataPerRegionPerPlayer.getOrDefault(region, new HashMap<>());
}
/**
* Removes the trace with the given id
*
* @param trace the trace to be removed
*/
public boolean remove(Trace trace) {
Map<Integer, Trace> traces = tracesByRegion.getOrDefault(trace.getRegion(), Collections.emptyMap());
Integer traceId = traces.entrySet().stream()
.filter(entry -> entry.getValue() == trace)
.map(Map.Entry::getKey)
.findFirst()
.orElse(null);
if (traceId == null) return false;
traces.remove(traceId);
trace.hide();
return true;
}
/**
* Clears all traces
*/
public void clear(Region region) {
showDataPerRegionPerPlayer.getOrDefault(region, new HashMap<>())
.keySet()
.forEach(player -> {
Set<Player> players = followerMap.getOrDefault(player, Collections.emptySet());
tracesByRegion.get(region).values().forEach(trace -> {
trace.hide(player);
players.forEach(trace::hide);
});
});
tracesByRegion.getOrDefault(region, new HashMap<>())
.forEach((i, trace) -> {
if (trace.getRegion() != region) return;
trace.getMetadataSaveFile().delete();
trace.getRecordsSaveFile().delete();
});
tracesByRegion.getOrDefault(region, new HashMap<>()).clear();
}
/**
* Methode to get all traces in a certain region
*
* @param region Region to look for traces in
* @return All traces recorded in the given Region
*/
public Collection<Trace> get(Region region) {
return tracesByRegion.getOrDefault(region, Collections.emptyMap()).values();
}
/**
* Methode to get the trace with specific id
*
* @param index index of the trace
* @return the trace with given id
*/
public Optional<Trace> get(int index) {
for (Map.Entry<Region, Map<Integer, Trace>> intermediate : tracesByRegion.entrySet()) {
if (intermediate.getValue().containsKey(index)) {
return Optional.ofNullable(intermediate.getValue().get(index));
}
}
return Optional.empty();
}
/**
* Methode to get all traces
*
* @return internal list of all current traces
*/
public Collection<Trace> getAll() {
return tracesByRegion.values().stream().map(Map::values).flatMap(Collection::stream).collect(Collectors.toList());
}
/**
* @return all ids of active traces
*/
public Set<Integer> getAllIds() {
return tracesByRegion.values().stream().map(Map::keySet).flatMap(Collection::stream).collect(Collectors.toSet());
}
/**
* Shows traces for the player of the current Region
*
* @param player
* @param playerTraceShowData
*/
public void show(Player player, PlayerTraceShowData playerTraceShowData) {
unfollow(player);
Region region = Region.getRegion(player.getLocation());
showDataPerRegionPerPlayer.computeIfAbsent(region, ignored -> new HashMap<>()).put(player, playerTraceShowData);
tracesByRegion.getOrDefault(region, Collections.emptyMap()).forEach((integer, trace) -> {
trace.render(player, playerTraceShowData);
followerMap.getOrDefault(player, Collections.emptySet()).forEach(follower -> {
trace.render(follower, playerTraceShowData);
});
});
}
/**
* Hides traces for the player of the current Region
*
* @param player
*/
public void hide(Player player) {
unfollow(player);
Region region = Region.getRegion(player.getLocation());
PlayerTraceShowData previous = showDataPerRegionPerPlayer.getOrDefault(region, Collections.emptyMap()).remove(player);
if (previous == null) return;
tracesByRegion.getOrDefault(region, Collections.emptyMap()).forEach((integer, trace) -> {
trace.hide(player);
followerMap.getOrDefault(player, Collections.emptySet()).forEach(trace::hide);
});
}
/**
* Makes the given player
*
* @param follower
* @param following
* @return
*/
public boolean follow(Player follower, Player following) {
if (followerMap.containsKey(follower)) return false;
if (followerMap.entrySet().stream().anyMatch(playerSetEntry -> playerSetEntry.getValue().contains(follower))) {
unfollow(follower);
}
followerMap.computeIfAbsent(following, ignored -> new HashSet<>()).add(follower);
showDataPerRegionPerPlayer.forEach((region, playerPlayerTraceShowDataMap) -> {
if (playerPlayerTraceShowDataMap.containsKey(follower)) {
tracesByRegion.getOrDefault(region, Collections.emptyMap()).forEach((integer, trace) -> trace.hide(follower));
}
PlayerTraceShowData playerTraceShowData = playerPlayerTraceShowDataMap.get(following);
if (playerTraceShowData == null) return;
tracesByRegion.getOrDefault(region, Collections.emptyMap()).forEach((integer, trace) -> {
trace.render(follower, playerTraceShowData);
});
});
return true;
}
public void unfollow(Player follower) {
if (followerMap.containsKey(follower)) return;
List<Player> toRemove = new ArrayList<>();
Set<Player> toHide = new HashSet<>();
followerMap.forEach((player, players) -> {
if (players.remove(follower)) toHide.add(follower);
if (players.isEmpty()) toRemove.add(player);
});
toRemove.forEach(followerMap::remove);
showDataPerRegionPerPlayer.forEach((region, playerPlayerTraceShowDataMap) -> {
toHide.forEach(player -> {
if (!playerPlayerTraceShowDataMap.containsKey(player)) return;
tracesByRegion.getOrDefault(region, Collections.emptyMap()).forEach((integer, trace) -> {
trace.hide(follower);
});
});
PlayerTraceShowData playerTraceShowData = playerPlayerTraceShowDataMap.get(follower);
if (playerTraceShowData == null) return;
tracesByRegion.getOrDefault(region, Collections.emptyMap()).forEach((integer, trace) -> {
trace.render(follower, playerTraceShowData);
});
});
}
/**
* Modifies the render for the given player, to only show tnts at the given time
* interval
*
* @param player
* @param from start of time interval
* @param to end of time interval
*/
public void renderAt(Player player, int from, int to) {
unfollow(player);
Region region = Region.getRegion(player.getLocation());
PlayerTraceShowData playerTraceShowData = showDataPerRegionPerPlayer
.computeIfAbsent(region, ignored -> new HashMap<>())
.computeIfAbsent(player, ignored -> new PlayerTraceShowData(BundleFilter.DEFAULT));
AtFlag atFlag = playerTraceShowData.getViewFlag(AtFlag.class);
if (atFlag == null) {
atFlag = new AtFlag(from, to);
playerTraceShowData.addViewFlag(atFlag);
} else {
atFlag.update(from, to);
}
tracesByRegion.getOrDefault(region, Collections.emptyMap()).forEach((integer, trace) -> {
trace.render(player, playerTraceShowData);
followerMap.getOrDefault(player, Collections.emptySet()).forEach(follower -> {
trace.render(follower, playerTraceShowData);
});
});
}
/**
* Toggles the isolated render for the given records and player
*
* @param player the player the trace is shown to
* @param records the record for which isolation is toggled
*/
public void isolate(Player player, TNTPoint... records) {
unfollow(player);
Region region = Region.getRegion(player.getLocation());
PlayerTraceShowData playerTraceShowData = showDataPerRegionPerPlayer
.computeIfAbsent(region, ignored -> new HashMap<>())
.computeIfAbsent(player, ignored -> new PlayerTraceShowData(BundleFilter.DEFAULT));
IsolateFlag isolateFlag;
if (playerTraceShowData.hasViewFlagOnly(IsolateFlag.class)) {
isolateFlag = playerTraceShowData.getViewFlag(IsolateFlag.class);
} else if (playerTraceShowData.hasNoViewFlags()) {
isolateFlag = new IsolateFlag();
playerTraceShowData.addViewFlag(isolateFlag);
} else {
playerTraceShowData = new PlayerTraceShowData(BundleFilter.DEFAULT);
isolateFlag = new IsolateFlag();
playerTraceShowData.addViewFlag(isolateFlag);
showDataPerRegionPerPlayer.get(region).put(player, playerTraceShowData);
}
for (TNTPoint record : records) {
isolateFlag.toggleId(record.getTntId());
}
PlayerTraceShowData finalPlayerTraceShowData = playerTraceShowData;
tracesByRegion.getOrDefault(region, Collections.emptyMap()).forEach((integer, trace) -> {
trace.render(player, finalPlayerTraceShowData);
followerMap.getOrDefault(player, Collections.emptySet()).forEach(follower -> {
trace.render(follower, finalPlayerTraceShowData);
});
});
}
@EventHandler
public void onPlayerQuit(PlayerQuitEvent event) {
unfollow(event.getPlayer());
new ArrayList<>(followerMap.getOrDefault(event.getPlayer(), Collections.emptySet())).forEach(this::unfollow);
showDataPerRegionPerPlayer.forEach((region, playerPlayerTraceShowDataMap) -> {
playerPlayerTraceShowDataMap.remove(event.getPlayer());
});
tracesByRegion.forEach((region, integerTraceMap) -> {
integerTraceMap.forEach((integer, trace) -> {
trace.hide(event.getPlayer());
});
});
}
}

Datei anzeigen

@ -0,0 +1,239 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.tracer;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.features.tpslimit.TPSUtils;
import de.steamwar.bausystem.region.Region;
import de.steamwar.linkage.Linked;
import org.bukkit.block.Block;
import org.bukkit.entity.TNTPrimed;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityExplodeEvent;
import org.bukkit.event.entity.EntitySpawnEvent;
import java.util.*;
@Linked
public class TraceRecorder implements Listener {
public static TraceRecorder instance;
{
instance = this;
}
/**
* Map for all traces being actively recorded
*/
private final Map<Region, TraceRecordingWrapper> activeTraces = new HashMap<>();
/**
* Map for all TNTs being traced, by region
*/
private final Map<Region, List<TNTPrimed>> trackedTNT = new HashMap<>();
/**
* Map from TNT to Region the TNT spawned in
*/
private final Map<TNTPrimed, Region> tntSpawnRegion = new HashMap<>();
/**
* Maps a tracked tnt entity to its entire recording history
*/
private final Map<TNTPrimed, List<TNTPoint>> historyMap = new HashMap<>();
/**
* Regions where auto-trace is enabled
*/
private final Set<Region> autoTraceRegions = new HashSet<>();
public TraceRecorder() {
BauSystem.runTaskTimer(BauSystem.getInstance(), () -> {
record();
checkForAutoTraceFinish();
}, 0, 1);
}
/**
* Toggles auto trace for the given region
*
* @param region
*/
public boolean toggleAutoTrace(Region region) {
if (!autoTraceRegions.remove(region)) {
autoTraceRegions.add(region);
return true;
} else {
return false;
}
}
/**
* Makes checks for whether auto traces finished
*/
public void checkForAutoTraceFinish() {
for (Region region : autoTraceRegions) {
if (autoTraceRegions.contains(region) && trackedTNT.getOrDefault(region, Collections.emptyList()).size() == 0) {
stopRecording(region);
}
}
}
/**
* Starts a recording at the given region
*
* @param region region to be recorded
*/
public int startRecording(Region region) {
if (activeTraces.containsKey(region)) {
return -1;
}
TraceRecordingWrapper wrappedTrace = new TraceRecordingWrapper(region);
activeTraces.put(region, wrappedTrace);
return TraceManager.instance.add(wrappedTrace.getTrace());
}
/**
* Stops the recording at the given region
*
* @param region region to stop recording
*/
public void stopRecording(Region region) {
TraceRecordingWrapper wrappedTrace = activeTraces.getOrDefault(region, null);
if (wrappedTrace == null) return;
wrappedTrace.finalizeRecording();
activeTraces.remove(region);
for (TNTPrimed tnt : trackedTNT.getOrDefault(region, Collections.emptyList())) {
historyMap.remove(tnt);
}
trackedTNT.put(region, new ArrayList<>());
}
/**
* Internal methode to record all tracked TNT Entities
*/
private void record() {
for (Region region : activeTraces.keySet()) {
TraceRecordingWrapper wrappedTrace = activeTraces.get(region);
for (TNTPrimed tnt : trackedTNT.getOrDefault(region, Collections.emptyList())) {
TNTPoint record = record(tnt, wrappedTrace, Collections.emptyList());
wrappedTrace.addRecord(record);
}
wrappedTrace.commitRecorded();
}
}
/**
* Internal methode to record exploded tnt
*
* @param tntPrimed tnt exploding
* @param wrappedTrace the trace to record the tnt for wrapped with metadata
* @param destroyedBlocks the blocks destoryed by the passed tnt
* @return the record creaded of the passed tnt
*/
private TNTPoint record(TNTPrimed tntPrimed, TraceRecordingWrapper wrappedTrace, List<Block> destroyedBlocks) {
List<TNTPoint> history = historyMap.getOrDefault(tntPrimed, new ArrayList<>());
int tntID;
if (history.size() == 0) {
historyMap.put(tntPrimed, history);
tntID = wrappedTrace.getNextOpenRecordIdAndIncrement();
} else {
tntID = history.get(0).getTntId();
}
boolean isExplosion = tntPrimed.getFuseTicks() == 0;
if (isExplosion) {
wrappedTrace.activateExplosionRecorded();
}
boolean afterFirstExplosion = wrappedTrace.isExplosionRecorded();
TNTPoint record = new TNTPoint(tntID, tntPrimed, isExplosion, afterFirstExplosion, TPSUtils.currentTick.get() - wrappedTrace.getStartTick(), history, destroyedBlocks);
history.add(record);
return record;
}
public boolean isAutoTraceEnabledInRegion(Region region) {
return autoTraceRegions.contains(region);
}
public boolean isTraceActiveInRegion(Region region) {
return activeTraces.containsKey(region);
}
public long getStartTimeOfTraceInRegion(Region region) {
TraceRecordingWrapper wrapper = activeTraces.get(region);
if (wrapper == null) return 0;
return wrapper.getStartTick();
}
/**
* Event for TNTs beeing spawn.
* Registers newly spawned TNT to be traced if reqired
*
* @param event
*/
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void onTNTSpawn(EntitySpawnEvent event) {
if (!(event.getEntity() instanceof TNTPrimed)) return;
Region region = Region.getRegion(event.getLocation());
if (autoTraceRegions.contains(region) && !activeTraces.containsKey(region)) {
startRecording(region);
}
if (activeTraces.containsKey(region)) {
// Check whether set for tracking already exists. Creating it if necessary
if (!trackedTNT.containsKey(region)) {
trackedTNT.put(region, new ArrayList<>());
}
trackedTNT.get(region).add((TNTPrimed) event.getEntity());
tntSpawnRegion.put((TNTPrimed) event.getEntity(), region);
activeTraces.get(region).addRecord(record((TNTPrimed) event.getEntity(), activeTraces.get(region), Collections.emptyList()));
}
}
/**
* Event for TNTs exploding
* Unregisters TNTs from beeing traced on explode
*
* @param event
*/
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onTNTExplode(EntityExplodeEvent event) {
if (!(event.getEntity() instanceof TNTPrimed)) return;
Region region = tntSpawnRegion.getOrDefault((TNTPrimed) event.getEntity(), null);
if (region == null) return;
trackedTNT.get(region).remove((TNTPrimed) event.getEntity());
tntSpawnRegion.remove((TNTPrimed) event.getEntity());
activeTraces.get(region).addRecord(record((TNTPrimed) event.getEntity(), activeTraces.get(region), event.blockList()));
}
}

Datei anzeigen

@ -0,0 +1,98 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2024 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.tracer;
import de.steamwar.bausystem.features.tpslimit.TPSUtils;
import de.steamwar.bausystem.region.Region;
import lombok.Getter;
import lombok.SneakyThrows;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.GZIPOutputStream;
public class TraceRecordingWrapper {
@Getter
private final long startTick;
private final List<TNTPoint> recordsToAdd;
private final List<TNTPoint> recordList;
private final ObjectOutputStream recordsOutputStream;
private int nextOpenRecordId = 0;
@Getter
private boolean explosionRecorded = false;
@Getter
private final Trace trace;
@SneakyThrows
public TraceRecordingWrapper(Region region) {
startTick = TPSUtils.currentRealTick.get();
recordsToAdd = new ArrayList<>();
recordList = new ArrayList<>();
trace = new Trace(region, recordList);
TraceManager.instance.add(trace);
File recordsSaveFile = new File(TraceManager.tracesFolder, trace.getUuid() + ".records");
recordsOutputStream = new ObjectOutputStream(new GZIPOutputStream(new FileOutputStream(recordsSaveFile)));
}
public int getNextOpenRecordIdAndIncrement() {
return nextOpenRecordId++;
}
public void activateExplosionRecorded() {
explosionRecorded = true;
}
public void addRecord(TNTPoint record) {
recordsToAdd.add(record);
}
public void commitRecorded() {
TraceManager.instance.showPartial(trace, recordsToAdd);
recordsToAdd.forEach(record -> {
try {
recordsOutputStream.writeObject(record);
recordsOutputStream.flush();
} catch (IOException e) {
e.printStackTrace();
}
});
recordList.addAll(recordsToAdd);
recordsToAdd.clear();
}
@SneakyThrows
protected void finalizeRecording() {
recordsOutputStream.flush();
recordsOutputStream.close();
if (trace.getRecords().isEmpty()) {
TraceManager.instance.remove(trace);
}
}
}

Datei anzeigen

@ -1,7 +1,7 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 SteamWar.de-Serverteam
* Copyright (C) 2024 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
@ -20,15 +20,14 @@
package de.steamwar.bausystem.features.tracer;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.features.tracer.record.Recorder;
import de.steamwar.bausystem.features.tracer.show.Record;
import de.steamwar.bausystem.features.tracer.show.StoredRecords;
import de.steamwar.bausystem.Permission;
import de.steamwar.bausystem.features.tpslimit.TPSUtils;
import de.steamwar.bausystem.region.Region;
import de.steamwar.bausystem.utils.ScoreboardElement;
import de.steamwar.linkage.Linked;
import org.bukkit.entity.Player;
import java.util.List;
import java.util.Collection;
@Linked
public class TraceScoreboardElement implements ScoreboardElement {
@ -45,17 +44,18 @@ public class TraceScoreboardElement implements ScoreboardElement {
@Override
public String get(Region region, Player p) {
String traceScore = Recorder.INSTANCE.get(region).scoreboard(p);
if (traceScore != null) {
return "§e" + BauSystem.MESSAGE.parse("SCOREBOARD_TRACE", p) + "§8: " + traceScore;
if (!Permission.BUILD.hasPermission(p)) return null;
if (TraceRecorder.instance.isTraceActiveInRegion(region)) {
return "§e" + BauSystem.MESSAGE.parse("SCOREBOARD_TRACE", p) + "§8: " + BauSystem.MESSAGE.parse("TRACE_RECORD", p) + " §8| §e" + (TPSUtils.currentRealTick.get() - TraceRecorder.instance.getStartTimeOfTraceInRegion(region)) + " §7" + BauSystem.MESSAGE.parse("SCOREBOARD_TRACE_TICKS", p);
} else if (TraceRecorder.instance.isAutoTraceEnabledInRegion(region)) {
return "§e" + BauSystem.MESSAGE.parse("SCOREBOARD_TRACE", p) + "§8: " + BauSystem.MESSAGE.parse("TRACE_IDLE_AUTO", p);
}
List<Record> records = StoredRecords.getRecords(region);
if (records.isEmpty()) {
Collection<Trace> traces = TraceManager.instance.get(region);
if (traces.isEmpty()) {
return null;
}
if (records.stream().allMatch(record -> record.getTnt().isEmpty())) {
return null;
}
} else {
return "§e" + BauSystem.MESSAGE.parse("SCOREBOARD_TRACE", p) + "§8: " + BauSystem.MESSAGE.parse("TRACE_HAS_TRACES", p);
}
}
}

Datei anzeigen

@ -1,101 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.tracer;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.Permission;
import de.steamwar.bausystem.SWUtils;
import de.steamwar.bausystem.features.tracer.record.*;
import de.steamwar.bausystem.linkage.specific.BauGuiItem;
import de.steamwar.bausystem.region.Region;
import de.steamwar.inventory.SWInventory;
import de.steamwar.inventory.SWItem;
import de.steamwar.linkage.Linked;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack;
import java.util.Arrays;
import java.util.Collections;
@Linked
public class TracerBauGuiItem extends BauGuiItem {
public TracerBauGuiItem() {
super(21);
}
@Override
public ItemStack getItem(Player player) {
Region region = Region.getRegion(player.getLocation());
return SWUtils.setCustomModelData(new SWItem(Material.OBSERVER, BauSystem.MESSAGE.parse("TRACE_GUI_ITEM_NAME", player), Arrays.asList(BauSystem.MESSAGE.parse("TRACE_GUI_ITEM_LORE", player, Recorder.INSTANCE.get(region).scoreboard(player))), false, clickType -> {
}), 1).getItemStack();
}
private static void open(Player p) {
Region region = Region.getRegion(p.getLocation());
TraceRecorder traceRecorder = Recorder.INSTANCE.get(region);
SWInventory inv = new SWInventory(p, 9, BauSystem.MESSAGE.parse("TRACE_GUI_NAME", p));
if (traceRecorder instanceof ActiveTracer) {
if (traceRecorder instanceof AutoTraceRecorder) {
inv.setItem(1, new SWItem(Material.GRAY_DYE, BauSystem.MESSAGE.parse("TRACE_GUI_TRACE_ACTIVE_AUTO", p)));
} else {
inv.setItem(1, new SWItem(Material.GREEN_DYE, BauSystem.MESSAGE.parse("TRACE_GUI_TRACE_ACTIVE", p), clickType -> {
p.performCommand("trace stop");
open(p);
}));
}
} else {
inv.setItem(1, new SWItem(Material.RED_DYE, BauSystem.MESSAGE.parse("TRACE_GUI_TRACE_INACTIVE", p), clickType -> {
p.performCommand("trace start");
open(p);
}));
}
if (traceRecorder instanceof AutoTraceRecorder) {
inv.setItem(3, new SWItem(Material.ENDER_EYE, BauSystem.MESSAGE.parse("TRACE_GUI_AUTO_TRACE_ACTIVE", p), clickType -> {
p.performCommand("trace auto");
open(p);
}));
} else {
inv.setItem(3, new SWItem(Material.FIREWORK_STAR, BauSystem.MESSAGE.parse("TRACE_GUI_AUTO_TRACE_INACTIVE", p), clickType -> {
p.performCommand("trace auto");
open(p);
}));
}
inv.setItem(7, new SWItem(Material.BARRIER, BauSystem.MESSAGE.parse("TRACE_GUI_DELETE", p), clickType -> {
p.performCommand("trace delete");
open(p);
}));
inv.open();
}
@Override
public boolean click(ClickType click, Player p) {
open(p);
return false;
}
@Override
public Permission permission() {
return Permission.BUILD;
}
}

Datei anzeigen

@ -1,23 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.tracer.record;
public interface ActiveTracer {
}

Datei anzeigen

@ -1,38 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.tracer.record;
public class AutoExplodeTraceRecorder extends AutoTraceRecorder {
@Override
protected String getInactivityMessage() {
return "TRACE_IDLE_AUTO_EXPLODE";
}
@Override
protected boolean shouldStartRecording(StartType startType) {
return startType == StartType.EXPLODE;
}
@Override
protected String getScriptState() {
return "IDLE_AUTO_EXPLODE";
}
}

Datei anzeigen

@ -1,38 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.tracer.record;
public class AutoIgniteTraceRecorder extends AutoTraceRecorder implements ActiveTracer {
@Override
protected String getInactivityMessage() {
return "TRACE_IDLE_AUTO_IGNITE";
}
@Override
protected boolean shouldStartRecording(StartType startType) {
return startType == StartType.IGNITE;
}
@Override
protected String getScriptState() {
return "IDLE_AUTO_IGNITE";
}
}

Datei anzeigen

@ -1,154 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.tracer.record;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.features.tpslimit.TPSUtils;
import de.steamwar.bausystem.features.tracer.show.Record;
import de.steamwar.bausystem.features.tracer.show.StoredRecords;
import de.steamwar.bausystem.features.tracer.show.TraceShowManager;
import de.steamwar.bausystem.region.Region;
import lombok.Getter;
import lombok.Setter;
import org.bukkit.entity.Player;
import org.bukkit.entity.TNTPrimed;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;
public abstract class AutoTraceRecorder implements TraceRecorder {
protected boolean recording = false;
private long startTime = TPSUtils.currentRealTick.get();
private long lastExplosion = 0;
private final Map<TNTPrimed, Record.TNTRecord> recordMap = new HashMap<>();
private Record record;
private Region region;
private Supplier<Record> recordSupplier;
@Setter
@Getter
private TraceRecordAutoDeletion traceRecordAutoDeletion = TraceRecordAutoDeletion.NEVER;
private Record lastRecord;
private Record.TNTRecord getRecord(TNTPrimed tntPrimed) {
return recordMap.computeIfAbsent(tntPrimed, __ -> record.spawn());
}
protected abstract String getInactivityMessage();
protected abstract boolean shouldStartRecording(StartType startType);
protected void stoppedRecording() {
}
@Override
public final String scoreboard(Player player) {
if (recording) {
return BauSystem.MESSAGE.parse("TRACE_RECORD", player) + " §8| §e" + (TPSUtils.currentRealTick.get() - startTime) + " §7" + BauSystem.MESSAGE.parse("SCOREBOARD_TRACE_TICKS", player);
} else {
return BauSystem.MESSAGE.parse(getInactivityMessage(), player);
}
}
private void startRecording() {
if (lastRecord != null && traceRecordAutoDeletion.test(lastRecord)) {
StoredRecords.remove(region, lastRecord);
TraceShowManager.reshow(region);
}
lastExplosion = 0;
startTime = TPSUtils.currentRealTick.get();
record = recordSupplier.get();
recording = true;
}
@Override
public void init(Region region, Supplier<Record> recordSupplier) {
this.region = region;
this.recordSupplier = recordSupplier;
}
@Override
public void postClear() {
recordMap.clear();
record = recordSupplier.get();
}
@Override
public final void spawn(TNTPrimed tntPrimed) {
if (!recording && shouldStartRecording(StartType.IGNITE)) {
startRecording();
}
if (recording) {
getRecord(tntPrimed).source(tntPrimed);
}
}
@Override
public final void tick(TNTPrimed tntPrimed) {
if (recording) {
getRecord(tntPrimed).location(tntPrimed);
}
}
@Override
public final void explode(TNTPrimed tntPrimed, boolean inBuildRegion, boolean inTestblockRegion) {
if (!recording && shouldStartRecording(StartType.EXPLODE)) {
startRecording();
}
if (recording) {
Record.TNTRecord tntRecord = getRecord(tntPrimed);
if (inBuildRegion) tntRecord.setInBuildArea(true);
if (inTestblockRegion) tntRecord.setInTestblockArea(true);
tntRecord.explode(tntPrimed);
}
lastExplosion = 0;
}
@Override
public final void tick() {
lastExplosion++;
if (recording && lastExplosion > 80) {
recording = false;
recordMap.clear();
lastRecord = record;
record = null;
stoppedRecording();
}
}
protected enum StartType {
IGNITE,
EXPLODE
}
protected abstract String getScriptState();
@Override
public String scriptState() {
return recording ? "RECORDING" : getScriptState();
}
@Override
public long scriptTime() {
return TPSUtils.currentRealTick.get() - startTime;
}
}

Datei anzeigen

@ -1,160 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.tracer.record;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.features.tracer.show.Record;
import de.steamwar.bausystem.features.tracer.show.StoredRecords;
import de.steamwar.bausystem.region.Region;
import de.steamwar.bausystem.region.utils.RegionExtensionType;
import de.steamwar.bausystem.region.utils.RegionType;
import de.steamwar.linkage.Linked;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.entity.TNTPrimed;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityExplodeEvent;
import org.bukkit.event.entity.EntitySpawnEvent;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
@Linked
public class Recorder implements Listener {
public static Recorder INSTANCE;
{
INSTANCE = this;
}
private static class DisabledTracerRecorder implements TraceRecorder {
@Override
public String scoreboard(Player player) {
return null;
}
@Override
public void spawn(TNTPrimed tntPrimed) {
}
@Override
public void tick(TNTPrimed tntPrimed) {
}
@Override
public void explode(TNTPrimed tntPrimed, boolean inBuildArea, boolean inTestblockRegion) {
}
@Override
public String scriptState() {
return "IDLE";
}
@Override
public long scriptTime() {
return 0;
}
}
private static final DisabledTracerRecorder DISABLED = new DisabledTracerRecorder();
private Map<Region, TraceRecorder> regionTraceRecorderMap = new HashMap<>();
private Map<TNTPrimed, Region> tntTraceRecorderMap = new HashMap<>();
private TraceRecorder get(TNTPrimed tntPrimed) {
return get(tntTraceRecorderMap.computeIfAbsent(tntPrimed, e -> Region.getRegion(e.getLocation())));
}
public boolean isDisabled(Region region) {
return !regionTraceRecorderMap.containsKey(region);
}
public TraceRecorder get(Region region) {
return regionTraceRecorderMap.getOrDefault(region, DISABLED);
}
public void set(Region region, TraceRecorder traceRecorder) {
regionTraceRecorderMap.put(region, traceRecorder);
traceRecorder.init(region, () -> {
Record record = new Record(region);
StoredRecords.add(region, record);
return record;
});
tntTraceRecorderMap.forEach((tntPrimed, rg) -> {
if (rg == region) {
traceRecorder.spawn(tntPrimed);
}
});
}
public void remove(Region region) {
regionTraceRecorderMap.remove(region);
}
public void postClear(Region region) {
get(region).postClear();
}
@EventHandler
public void onEntitySpawn(EntitySpawnEvent event) {
Entity entity = event.getEntity();
if (!(entity instanceof TNTPrimed)) {
return;
}
get((TNTPrimed) entity).spawn((TNTPrimed) entity);
}
{
BauSystem.runTaskTimer(BauSystem.getInstance(), () -> {
tick();
tntTraceRecorderMap.keySet()
.stream()
.filter(e -> !e.isValid())
.collect(Collectors.toList())
.forEach(tntTraceRecorderMap::remove);
new ArrayList<>(regionTraceRecorderMap.values()).forEach(TraceRecorder::tick);
}, 1, 1);
}
private void tick() {
TNTPrimedIterator.impl.iterator().forEach(tntPrimed -> {
get(tntPrimed).tick(tntPrimed);
});
}
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void onEntityExplode(EntityExplodeEvent event) {
Entity entity = event.getEntity();
if (!(entity instanceof TNTPrimed)) {
return;
}
TraceRecorder traceRecorder = get((TNTPrimed) entity);
Region region = tntTraceRecorderMap.get((TNTPrimed) entity);
boolean inBuildRegion = event.blockList().stream().anyMatch(block -> region.inRegion(block.getLocation(), RegionType.BUILD, RegionExtensionType.EXTENSION));
boolean inTestblockRegion = event.blockList().stream().anyMatch(block -> region.inRegion(block.getLocation(), RegionType.TESTBLOCK, RegionExtensionType.EXTENSION));
traceRecorder.explode((TNTPrimed) entity, inBuildRegion, inTestblockRegion);
tntTraceRecorderMap.remove(entity);
tick();
}
}

Datei anzeigen

@ -1,86 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.tracer.record;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.features.tpslimit.TPSUtils;
import de.steamwar.bausystem.features.tracer.show.Record;
import de.steamwar.bausystem.region.Region;
import org.bukkit.entity.Player;
import org.bukkit.entity.TNTPrimed;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;
public class SimpleTraceRecorder implements TraceRecorder, ActiveTracer {
private final long startTime = TPSUtils.currentRealTick.get();
private final Map<TNTPrimed, Record.TNTRecord> recordMap = new HashMap<>();
private Record record;
@Override
public String scoreboard(Player player) {
return BauSystem.MESSAGE.parse("TRACE_RECORD", player) + " §8| §e" + (TPSUtils.currentRealTick.get() - startTime) + " §7" + BauSystem.MESSAGE.parse("SCOREBOARD_TRACE_TICKS", player);
}
@Override
public void init(Region region, Supplier<Record> recordSupplier) {
record = recordSupplier.get();
}
@Override
public void postClear() {
recordMap.clear();
}
private Record.TNTRecord getRecord(TNTPrimed tntPrimed) {
return recordMap.computeIfAbsent(tntPrimed, __ -> record.spawn());
}
@Override
public void spawn(TNTPrimed tntPrimed) {
getRecord(tntPrimed).source(tntPrimed);
}
@Override
public void tick(TNTPrimed tntPrimed) {
getRecord(tntPrimed).location(tntPrimed);
}
@Override
public void explode(TNTPrimed tntPrimed, boolean inBuildRegion, boolean inTestblockRegion) {
Record.TNTRecord tntRecord = getRecord(tntPrimed);
if (inBuildRegion) tntRecord.setInBuildArea(true);
if (inTestblockRegion) tntRecord.setInTestblockArea(true);
tntRecord.explode(tntPrimed);
recordMap.remove(tntPrimed);
}
@Override
public String scriptState() {
return "RECORD";
}
@Override
public long scriptTime() {
return TPSUtils.currentRealTick.get() - startTime;
}
}

Datei anzeigen

@ -1,51 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.tracer.record;
import de.steamwar.bausystem.region.Region;
public class SingleTraceRecorder extends AutoTraceRecorder {
private Region region;
public SingleTraceRecorder(Region region) {
this.region = region;
}
@Override
protected String getInactivityMessage() {
return "TRACE_IDLE_SINGLE";
}
@Override
protected boolean shouldStartRecording(StartType startType) {
return startType == StartType.IGNITE;
}
@Override
protected void stoppedRecording() {
Recorder.INSTANCE.remove(region);
}
@Override
protected String getScriptState() {
return "IDLE_SINGLE";
}
}

Datei anzeigen

@ -1,32 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.tracer.record;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.core.VersionDependent;
import org.bukkit.entity.TNTPrimed;
import java.util.stream.Stream;
public interface TNTPrimedIterator {
TNTPrimedIterator impl = VersionDependent.getVersionImpl(BauSystem.getInstance());
Stream<TNTPrimed> iterator();
}

Datei anzeigen

@ -1,65 +0,0 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.tracer.record;
import de.steamwar.bausystem.features.tracer.show.Record;
public enum TraceRecordAutoDeletion {
ALWAYS {
@Override
public boolean test(Record record) {
return true;
}
},
NEVER {
@Override
public boolean test(Record record) {
return false;
}
},
NO_BUILD_DESTROY {
@Override
public boolean test(Record record) {
return record.getTnt().stream().noneMatch(Record.TNTRecord::isInBuildArea);
}
},
BUILD_DESTROY {
@Override
public boolean test(Record record) {
return record.getTnt().stream().anyMatch(Record.TNTRecord::isInBuildArea);
}
},
NO_TESTBLOCK_DESTROY {
@Override
public boolean test(Record record) {
return record.getTnt().stream().noneMatch(Record.TNTRecord::isInTestblockArea);
}
},
TESTBLOCK_DESTROY {
@Override
public boolean test(Record record) {
return record.getTnt().stream().anyMatch(Record.TNTRecord::isInTestblockArea);
}
},
;
public abstract boolean test(Record record);
}

Datei anzeigen

@ -1,44 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.tracer.record;
import de.steamwar.bausystem.features.tracer.show.Record;
import de.steamwar.bausystem.region.Region;
import org.bukkit.entity.Player;
import org.bukkit.entity.TNTPrimed;
import java.util.function.Supplier;
public interface TraceRecorder {
String scoreboard(Player player);
default void init(Region region, Supplier<Record> recordSupplier) {
}
default void postClear() {
}
void spawn(TNTPrimed tntPrimed);
void tick(TNTPrimed tntPrimed);
void explode(TNTPrimed tntPrimed, boolean inBuildRegion, boolean inTestblockRegion);
default void tick() {
}
String scriptState();
long scriptTime();
}

Datei anzeigen

@ -0,0 +1,69 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2024 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.tracer.rendering;
import de.steamwar.bausystem.features.tracer.TNTPoint;
import lombok.RequiredArgsConstructor;
import java.util.function.BiFunction;
/**
* A Comparator for determining whether two records should be bundled
*/
@RequiredArgsConstructor
public enum BundleFilter {
LOOSE((TNTPoint a, TNTPoint b) -> {
if (a.isExplosion() != b.isExplosion()) return false;
if (a.getLocation().distanceSquared(b.getLocation()) > BundleFilter.pixelSizeSquared * 8) return false;
if (a.getVelocity().distanceSquared(b.getVelocity()) > BundleFilter.pixelSizeSquared * 8) return false;
return true;
}),
DEFAULT((TNTPoint a, TNTPoint b) -> {
if (a.isExplosion() != b.isExplosion()) return false;
if (a.getTicksSinceStart() != b.getTicksSinceStart()) return null;
if (a.getLocation().distanceSquared(b.getLocation()) > BundleFilter.pixelSizeSquared) return false;
if (a.getVelocity().distanceSquared(b.getVelocity()) > BundleFilter.pixelSizeSquared) return false;
return true;
}),
RAW((TNTPoint a, TNTPoint b) -> {
if (a.isExplosion() != b.isExplosion()) return false;
if (!a.getLocation().equals(b.getLocation())) return false;
if (!a.getVelocity().equals(b.getVelocity())) return false;
if (a.getTicksSinceStart() != b.getTicksSinceStart()) return null;
return true;
}),
NONE((TNTPoint a, TNTPoint b) -> {
return null;
});
/**
* {@code null}: Bundling can be stopped from this point forward
* {@code false}: No bundling allowed
* {@code true}: Bundling should be applied
*/
public final BiFunction<TNTPoint, TNTPoint, Boolean> function;
private static final double pixelSize = 0.0625;
private static final double pixelSizeSquared = pixelSize * pixelSize;
}

Datei anzeigen

@ -0,0 +1,98 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2024 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.tracer.rendering;
import lombok.Getter;
import lombok.Setter;
import java.util.*;
/**
* A holder for the view data of a player trace render
*/
public class PlayerTraceShowData {
/**
* The bundle filter applied by this class
*/
@Getter
@Setter
private BundleFilter bundleFilter;
/**
* A map for stating whether a flag is contained in this holder or not
*/
private final Map<Class<? extends ViewFlag>, ViewFlag> viewFlags = new HashMap<>();
public PlayerTraceShowData(BundleFilter bundleFilter, ViewFlag... viewFlags) {
this.bundleFilter = bundleFilter;
for (ViewFlag viewFlag : viewFlags) {
this.viewFlags.put(viewFlag.getClass(), viewFlag);
}
}
/**
* A methode that returns the flags that should be used by renders according
* to this holder. Especially handles inverse and required flags
*
* @return the flags that should be used in a render according to this holder
*/
public Set<ViewFlag> getEffectiveViewFlags() {
// Manage flags and required flags
Set<ViewFlag> flagList = new HashSet<>();
for (ViewFlag flag : viewFlags.values()) {
flagList.add(flag);
if (flag.required != null) {
flagList.addAll(Arrays.asList(flag.required));
}
}
// Manage inverse flags
ViewFlag.inverseFlags.forEach(viewFlag -> {
if (!flagList.remove(viewFlag)) {
flagList.add(viewFlag);
}
});
return flagList;
}
public boolean hasNoViewFlags() {
return viewFlags.isEmpty();
}
public boolean hasViewFlag(Class<? extends ViewFlag> clazz) {
return viewFlags.containsKey(clazz);
}
public boolean hasViewFlagOnly(Class<? extends ViewFlag> clazz) {
return viewFlags.containsKey(clazz) && viewFlags.size() == 1;
}
// TODO ?
@SuppressWarnings("unchecked")
public <T extends ViewFlag> T getViewFlag(Class<T> clazz) {
return (T) viewFlags.get(clazz);
}
public void addViewFlag(ViewFlag viewFlag) {
viewFlags.put(viewFlag.getClass(), viewFlag);
}
}

Datei anzeigen

@ -0,0 +1,95 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2024 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.tracer.rendering;
import com.comphenix.tinyprotocol.Reflection;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.features.tracer.TNTPoint;
import de.steamwar.bausystem.features.tracer.Trace;
import de.steamwar.bausystem.features.tracer.TraceManager;
import de.steamwar.core.Core;
import de.steamwar.entity.REntity;
import de.steamwar.entity.REntityServer;
import de.steamwar.techhider.BlockIds;
import lombok.Getter;
import net.md_5.bungee.api.chat.ClickEvent;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import java.util.List;
import java.util.stream.Collectors;
/**
* Wrapper for the rendering of a record bundle
*/
public class TraceEntity extends REntity {
private static final Reflection.MethodInvoker addEntityMethod = Reflection.getMethod(REntityServer.class, "addEntity", REntity.class);
/**
* The records represented by this REntity
*/
@Getter
private final List<TNTPoint> records;
/**
* A string of all unique tnt records
*/
private final String uniqueTntIdsString;
private final Trace trace;
public TraceEntity(REntityServer server, Location location, boolean isExplosion, List<TNTPoint> records, Trace trace) {
super(server, EntityType.FALLING_BLOCK, location, BlockIds.impl.materialToId(isExplosion ? Material.RED_STAINED_GLASS : Material.TNT) >> (Core.getVersion() <= 12 ? 4 : 0));
setNoGravity(true);
this.records = records;
uniqueTntIdsString = records.stream().map(TNTPoint::getTntId).distinct().map(Object::toString).collect(Collectors.joining(" "));
this.trace = trace;
addEntityMethod.invoke(server, this);
}
/**
* Message for printing the data contained in this wrapper into player chat
*
* @param player the player the message should be printed for
*/
public void printIntoChat(Player player) {
TNTPoint representative = records.get(0);
BauSystem.MESSAGE.sendPrefixless("TNT_CLICK_HEADER", player);
BauSystem.MESSAGE.sendPrefixless("TNT_CLICK_FUSE_TIME", player, representative.getFuse());
BauSystem.MESSAGE.sendPrefixless("TNT_CLICK_POSITION_X", player, representative.getLocation().getX() + "");
BauSystem.MESSAGE.sendPrefixless("TNT_CLICK_POSITION_Y", player, representative.getLocation().getY() + "");
BauSystem.MESSAGE.sendPrefixless("TNT_CLICK_POSITION_Z", player, representative.getLocation().getZ() + "");
BauSystem.MESSAGE.sendPrefixless("TNT_CLICK_VELOCITY_X", player, representative.getVelocity().getX() + "");
BauSystem.MESSAGE.sendPrefixless("TNT_CLICK_VELOCITY_Y", player, representative.getVelocity().getY() + "");
BauSystem.MESSAGE.sendPrefixless("TNT_CLICK_VELOCITY_Z", player, representative.getVelocity().getZ() + "");
BauSystem.MESSAGE.sendPrefixless("TNT_CLICK_ISOLATE", player, BauSystem.MESSAGE.parse("TRACE_MESSAGE_CLICK_ISOLATE", player), new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/trace isolate " + TraceManager.instance.getId(trace) + " " + uniqueTntIdsString));
}
@Override
public boolean equals(Object object) {
if (!(object instanceof TraceEntity)) return false;
TraceEntity entity = (TraceEntity) object;
return records.get(0).equals(entity.getRecords().get(0));
}
}

Datei anzeigen

@ -0,0 +1,247 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2024 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.tracer.rendering;
import de.steamwar.bausystem.features.tracer.TNTPoint;
import de.steamwar.entity.REntityServer;
import de.steamwar.entity.RFallingBlockEntity;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.util.Vector;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* A settable flag that changes how a trace is rendered
*/
public abstract class ViewFlag {
/**
* Static registry of static flags
*/
public static final List<ViewFlag> flags = new ArrayList<>();
/**
* Inverse flags are used by trace render by default, as long as they are not explicitly added as argument
*/
public static final List<ViewFlag> inverseFlags = new ArrayList<>();
public static ViewFlag EXPLOSION = new ViewFlag(true, false, "explosion", "e") {
@Override
public Stream<TNTPoint> filter(Stream<TNTPoint> records) {
return records.filter(TNTPoint::isExplosion);
}
};
public static ViewFlag IGNITE = new ViewFlag(true, true, "ignite", "i") {
@Override
public Stream<TNTPoint> filter(Stream<TNTPoint> records) {
return records.filter(record -> record.isAfterFirstExplosion());
}
};
public static ViewFlag SOURCE = new ViewFlag(true, false, IGNITE, "source", "s") {
@Override
public Stream<TNTPoint> filter(Stream<TNTPoint> records) {
return records.filter(record -> record.getFuse() == 80);
}
};
public static ViewFlag BUILD_DESTROY_ONLY = new ViewFlag(true, false, "build-destroy-only") {
@Override
public Stream<TNTPoint> filter(Stream<TNTPoint> records) {
return records.filter(record -> record.getHistory().get(record.getHistory().size() - 1).isDestroyedBuildArea());
}
};
public static ViewFlag TESTBLOCK_DESTROY_ONLY = new ViewFlag(true, false, "testblock-destroy-only") {
@Override
public Stream<TNTPoint> filter(Stream<TNTPoint> records) {
return records.filter(record -> record.getHistory().get(record.getHistory().size() - 1).isDestroyedTestBlock());
}
};
public static ViewFlag MICROMOTION = new ViewFlag(true, false, "micromotion", "m") {
@Override
public Stream<TNTPoint> filter(Stream<TNTPoint> stream) {
List<TNTPoint> records = stream.collect(Collectors.toList());
;
Set<Integer> seen = new HashSet<>();
Set<TNTPoint> toRemove = new HashSet<>();
for (TNTPoint uniqueRecord : records) {
if (seen.contains(uniqueRecord.getTntId())) continue;
boolean hasMicromotion = false;
for (TNTPoint record : uniqueRecord.getHistory()) {
Vector velocity = record.getVelocity();
if (velocity.getY() == 0 && (Math.abs(velocity.getX()) < 0.001 || Math.abs(velocity.getZ()) < 0.001)) {
hasMicromotion = true;
break;
}
}
if (!hasMicromotion)
toRemove.add(uniqueRecord);
seen.add(uniqueRecord.getTntId());
}
for (TNTPoint record : toRemove) {
records.removeAll(record.getHistory());
}
return records.stream();
}
};
public static ViewFlag ADVANCED = new ViewFlag(true, false, "advanced", "a") {
@Override
public void modify(REntityServer server, List<TraceEntity> entities) {
for (TraceEntity entity : entities) {
TNTPoint current = entity.getRecords().get(0);
if (current.isExplosion()) continue;
TNTPoint next = current.getNext().orElse(null);
if (next == null) continue;
Location pos = current.getLocation().clone();
pos.setY(next.getLocation().getY());
if (pos.distanceSquared(current.getLocation()) >= 1.0 / 256.0) {
RFallingBlockEntity y = new RFallingBlockEntity(server, pos, Material.WHITE_STAINED_GLASS);
y.setNoGravity(true);
}
if (current.getVelocity().getX() >= current.getVelocity().getZ()) {
pos.setX(next.getLocation().getX());
} else {
pos.setZ(next.getLocation().getZ());
}
if (pos.distanceSquared(next.getLocation()) >= 1.0 / 256.0) {
RFallingBlockEntity second = new RFallingBlockEntity(server, pos, Material.WHITE_STAINED_GLASS);
second.setNoGravity(true);
}
}
}
};
public static ViewFlag COUNT = new ViewFlag(true, false, "count", "c") {
@Override
public void modify(REntityServer server, List<TraceEntity> entities) {
for (TraceEntity entity : entities) {
entity.setDisplayName(String.valueOf(entity.getRecords().size()));
}
}
};
public static ViewFlag FUSE = new ViewFlag(true, false, "fuse", "f") {
@Override
public void modify(REntityServer server, List<TraceEntity> entities) {
for (TraceEntity entity : entities) {
List<String> fuses = entity.getRecords()
.stream()
.map(TNTPoint::getFuse)
.distinct()
.sorted()
.map(i -> i + "")
.collect(Collectors.toList());
if (fuses.size() <= 5) {
entity.setDisplayName(String.join(",", fuses));
} else {
entity.setDisplayName(fuses.stream().limit(5).collect(Collectors.joining(",")) + ", +" + (fuses.size() - 5));
}
}
}
};
public static ViewFlag TIME = new ViewFlag(true, false, "time", "t") {
@Override
public void modify(REntityServer server, List<TraceEntity> entities) {
for (TraceEntity entity : entities) {
List<String> time = entity.getRecords()
.stream()
.map(TNTPoint::getTicksSinceStart)
.distinct()
.sorted()
.map(i -> i + "")
.collect(Collectors.toList());
if (time.size() <= 5) {
entity.setDisplayName(String.join(",", time));
} else {
entity.setDisplayName(time.stream().limit(5).collect(Collectors.joining(",")) + ", +" + (time.size() - 5));
}
}
}
};
/**
* Name of the flag
*/
public final String name;
/**
* Aliases of the flag
*/
public final String[] aliases;
/**
* A flag that is used whenever this flag is used
*/
public final ViewFlag[] required;
protected ViewFlag(boolean isStatic, boolean isInverse, String name, String... aliases) {
this(isStatic, isInverse, new ViewFlag[0], name, aliases);
}
protected ViewFlag(boolean isStatic, boolean isInverse, ViewFlag required, String name, String... aliases) {
this(isStatic, isInverse, new ViewFlag[]{required}, name, aliases);
}
protected ViewFlag(boolean isStatic, boolean isInverse, ViewFlag[] required, String name, String... aliases) {
this.name = name;
this.aliases = aliases;
if (isStatic) flags.add(this);
if (isInverse) inverseFlags.add(this);
this.required = required;
}
/**
* Filters the given records for a given condition
*
* @param records Records to be filtered
* @return Filtered records
*/
public Stream<TNTPoint> filter(Stream<TNTPoint> records) {
return records;
}
/**
* Modifies the trace rendering
*
* @param server the server the trace is rendered on
* @param entities the entities representing tnts
*/
public void modify(REntityServer server, List<TraceEntity> entities) {
}
}

Datei anzeigen

@ -0,0 +1,61 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2024 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.tracer.rendering.dynamicflags;
import de.steamwar.bausystem.features.tracer.TNTPoint;
import de.steamwar.bausystem.features.tracer.rendering.ViewFlag;
import java.util.stream.Stream;
/**
* A view flag for rendering a trace only in a given time intervall
*/
public class AtFlag extends ViewFlag {
/**
* Start of the time interval
*/
private int start;
/**
* End of the time interval
*/
private int end;
public AtFlag(int start, int end) {
super(false, false, ViewFlag.IGNITE, null);
this.start = start;
this.end = end;
}
/**
* Update this flag to represent another time interval
*
* @param start new interval start
* @param end new interval end
*/
public void update(int start, int end) {
this.start = start;
this.end = end;
}
@Override
public Stream<TNTPoint> filter(Stream<TNTPoint> records) {
return records.filter(record -> record.getTicksSinceStart() >= start && record.getTicksSinceStart() <= end);
}
}

Datei anzeigen

@ -0,0 +1,59 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2024 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.tracer.rendering.dynamicflags;
import de.steamwar.bausystem.features.tracer.TNTPoint;
import de.steamwar.bausystem.features.tracer.rendering.ViewFlag;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Stream;
/**
* A flag for rendering only the records of specific tnts
*/
public class IsolateFlag extends ViewFlag {
/**
* Tnt ids that will be isolated
*/
private final Set<Integer> tntToIsolate = new HashSet<>();
public IsolateFlag() {
super(false, false, ViewFlag.IGNITE, null);
}
/**
* Toggles the given id to be or not to be rendered
*
* @param id
*/
public void toggleId(int id) {
if (!tntToIsolate.remove(id)) {
tntToIsolate.add(id);
}
}
@Override
public Stream<TNTPoint> filter(Stream<TNTPoint> records) {
if (tntToIsolate.isEmpty()) return records;
return records.filter(record -> tntToIsolate.contains(record.getTntId()));
}
}

Datei anzeigen

@ -1,268 +0,0 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.tracer.show;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.features.tracer.TNTPosition;
import de.steamwar.bausystem.shared.RoundedPosition;
import de.steamwar.bausystem.shared.ShowMode;
import de.steamwar.bausystem.utils.FlatteningWrapper;
import de.steamwar.entity.REntity;
import de.steamwar.entity.REntityServer;
import de.steamwar.entity.RFallingBlockEntity;
import net.md_5.bungee.api.chat.ClickEvent;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.stream.Stream;
public class EntityShowMode implements ShowMode<TNTPosition> {
private final int factor;
private final Player player;
private final ShowModeParameter showModeParameter;
private REntityServer entityServer;
private final Map<RoundedPosition, EntityStack> tntEntityMap = new HashMap<>();
private final Map<RoundedPosition, EntityStack> explodeEntityMap = new HashMap<>();
private final Map<RoundedPosition, EntityStack> updateEntityMap = new HashMap<>();
public EntityShowMode(Player player, ShowModeParameter showModeParameter, int factor) {
this.player = player;
this.showModeParameter = showModeParameter;
this.factor = factor;
}
@Override
public void show(TNTPosition position) {
if (entityServer == null) {
entityServer = new REntityServer();
entityServer.setCallback((player, rEntity, entityAction) -> {
if (entityAction != REntityServer.EntityAction.INTERACT) return;
TNTPosition tntPosition = Stream.concat(tntEntityMap.values().stream(), explodeEntityMap.values().stream())
.filter(entityStack -> entityStack.entity == rEntity)
.findFirst()
.map(entityStack -> entityStack.tntPosition)
.orElse(null);
if (tntPosition == null) return;
BauSystem.MESSAGE.sendPrefixless("TNT_CLICK_HEADER", player);
BauSystem.MESSAGE.sendPrefixless("TNT_CLICK_FUSE_TIME", player, tntPosition.getFuseTicks());
BauSystem.MESSAGE.sendPrefixless("TNT_CLICK_POSITION_X", player, tntPosition.getLocation().getX() + "");
BauSystem.MESSAGE.sendPrefixless("TNT_CLICK_POSITION_Y", player, tntPosition.getLocation().getY() + "");
BauSystem.MESSAGE.sendPrefixless("TNT_CLICK_POSITION_Z", player, tntPosition.getLocation().getZ() + "");
BauSystem.MESSAGE.sendPrefixless("TNT_CLICK_VELOCITY_X", player, tntPosition.getVelocity().getX() + "");
BauSystem.MESSAGE.sendPrefixless("TNT_CLICK_VELOCITY_Y", player, tntPosition.getVelocity().getY() + "");
BauSystem.MESSAGE.sendPrefixless("TNT_CLICK_VELOCITY_Z", player, tntPosition.getVelocity().getZ() + "");
BauSystem.MESSAGE.sendPrefixless("TNT_CLICK_ISOLATE", player, BauSystem.MESSAGE.parse("TRACE_MESSAGE_CLICK_ISOLATE", player), new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/trace isolate " + tntPosition.getRecord().getId()));
});
entityServer.addPlayer(player);
}
if (showModeParameter.isBuildDestroyOnly() && !position.getRecord().isInBuildArea()) {
return;
}
if (showModeParameter.isTestblockDestroyOnly() && !position.getRecord().isInTestblockArea()) {
return;
}
if (showModeParameter.isMicroMotion() && !position.getRecord().isHasMicroMotion()) {
return;
}
boolean exploded = position.getRecord().getPositions().stream().anyMatch(TNTPosition::isExploded);
boolean hideWater = !showModeParameter.isWater() && exploded && checkWater(position.getLocation());
if (showModeParameter.isExplodeOnly()) {
if (position.isExploded()) {
generatePositions(position, false, false);
}
if (!showModeParameter.isSourceOnly() && !showModeParameter.isMicroMotionLocation() && !hideWater) {
return;
}
}
if (showModeParameter.isSourceOnly()) {
if (position.isSource()) {
generatePositions(position, false, false);
}
if (!showModeParameter.isMicroMotionLocation() && !hideWater) {
return;
}
}
if (showModeParameter.isMicroMotionLocation()) {
if (position.isMicroMotion()) {
generatePositions(position, false, false);
}
if (!hideWater) {
return;
}
}
if (hideWater) {
if (position.isExploded()) {
for (TNTPosition pos : position.getRecord().getPositions()) {
generatePositions(pos, showModeParameter.isInterpolateY(), showModeParameter.isInterpolateXZ(), (positionType, vector) -> {
RoundedPosition roundedPosition = new RoundedPosition(vector, factor);
Map<RoundedPosition, EntityStack> map;
if (positionType == PositionType.TNT) {
map = tntEntityMap;
} else if (positionType == PositionType.EXPLODE) {
map = explodeEntityMap;
} else {
map = updateEntityMap;
}
map.computeIfPresent(roundedPosition, (roundedPosition1, entityStack) -> {
if (!entityStack.remove(pos.getRecord())) {
return null;
}
return entityStack;
});
});
}
}
return;
}
generatePositions(position, showModeParameter.isInterpolateY(), showModeParameter.isInterpolateXZ());
}
@Override
public void hide() {
tntEntityMap.clear();
explodeEntityMap.clear();
updateEntityMap.clear();
if (entityServer != null) {
entityServer.close();
entityServer = null;
}
}
private void generatePositions(TNTPosition position, boolean interpolateY, boolean interpolateXZ) {
generatePositions(position, interpolateY, interpolateXZ, (positionType, vector) -> {
RoundedPosition roundedPosition = new RoundedPosition(vector, factor);
EntityStack entityStack;
if (positionType == PositionType.TNT) {
entityStack = tntEntityMap.computeIfAbsent(roundedPosition, i -> new EntityStack(position, vector, positionType, position.getFuseTicks()));
} else if (positionType == PositionType.EXPLODE) {
entityStack = explodeEntityMap.computeIfAbsent(roundedPosition, i -> new EntityStack(position, vector, positionType, position.getFuseTicks()));
} else {
entityStack = updateEntityMap.computeIfAbsent(roundedPosition, i -> new EntityStack(position, vector, positionType, position.getFuseTicks()));
}
entityStack.add(position.getRecord());
});
}
private boolean checkWater(Vector position) {
return FlatteningWrapper.impl.inWater(player.getWorld(), position);
}
private REntity createEntity(Vector position, PositionType positionType) {
Material material;
if (positionType == PositionType.TNT) {
material = Material.TNT;
} else if (positionType == PositionType.EXPLODE) {
material = Material.RED_STAINED_GLASS;
} else {
material = Material.WHITE_STAINED_GLASS;
}
RFallingBlockEntity entity = new RFallingBlockEntity(entityServer, position.toLocation(player.getWorld()), material);
entity.setNoGravity(true);
return entity;
}
private class EntityStack {
private final TNTPosition tntPosition;
private final Vector position;
private final PositionType positionType;
private final int fuseTicks;
private REntity entity;
private int count;
private List<Record.TNTRecord> records = new ArrayList<>();
public EntityStack(TNTPosition tntPosition, Vector position, PositionType positionType, int fuseTicks) {
this.tntPosition = tntPosition;
this.position = position;
this.positionType = positionType;
this.fuseTicks = fuseTicks;
}
public void add(Record.TNTRecord record) {
records.add(record);
if (entity == null) {
entity = createEntity(position, positionType);
}
count++;
if (showModeParameter.isFuse()) {
entity.setDisplayName(fuseTicks + "");
} else if (showModeParameter.isCount()) {
entity.setDisplayName(new HashSet<>(records).size() + "");
}
}
public boolean remove(Record.TNTRecord record) {
if (entity == null) return false;
records.remove(record);
count--;
if (count == 0) {
entity.die();
entity = null;
return false;
}
return true;
}
}
public static void generatePositions(TNTPosition position, boolean interpolateY, boolean interpolateXZ, BiConsumer<PositionType, Vector> positionCallback) {
positionCallback.accept(position.isExploded() ? PositionType.EXPLODE : PositionType.TNT, position.getLocation());
if (position.getPreviousLocation() == null) return;
if (interpolateY) {
Vector updatePointY = position.getPreviousLocation().clone().setY(position.getLocation().getY());
if (!position.getLocation().equals(updatePointY)) {
positionCallback.accept(PositionType.UPDATE, updatePointY);
}
}
if (interpolateXZ) {
Vector updatePointXZ = Math.abs(position.getUpdateVelocity().getX()) >= Math.abs(position.getUpdateVelocity().getZ())
? position.getLocation().clone().setZ(position.getPreviousLocation().getZ())
: position.getLocation().clone().setX(position.getPreviousLocation().getX());
if (!position.getLocation().equals(updatePointXZ)) {
positionCallback.accept(PositionType.UPDATE, updatePointXZ);
}
}
}
public enum PositionType {
TNT,
EXPLODE,
UPDATE
}
}

Datei anzeigen

@ -1,136 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.tracer.show;
import de.steamwar.bausystem.features.tpslimit.TPSUtils;
import de.steamwar.bausystem.features.tracer.TNTPosition;
import de.steamwar.bausystem.region.Region;
import de.steamwar.bausystem.shared.ShowMode;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import org.bukkit.entity.TNTPrimed;
import org.bukkit.util.Vector;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
@RequiredArgsConstructor
public class Record {
@Getter
private final List<TNTRecord> tnt = new ArrayList<>();
private final Region region;
private final long startTicks = TPSUtils.currentTick.get();
public int size() {
return tnt.size();
}
public void showAll(ShowMode<TNTPosition> traceShowMode) {
tnt.forEach(tntRecord -> tntRecord.getPositions().forEach(traceShowMode::show));
}
public TNTRecord spawn() {
TNTRecord record = new TNTRecord(this, region);
tnt.add(record);
return record;
}
public void clear() {
tnt.clear();
}
private void checkMicroMotion(Vector explosionPosition) {
for (TNTRecord tntRecord : tnt) {
List<TNTPosition> positions = tntRecord.positions;
if (positions.isEmpty()) continue;
TNTPosition position = positions.get(positions.size() - 1);
if (position.isExploded()) continue;
if (position.getLocation().distanceSquared(explosionPosition) > 64) continue;
Vector velocity = position.getVelocity();
if (velocity.getY() == 0 && ((velocity.getX() != 0 && Math.abs(velocity.getX()) < 0.001) || (velocity.getZ() != 0 && Math.abs(velocity.getZ()) < 0.001))) {
if (!tntRecord.hasMicroMotion) {
positions.forEach(tntPosition -> TraceShowManager.show(region, tntPosition));
}
tntRecord.hasMicroMotion = true;
position.setMicroMotion(true);
}
}
}
public static class TNTRecord {
@Getter
private final UUID id = UUID.randomUUID();
private Record record;
@Getter
private final Region region;
@Getter
private final List<TNTPosition> positions = new ArrayList<>(82);
@Getter
@Setter
private boolean inBuildArea = false;
@Getter
@Setter
private boolean inTestblockArea = false;
@Getter
private boolean hasMicroMotion = false;
public TNTRecord(Record record, Region region) {
this.record = record;
this.region = region;
}
public void source(TNTPrimed tntPrimed) {
add(tntPrimed, true, false);
}
public void location(TNTPrimed tntPrimed) {
add(tntPrimed, false, false);
}
public void explode(TNTPrimed tntPrimed) {
add(tntPrimed, false, true);
record.checkMicroMotion(tntPrimed.getLocation().toVector());
}
private void add(TNTPrimed tntPrimed, boolean source, boolean exploded) {
TNTPosition position;
if (positions.isEmpty()) {
position = new TNTPosition(this, tntPrimed, TPSUtils.currentTick.get() - record.startTicks, null, tntPrimed.getVelocity(), null, source, exploded);
} else {
TNTPosition tntPosition = positions.get(positions.size() - 1);
Vector lastVelocity = tntPrimed.getLocation().toVector().clone().subtract(tntPosition.getLocation());
position = new TNTPosition(this, tntPrimed, TPSUtils.currentTick.get() - record.startTicks, positions.get(positions.size() - 1).getLocation(), tntPrimed.getVelocity(), lastVelocity, source, exploded);
}
positions.add(position);
TraceShowManager.show(region, position);
}
}
}

Datei anzeigen

@ -1,85 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.tracer.show;
import lombok.Getter;
@Getter
public class ShowModeParameter {
private boolean water = false;
private boolean interpolateY = false;
private boolean interpolateXZ = false;
private boolean sourceOnly = false;
private boolean explodeOnly = false;
private boolean fuse = false;
private boolean count = false;
private boolean buildDestroyOnly = false;
private boolean testblockDestroyOnly = false;
private boolean microMotion = false;
private boolean microMotionLocation = false;
public void enableWater() {
this.water = true;
}
public void disableWater() {
this.water = false;
}
public void enableInterpolateY() {
this.interpolateY = true;
}
public void enableInterpolateXZ() {
this.interpolateXZ = true;
}
public void enableSourceOnly() {
this.sourceOnly = true;
}
public void enableExplodeOnly() {
this.explodeOnly = true;
}
public void enableFuse() {
this.fuse = true;
}
public void enableCount() {
this.count = true;
}
public void enableBuildDestroyOnly() {
this.buildDestroyOnly = true;
}
public void enableTestblockDestroyOnly() {
this.testblockDestroyOnly = true;
}
public void enableMicroMotion() {
this.microMotion = true;
}
public void enableMicroMotionLocation() {
this.microMotionLocation = true;
}
}

Datei anzeigen

@ -1,74 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.tracer.show;
import lombok.Getter;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import java.util.function.Supplier;
public enum ShowModeParameterType {
WATER(ShowModeParameter::enableWater, Arrays.asList("-water"), "EXPLODE", "SOURCE", "BUILD_DESTROY_ONLY"),
INTERPOLATE_Y(ShowModeParameter::enableInterpolateY, Arrays.asList("-interpolatey", "-interpolate-y", "-interpolate_y", "-y"), "ADVANCED"),
INTERPOLATE_XZ(ShowModeParameter::enableInterpolateXZ, Arrays.asList("-interpolatex", "-interpolate-x", "-interpolate_x", "-x", "-interpolatez", "-interpolate-z", "-interpolate_z", "-z", "-interpolatexz", "-interpolate-xz", "-interpolate_xz", "-xz"), "ADVANCED"),
ADVANCED(showModeParameter -> {
showModeParameter.enableInterpolateY();
showModeParameter.enableInterpolateXZ();
}, Arrays.asList("-advanced", "-a"), "INTERPOLATE_Y", "INTERPOLATE_XZ"),
SOURCE(ShowModeParameter::enableSourceOnly, Arrays.asList("-source", "-sourceonly", "-ignite"), "FUSE", "ADVANCED", "INTERPOLATE_Y", "INTERPOLATE_XZ", "WATER"),
EXPLODE(ShowModeParameter::enableExplodeOnly, Arrays.asList("-explode", "-explodeonly"), "FUSE", "ADVANCED", "INTERPOLATE_Y", "INTERPOLATE_XZ", "WATER"),
FUSE(ShowModeParameter::enableFuse, Arrays.asList("-fuse", "-f"), "EXPLODE", "SOURCE", "COUNT"),
COUNT(ShowModeParameter::enableCount, Arrays.asList("-count", "-c"), "FUSE"),
BUILD_DESTROY_ONLY(ShowModeParameter::enableBuildDestroyOnly, Arrays.asList("-builddestroy", "-builddestoryonly"), "WATER", "TESTBLOCK_DESTROY_ONLY"),
TESTBLOCK_DESTROY_ONLY(ShowModeParameter::enableTestblockDestroyOnly, Arrays.asList("-testblockdestroy", "-testblockdestroyonly"), "WATER", "BUILD_DESTROY_ONLY"),
MICROMOTION(ShowModeParameter::enableMicroMotion, Arrays.asList("-micromotion", "-micro", "-m")),
MICROMOTION_LOCATION(ShowModeParameter::enableMicroMotionLocation, Arrays.asList("-micromotionloc", "-microloc", "-mloc", "-micromotionlocation", "-microlocation", "-mlocation")),
;
@Getter
private final Consumer<ShowModeParameter> showModeParameterConsumer;
@Getter
private List<String> tabCompletes;
@Getter
private final Supplier<ShowModeParameterType[]> removed;
private AtomicReference<ShowModeParameterType[]> cached = new AtomicReference<>();
ShowModeParameterType(Consumer<ShowModeParameter> showModeParameterConsumer, List<String> tabCompletes, String... removed) {
this.showModeParameterConsumer = showModeParameterConsumer;
this.tabCompletes = tabCompletes;
this.removed = () -> {
if (cached.get() == null) {
ShowModeParameterType[] showModeParameterTypes = new ShowModeParameterType[removed.length];
for (int i = 0; i < removed.length; i++) {
showModeParameterTypes[i] = ShowModeParameterType.valueOf(removed[i]);
}
cached.set(showModeParameterTypes);
return showModeParameterTypes;
}
return cached.get();
};
}
}

Datei anzeigen

@ -1,70 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.tracer.show;
import de.steamwar.bausystem.features.tracer.TNTPosition;
import de.steamwar.bausystem.features.tracer.record.Recorder;
import de.steamwar.bausystem.region.Region;
import de.steamwar.bausystem.shared.ShowMode;
import lombok.experimental.UtilityClass;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@UtilityClass
public class StoredRecords {
private static final Map<Region, List<Record>> records = new HashMap<>();
public static void add(Region region, Record record) {
records.computeIfAbsent(region, k -> new ArrayList<>()).add(record);
}
public static void remove(Region region, Record record) {
records.computeIfAbsent(region, k -> new ArrayList<>()).remove(record);
}
public static void clear(Region region) {
records.remove(region);
TraceShowManager.clear(region);
Recorder.INSTANCE.postClear(region);
}
public static List<Record> getRecords() {
return records.values().stream()
.flatMap(Collection::stream)
.collect(Collectors.toList());
}
public static List<Record> getRecords(Region region) {
return records.getOrDefault(region, Collections.emptyList());
}
static void show(Region region, Predicate<TNTPosition> traceShowFilter, ShowMode<TNTPosition> traceShowMode) {
records.getOrDefault(region, new ArrayList<>()).forEach(record -> {
record.getTnt().forEach(tntRecord -> {
tntRecord.getPositions().stream()
.filter(traceShowFilter)
.forEach(traceShowMode::show);
});
});
}
}

Datei anzeigen

@ -1,152 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.tracer.show;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.features.tracer.TNTPosition;
import de.steamwar.bausystem.region.Region;
import de.steamwar.bausystem.shared.ShowMode;
import de.steamwar.bausystem.utils.BauMemberUpdateEvent;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerQuitEvent;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Predicate;
public class TraceShowManager implements Listener {
private TraceShowManager() {
}
private static final Map<Region, Map<Player, ShowMode<TNTPosition>>> showModes = new HashMap<>();
private static final Map<Region, Map<Player, Predicate<TNTPosition>>> showFilters = new HashMap<>();
public static void show(Player player, ShowMode<TNTPosition> traceShowMode) {
Region region = Region.getRegion(player.getLocation());
_hide(region, player, true);
Map<Player, ShowMode<TNTPosition>> regionalShowModes = showModes.computeIfAbsent(region, __ -> new HashMap<>());
regionalShowModes.put(player, traceShowMode);
StoredRecords.show(region, getShowFilter(player, region), traceShowMode);
}
public static void hide(Player player) {
Region region = Region.getRegion(player.getLocation());
_hide(region, player, true);
showFilters.getOrDefault(region, new HashMap<>()).remove(player);
}
public static void setShowFilter(Player player, Predicate<TNTPosition> showFilter) {
Region region = Region.getRegion(player.getLocation());
Map<Player, Predicate<TNTPosition>> regionShowFilters = showFilters.computeIfAbsent(region, __ -> new HashMap<>());
if (showFilter == null) {
regionShowFilters.remove(player);
} else {
regionShowFilters.put(player, showFilter);
}
_hide(region, player, false);
ShowMode<TNTPosition> showMode = showModes.computeIfAbsent(region, __ -> new HashMap<>()).computeIfAbsent(player, __ -> new EntityShowMode(player, new ShowModeParameter(), 16));
StoredRecords.show(region, getShowFilter(player, region), showMode);
}
public static void reshow(Region region) {
Map<Player, ShowMode<TNTPosition>> regionalShowModes = showModes.get(region);
if (regionalShowModes == null) {
return;
}
for (Map.Entry<Player, ShowMode<TNTPosition>> entry : regionalShowModes.entrySet()) {
entry.getValue().hide();
StoredRecords.show(region, getShowFilter(entry.getKey(), region), entry.getValue());
}
}
private static void _hide(Region region, Player player, boolean remove) {
Map<Player, ShowMode<TNTPosition>> regionalShowModes = showModes.get(region);
if (regionalShowModes == null) {
return;
}
ShowMode<TNTPosition> showMode;
if (remove) {
showMode = regionalShowModes.remove(player);
} else {
showMode = regionalShowModes.get(player);
}
if (showMode == null) {
return;
}
showMode.hide();
}
private static Predicate<TNTPosition> getShowFilter(Player player, Region region) {
return showFilters.getOrDefault(region, new HashMap<>()).getOrDefault(player, tntPosition -> true);
}
/* Only to be called by record */
static void show(Region region, TNTPosition tnt) {
Map<Player, ShowMode<TNTPosition>> regionalShowModes = showModes.get(region);
if (regionalShowModes == null) {
return;
}
regionalShowModes.forEach((player, tntPositionShowMode) -> {
if (getShowFilter(player, region).test(tnt)) {
tntPositionShowMode.show(tnt);
}
});
}
/* Only to be called by StoredRecords */
static void clear(Region region) {
Map<Player, ShowMode<TNTPosition>> regionalShowModes = showModes.get(region);
if (regionalShowModes == null) {
return;
}
regionalShowModes.values().forEach(ShowMode::hide);
}
/* Internal if player leaves*/
static {
Bukkit.getPluginManager().registerEvents(new TraceShowManager(), BauSystem.getInstance());
}
@EventHandler
public void onLeave(PlayerQuitEvent event) {
hideComplete(event.getPlayer());
}
@EventHandler
public void onBauMemberUpdate(BauMemberUpdateEvent event) {
event.getNewSpectator().forEach(this::hideComplete);
}
private void hideComplete(Player player) {
showModes.forEach((region, playerShowModeMap) -> {
ShowMode<TNTPosition> showMode = playerShowModeMap.remove(player);
if (showMode != null) showMode.hide();
});
showFilters.forEach((region, playerPredicateMap) -> {
playerPredicateMap.remove(player);
});
}
}