Merge pull request 'Trace Refactor' (#233) from TracerGUI into master
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
Reviewed-on: #233 Reviewed-by: YoyoNow <jwsteam@nidido.de>
Dieser Commit ist enthalten in:
Commit
aeb5ebfc12
8
.gitignore
vendored
8
.gitignore
vendored
@ -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
|
@ -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());
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
@ -858,16 +795,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.
|
||||
@ -877,7 +811,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
|
||||
@ -889,16 +822,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
|
||||
@ -941,39 +871,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
|
||||
@ -981,16 +903,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
|
||||
@ -998,11 +916,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
|
||||
@ -1010,11 +926,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}
|
||||
@ -1026,7 +940,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
|
||||
@ -1037,15 +950,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}
|
||||
@ -1069,30 +979,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
|
||||
|
@ -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
|
||||
@ -822,13 +754,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.
|
||||
@ -838,7 +768,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
|
||||
@ -850,16 +779,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
|
||||
@ -898,39 +824,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
|
||||
@ -938,16 +856,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
|
||||
@ -955,11 +869,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
|
||||
@ -967,11 +879,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}
|
||||
@ -993,14 +903,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}
|
||||
@ -1024,30 +931,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
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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 -> {
|
||||
|
@ -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()));
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -196,4 +196,9 @@ public class CreatingLaufState implements LaufbauState {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LaufbauState getNextState() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -45,4 +45,6 @@ public interface LaufbauState {
|
||||
}
|
||||
return LocalTime.ofNanoOfDay(eta).format(DateTimeFormatter.ofPattern(BauSystem.MESSAGE.parse("TIME", p)));
|
||||
}
|
||||
|
||||
LaufbauState getNextState();
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
227
BauSystem_Main/src/de/steamwar/bausystem/features/tracer/TNTPoint.java
Normale Datei
227
BauSystem_Main/src/de/steamwar/bausystem/features/tracer/TNTPoint.java
Normale Datei
@ -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;
|
||||
}
|
||||
}
|
@ -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() +
|
||||
'}';
|
||||
}
|
||||
}
|
339
BauSystem_Main/src/de/steamwar/bausystem/features/tracer/Trace.java
Normale Datei
339
BauSystem_Main/src/de/steamwar/bausystem/features/tracer/Trace.java
Normale Datei
@ -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() +
|
||||
'}';
|
||||
}
|
||||
}
|
@ -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());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -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());
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
@ -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()));
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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 {
|
||||
}
|
@ -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";
|
||||
}
|
||||
}
|
@ -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";
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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";
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
@ -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);
|
||||
}
|
@ -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();
|
||||
}
|
@ -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;
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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));
|
||||
}
|
||||
}
|
@ -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) {
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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()));
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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();
|
||||
};
|
||||
}
|
||||
}
|
@ -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);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
@ -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);
|
||||
});
|
||||
}
|
||||
}
|
In neuem Issue referenzieren
Einen Benutzer sperren