diff --git a/BauSystem_Linkage/src/de/steamwar/linkage/types/SmartPlaceBehaviour_GENERIC.java b/BauSystem_Linkage/src/de/steamwar/linkage/types/SmartPlaceBehaviour_GENERIC.java deleted file mode 100644 index 0f50ac45..00000000 --- a/BauSystem_Linkage/src/de/steamwar/linkage/types/SmartPlaceBehaviour_GENERIC.java +++ /dev/null @@ -1,40 +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 . - */ - -package de.steamwar.linkage.types; - -import de.steamwar.linkage.LinkageType; -import de.steamwar.linkage.plan.BuildPlan; -import de.steamwar.linkage.plan.MethodBuilder; - -import javax.lang.model.element.TypeElement; - -public class SmartPlaceBehaviour_GENERIC implements LinkageType { - - @Override - public String method() { - return "linkSmartPlace"; - } - - @Override - public void generateCode(BuildPlan buildPlan, MethodBuilder methodBuilder, String s, TypeElement typeElement) { - buildPlan.addImport("de.steamwar.bausystem.features.smartplace.SmartPlaceListener"); - methodBuilder.addLine("SmartPlaceListener.add(" + s + ");"); - } -} diff --git a/BauSystem_Main/build.gradle b/BauSystem_Main/build.gradle index 744e575c..62d604cf 100644 --- a/BauSystem_Main/build.gradle +++ b/BauSystem_Main/build.gradle @@ -54,12 +54,11 @@ dependencies { implementation project(":BauSystem_Linkage") annotationProcessor project(":BauSystem_Linkage") - compileOnly 'org.spigotmc:spigot-api:1.19-R0.1-SNAPSHOT' + compileOnly 'org.spigotmc:spigot-api:1.20-R0.1-SNAPSHOT' compileOnly 'com.mojang:authlib:1.5.25' compileOnly 'io.netty:netty-all:4.1.68.Final' - compileOnly swdep('Spigot-1.19') - // compileOnly swdep('WorldEdit-1.15') + compileOnly swdep('Spigot-1.20') compileOnly swdep('SpigotCore') annotationProcessor swdep('SpigotCore') diff --git a/BauSystem_Main/src/BauSystem.properties b/BauSystem_Main/src/BauSystem.properties index 57f92a6e..045e4872 100644 --- a/BauSystem_Main/src/BauSystem.properties +++ b/BauSystem_Main/src/BauSystem.properties @@ -60,6 +60,7 @@ 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 @@ -105,9 +106,8 @@ AUTOSTART_ITEM_LORE = §eRight Click Block §8- §7Start Timer AUTOSTART_MESSAGE_NO_REGION = §cYou are not inside any region AUTOSTART_MESSAGE_RESET = §eAutostartTimer restarted AUTOSTART_MESSAGE_START = §eAutostartTimer started -AUTOSTART_MESSAGE_RESULT1 = §eTime §7until §eexplosion §7at enemy§8:§e {0} -AUTOSTART_MESSAGE_DATE_PATTERN=mm:ss SSSS -AUTOSTART_MESSAGE_RESULT2 = §eTime difference in game-ticks §7until {0} seconds§8:§e {1} +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 @@ -140,22 +140,21 @@ BAU_INFO_ITEM_NAME = §eBau-Management ## This is used in BauInfoBauGuiItem.java BAU_INFO_ITEM_LORE_TNT = §7TNT§8: §e{0} BAU_INFO_ITEM_LORE_FREEZE = §7Freeze§8: §e{0} -BAU_INFO_ITEM_LORE_DAMAGE= 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: §e{0} -BAU_INFO_COMMAND_MEMBER = §7Member: §e +BAU_INFO_COMMAND_OWNER = §7Owner§8: §e{0} +BAU_INFO_COMMAND_MEMBER = §7Member §8[§7{0}§8]§8: §e BAU_INFO_MEMBER_INFO = §e{0}§8[{1}§8,{2}§8] §8 BAU_INFO_MEMBER_WE_ALLOW = §aWE BAU_INFO_MEMBER_WE_DISALLOW = §cWE BAU_INFO_MEMBER_WORLD_ALLOW = §aW BAU_INFO_MEMBER_WORLD_DISALLOW = §cW -BAU_INFO_COMMAND_FLAG = §e{0} §8: §7{1} -BAU_INFO_COMMAND_TPS = TPS:§e +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 @@ -168,10 +167,10 @@ 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- §7Show where Endstone is +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 activated -DESIGN_ENDSTONE_DISABLE = §cEndstone is deactivated +DESIGN_ENDSTONE_ENABLE = §aEndstone is highlighted +DESIGN_ENDSTONE_DISABLE = §cEndstone is no longer hightlighted # Detonator DETONATOR_LOC_REMOVE = §e{0} removed @@ -202,7 +201,7 @@ DETONATOR_INVALID_POINT=§cOne point could not be activated DETONATOR_INVALID_POINTS=§c{0} points could not be activated DETONATOR_INVALID_BLOCK=§eThe block could not be addded # Hotbar -HOTBAR_HELP_GENERIC=§7Saves a hotbar. While joining a bau with an empty inventory this hotbar will be used +HOTBAR_HELP_GENERIC=§7Saves a hotbar. While joining a bau with an empty inventory this hotbar will be used. HOTBAR_HELP_SAVE=§8/§ehotbar save §8-§7 Saves your current hotbar HOTBAR_HELP_LOAD=§8/§ehotbar load §8-§7 Loads the saved hotbar HOTBAR_HELP_SHOW=§8/§ehotbar show §8-§7 Displays the saved hotbar @@ -490,14 +489,19 @@ 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_MESSAGE_START = §aTNT-Tracer started TRACE_MESSAGE_SINGLE = §aSingle-Tracer started TRACE_MESSAGE_STOP = §cTNT-Tracer stopped TRACE_MESSAGE_DELETE = §cAll TNT-positions deleted TRACE_MESSAGE_SHOW = §aAll TNT-positions shown TRACE_MESSAGE_HIDE = §cAll TNT-positions hidden -TRACE_MESSAGE_ISOLATE = §aTNT-positions isolated -TRACE_MESSAGE_UNISOLATE = §cTNT-positions hidden TRACE_MESSAGE_CLICK_ISOLATE = §eClick to §aisolate§8/§cunisolate TRACE_MESSAGE_DISALLOWED = §cYou are not allowed to use the TNT-Tracer here @@ -505,15 +509,10 @@ TRACE_COMMAND_HELP_START = §8/§etrace start §8- §7Starts recording of all TN 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_HIDE = §8/§etrace hide §8- §7Hides all TNT-positions TRACE_COMMAND_HELP_DELETE = §8/§etrace delete §8- §7Deletes all TNT-positions -TRACE_COMMAND_HELP_GUI = §8/§etrace gui §8- §7Shows the Trace GUI -TRACE_COMMAND_HELP_REPLAY = §8/§etrace replay §8[§7tick§8] §8- §7Replays your recording -TRACE_COMMAND_HELP_REPLAY_DISABLE = §8/§etrace replay disable §8- §7Stops the replay -TRACE_COMMAND_HELP_REPLAY_NEXT = §8/§etrace replay next §8[§7step§8] §8- §7Jump one§8/§7step tick forward -TRACE_COMMAND_HELP_REPLAY_PREVIOUS = §8/§etrace replay previous §8[§7step§8] §8- §7Jump one§8/§7step tick back -TRACE_COMMAND_HELP_REPLAY_LOOP = §8/§etrace replay loop §8<§7start§8> §8<§7end§8> §8[§7speed§8] §8- §7Loop the replay TRACE_GUI_ITEM_NAME = §eTracer TRACE_GUI_ITEM_LORE = §7Status§8: {0} @@ -525,19 +524,6 @@ TRACE_GUI_AUTO_TRACE_INACTIVE = §eacitvate Auto-Tracer TRACE_GUI_AUTO_TRACE_ACTIVE = §edeactivate Auto-Tracer TRACE_GUI_DELETE = §eDelete trace -TRACE_GUI_TITLE = Trace GUI -TRACE_GUI_ITEM_BACK = §eBack -TRACE_GUI_ITEM = §eTrace §8- §e{0} §7TNT -TRACE_GUI_CLEAR = §eDelete traces -TRACE_GUI_RECORD_ITEM = §eTNT §8- §e{0} §7Positions -TRACE_GUI_RECORD_CLEAR = §eDelete TNT -TRACE_GUI_POSITION_ITEM = §ePosition -TRACE_GUI_POSITION_X = §7X§8: §e{0} -TRACE_GUI_POSITION_Y = §7Y§8: §e{0} -TRACE_GUI_POSITION_Z = §7Z§8: §e{0} -TRACE_GUI_POSITION_SOURCE = §7Source§8: §e{0} -TRACE_GUI_POSITION_EXPLODED = §7Exploded§8: §e{0} - # Loader LOADER_SETUP = §eSetup LOADER_RUNNING = §aRunning @@ -545,6 +531,7 @@ LOADER_PAUSE = §7Pause LOADER_END = §8Finished LOADER_MESSAGE_INTERACT=§e{0} added {1} +LOADER_MESSAGE_UNINTERACT=§eRemoved Element LOADER_BUTTON_TNT=TNT LOADER_BUTTON_SWITCH=Lever LOADER_BUTTON_WOOD_BUTTON=Wooden Button @@ -567,36 +554,45 @@ LOADER_HELP_START=§8/§eloader start §8- §7Playback of previously recorded ac 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 +LOADER_HELP_WAIT=§8/§7loader wait §8[§7Ticks§8] - §7Sets wait time between shots +LOADER_HELP_SPEED=§8/§7loader speed §8[§7Ticks§8] - §7Sets wait time between actions LOADER_NO_LOADER=§cYou have no Laoder. Create one with /loader setup 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_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_PERMS=§cYou are not allowed to use the Loader here LOADER_NOTHING_RECORDED=§cYou have not recorded anything yet! LOADER_GUI_TITLE=Loader GUI -LOADER_GUI_SHOW_INTERACTIONS=§eShow only Interactions -LOADER_GUI_SHOW_WAITS=§eShow only Waits -LOADER_GUI_SHOW_WAITS_SET_BETWEEN_TNT=§7Wait Time between TNT +LOADER_GUI_SHOW_ALL=Show all +LOADER_GUI_SHOW_INTERACTIONS=Show only Interactions +LOADER_GUI_SHOW_WAITS=Show only Waits +LOADER_GUI_SHOW_WAITS_BETWEEN_TNT=Show only Waits between TNT +LOADER_GUI_SHOW_TNT=Show TNT LOADER_GUI_SHOW_WAITS_SET_ALL=§7Wait Time all LOADER_GUI_SHOW_WAITS_TITLE=§7Wait Time LOADER_GUI_SETTINGS_TITLE=Settings +LOADER_GUI_COPY_TITLE=Copy amount LOADER_GUI_SETTINGS_BACK=§8Back +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=§7Klicke zum editieren +LOADER_GUI_CLICK_TO_EDIT=§7Click to edit LOADER_GUI_ITEM_NAME=§7{0}§8: §e{1} LOADER_SETTING_NAME=§7{0} -LOADER_SETTING_MODES=§7Modi§8: §e{0} -LOADER_SETTING_POWER=§7Redstone Stärke§8: §e{0} +LOADER_SETTING_MODES=§7Modes§8: §e{0} +LOADER_SETTING_POWER=§7Power§8: §e{0} LOADER_SETTING_TICKS=§7Ticks§8: §e{0} LOADER_SETTING_REPEATER=§7Repeater§8: §e{0} -LOADER_SETTING_WAIT=§7Wartezeit§8: §e{0} Tick(s) -LOADER_SETTING_WAIT_NAME=Wartezeit +LOADER_SETTING_WAIT=§7Wait§8: §e{0} Tick(s) +LOADER_SETTING_WAIT_NAME=Wait LOADER_SETTING_TICKS_NAME=Ticks LOADER_SETTING_TICKS_REMOVE_ONE=§c-1 LOADER_SETTING_TICKS_REMOVE_ONE_SHIFT=§7Shift§8: §c-5 @@ -607,18 +603,21 @@ LOADER_SETTING_TNT_X=§7X§8: §e{0} LOADER_SETTING_TNT_Y=§7Y§8: §e{0} LOADER_SETTING_TNT_Z=§7Z§8: §e{0} LOADER_INTERACTION_NOOP=NOOP -LOADER_INTERACTION_INTERACT=Interagiere -LOADER_INTERACTION_POWERED=Aktiviert -LOADER_INTERACTION_UNPOWERED=Deaktiviert -LOADER_INTERACTION_PAGE_PREV=Vorherige Seite -LOADER_INTERACTION_PAGE_NEXT=Nächste Seite -LOADER_INTERACTION_PAGE=Seite {0} -LOADER_INTERACTION_ACTIVE=Aktiviert -LOADER_INTERACTION_INACTIVE=Deaktiviert -LOADER_INTERACTION_WAIT_FOR=Darauf warten -LOADER_INTERACTION_NO_WAIT_FOR=Nicht darauf warten -LOADER_INTERACTION_OPEN=Geöffnet -LOADER_INTERACTION_CLOSED=Geschlossen +LOADER_INTERACTION_PLACE=Place +LOADER_INTERACTION_INTERACT=Interact +LOADER_INTERACTION_POWERED=Powered +LOADER_INTERACTION_UNPOWERED=Unpowered +LOADER_INTERACTION_PAGE_PREV=Previous Page +LOADER_INTERACTION_PAGE_NEXT=Next Page +LOADER_INTERACTION_PAGE=Page {0} +LOADER_INTERACTION_ACTIVE=Active +LOADER_INTERACTION_INACTIVE=Inactive +LOADER_INTERACTION_WAIT_FOR=Wait for +LOADER_INTERACTION_NO_WAIT_FOR=No wait for +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 @@ -709,6 +708,12 @@ OTHER_TPS_HEAD = §7TPS: 1s 10s 1m 5m 10m OTHER_TPS_MESSAGE = §7 §e{0}§7 §e{1}§7 §e{2}§7 §e{3}§7 §e{4} OTHER_TPS_SINGLE = §8TPS: §e{0} OTHER_WORLDSPAWN_HELP=§8/§eworldspawn §8-§e Teleport to the spawn +OTHER_BIND_HELP=§8/§ebind §8[§7Command§8] §8-§e Bind a command on item interaction +OTHER_BIND_ERROR=§cInvalid or unknown command +OTHER_BIND_UNBINDABLE=§cCould not bind command +OTHER_BIND_LORE=§eCommand§8:§7 {0} +OTHER_BIND_MESSAGE_BIND=§7Bound command §e{0} §7to item +OTHER_BIND_MESSAGE_UNBIND=§7Unbound command # DebugStick DEBUG_STICK_COMMAND_HELP=§8/§edebugstick §8-§7 receive a debugstick DEBUG_STICK_NAME=§eDebugstick @@ -786,10 +791,12 @@ REGION_ITEM_RESET=§eReset REGION_ITEM_TESTBLOCK=§eDummy REGION_ITEM_TNT_OFF=§7TNT: §eDeactivated REGION_ITEM_TNT_ONLY_TB=§7TNT: §eonly dummy +REGION_ITEM_TNT_ONLY_BUILD=§7TNT: §eonly build REGION_ITEM_TNT_ON=§7TNT: §eActivated REGION_ITEM_SELECTOR_TITLE=Tnt Mode REGION_ITEM_SELECTOR_ON=§eActivate REGION_ITEM_SELECTOR_ONLY_TB=§eonly dummy +REGION_ITEM_SELECTOR_ONLY_BUILD=§eonly build REGION_ITEM_SELECTOR_OFF=§eDeactivate #Region REGION_COLOR_HELP_COLOR=§8/§ecolor §8[§7Color§8] §8- §7Sets the color of the region @@ -873,8 +880,10 @@ REGION_TNT_HELP_MODE=§8/§etnt §8[§7Mode§8] §8- §7Set TNT behaviour to a g REGION_TNT_ON=§aTNT-Damage activated REGION_TNT_OFF=§cTNT-Damage deactivated REGION_TNT_TB=§aTNT-Damage activated outside the building area +REGION_TNT_BUILD=§aTNT-Damage activated outside the testblok area REGION_TNT_NO_PERMS=§cYou are not allowed to toggle tnt damage here -REGION_TNT_BUILD=§cAn explosion would have destroyed blocks in the building 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 5 minutes. AFK_WARNING_MESSAGE=§cThis server will stop in one minute if you remain inactive diff --git a/BauSystem_Main/src/BauSystem_de.properties b/BauSystem_Main/src/BauSystem_de.properties index b7496d63..368721b8 100644 --- a/BauSystem_Main/src/BauSystem_de.properties +++ b/BauSystem_Main/src/BauSystem_de.properties @@ -60,6 +60,7 @@ 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 @@ -104,8 +105,8 @@ AUTOSTART_ITEM_LORE = §eRechtsklick Block §8- §7Starte den Timer AUTOSTART_MESSAGE_NO_REGION = §cDu befindest dich derzeit in keiner Region AUTOSTART_MESSAGE_RESET = §eDer AutostartTimer wurde zurückgesetzt AUTOSTART_MESSAGE_START = §eAutostartTimer gestartet -AUTOSTART_MESSAGE_RESULT1 = §eZeit §7bis zur §eExplosion §7am Gegner§8:§e {0} -AUTOSTART_MESSAGE_RESULT2 = §eZeitdifferenz in ticks §7bis {0} Sekunden§8:§e {1} +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 @@ -144,15 +145,15 @@ 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: §e{0} -BAU_INFO_COMMAND_MEMBER = §7Mitglieder: §e +BAU_INFO_COMMAND_OWNER = §7Besitzer§8: §e{0} +BAU_INFO_COMMAND_MEMBER = §7Mitglieder §8[§7{0}§8]§8: §e BAU_INFO_MEMBER_INFO = §e{0}§8[{1}§8,{2}§8] §8 BAU_INFO_MEMBER_WE_ALLOW = §aWE BAU_INFO_MEMBER_WE_DISALLOW = §cWE BAU_INFO_MEMBER_WORLD_ALLOW = §aW BAU_INFO_MEMBER_WORLD_DISALLOW = §cW -BAU_INFO_COMMAND_FLAG = §e{0} §8: §7{1} -BAU_INFO_COMMAND_TPS = TPS:§e +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 @@ -165,10 +166,10 @@ 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 wo Endstone ist +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 ist aktiviert -DESIGN_ENDSTONE_DISABLE = §cEndstone ist deaktiviert +DESIGN_ENDSTONE_ENABLE = §aEndstone im Design ist angezeigt +DESIGN_ENDSTONE_DISABLE = §cEndstone im Design ist versteckt # Detonator DETONATOR_LOC_REMOVE = §e{0} entfernt @@ -457,14 +458,19 @@ 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_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_ISOLATE = §aTNT-Positionen isoliert -TRACE_MESSAGE_UNISOLATE = §cTNT-Positionen ausgeblendet TRACE_MESSAGE_CLICK_ISOLATE = §eKlicken zum §aisolieren§8/§causblenden TRACE_MESSAGE_DISALLOWED = §cDu darfst hier nicht den TNT-Tracer nutzen @@ -472,15 +478,10 @@ TRACE_COMMAND_HELP_START = §8/§etrace start §8- §7Startet die Aufnahme aller 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_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_GUI = §8/§etrace gui §8- §7Zeigt die Trace Oberfläche an -TRACE_COMMAND_HELP_REPLAY = §8/§etrace replay §8[§7Tick§8] §8- §7Replayes die Aufnahme -TRACE_COMMAND_HELP_REPLAY_DISABLE = §8/§etrace replay disable §8- §7Stoppt das Replay -TRACE_COMMAND_HELP_REPLAY_NEXT = §8/§etrace replay next §8[§7Step§8] §8- §7Springe einen§8/§7step Tick vor -TRACE_COMMAND_HELP_REPLAY_PREVIOUS = §8/§etrace replay previous §8[§7Step§8] §8- §7Springe einen§8/§7step Tick zurück -TRACE_COMMAND_HELP_REPLAY_LOOP = §8/§etrace replay loop §8<§7start§8> §8<§7end§8> §8[§7speed§8] §8- §7Spielt die Aufnahme in einer Schleife ab TRACE_GUI_ITEM_NAME = §eTracer TRACE_GUI_ITEM_LORE = §7Status§8: {0} @@ -492,19 +493,6 @@ TRACE_GUI_AUTO_TRACE_INACTIVE = §eAuto-Tracer Aktivieren TRACE_GUI_AUTO_TRACE_ACTIVE = §eAuto-Tracer Deaktivieren TRACE_GUI_DELETE = §eTrace Löschen -TRACE_GUI_TITLE = Trace GUI -TRACE_GUI_ITEM_BACK = §eBack -TRACE_GUI_ITEM = §eTrace §8- §e{0} §7TNT -TRACE_GUI_CLEAR = §eTraces löschen -TRACE_GUI_RECORD_ITEM = §eTNT §8- §e{0} §7Positionen -TRACE_GUI_RECORD_CLEAR = §eTNT löschen -TRACE_GUI_POSITION_ITEM = §ePosition -TRACE_GUI_POSITION_X = §7X§8: §e{0} -TRACE_GUI_POSITION_Y = §7Y§8: §e{0} -TRACE_GUI_POSITION_Z = §7Z§8: §e{0} -TRACE_GUI_POSITION_SOURCE = §7Ursprung§8: §e{0} -TRACE_GUI_POSITION_EXPLODED = §7Explodiert§8: §e{0} - # Loader LOADER_SETUP = §eEinrichtung LOADER_RUNNING = §aLaufend @@ -534,36 +522,45 @@ LOADER_HELP_START=§8/§eloader start §8- §7Spielt die zuvor aufgenommenen Akt 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 +LOADER_HELP_WAIT=§8/§7loader wait §8[§7Ticks§8] - §7Setzt die Wartezeit zwischen Schüssen +LOADER_HELP_SPEED=§8/§7loader speed §8[§7Ticks§8] - §7Setzt die Wartezeit zwischen Aktionen LOADER_NO_LOADER=§cDu hast noch keinen Loader. Erstelle dir einen mit /loader setup LOADER_NEW=§7Belade und feuer einmal die Kanone ab, um den Loader zu initialisieren. 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_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_PERMS=§cDu darfst hier nicht den Detonator nutzen LOADER_NOTHING_RECORDED=§cEs wurden keine Elemente aufgenommen! LOADER_GUI_TITLE=Loader Einstellungen -LOADER_GUI_SHOW_INTERACTIONS=§eZeige Interaktionen -LOADER_GUI_SHOW_WAITS=§eZeige Wartezeiten -LOADER_GUI_SHOW_WAITS_SET_BETWEEN_TNT=§7Wait Time zwischen TNT +LOADER_GUI_SHOW_ALL=Zeige alles +LOADER_GUI_SHOW_INTERACTIONS=Zeige Interaktionen +LOADER_GUI_SHOW_WAITS=Zeige Wartezeiten +LOADER_GUI_SHOW_WAITS_BETWEEN_TNT=Zeige Wartezeiten zwischen TNT +LOADER_GUI_SHOW_TNT=Zeige TNT LOADER_GUI_SHOW_WAITS_SET_ALL=§7Wait Time alle LOADER_GUI_SHOW_WAITS_TITLE=§7Wartezeit LOADER_GUI_SETTINGS_TITLE=Einstellungen +LOADER_GUI_COPY_TITLE=Anzahl Kopien LOADER_GUI_SETTINGS_BACK=§8Zurück +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=§7Click to edit +LOADER_GUI_CLICK_TO_EDIT=§7Klicke zum editieren LOADER_GUI_ITEM_NAME=§7{0}§8: §e{1} LOADER_SETTING_NAME=§7{0} -LOADER_SETTING_MODES=§7Modes§8: §e{0} -LOADER_SETTING_POWER=§7Power§8: §e{0} +LOADER_SETTING_MODES=§7Modi§8: §e{0} +LOADER_SETTING_POWER=§7Redstone Stärke§8: §e{0} LOADER_SETTING_TICKS=§7Ticks§8: §e{0} LOADER_SETTING_REPEATER=§7Repeater§8: §e{0} -LOADER_SETTING_WAIT=§7Wait§8: §e{0} Tick(s) -LOADER_SETTING_WAIT_NAME=Wait +LOADER_SETTING_WAIT=§7Wartezeit§8: §e{0} Tick(s) +LOADER_SETTING_WAIT_NAME=Wartezeit LOADER_SETTING_TICKS_NAME=Ticks LOADER_SETTING_TICKS_REMOVE_ONE=§c-1 LOADER_SETTING_TICKS_REMOVE_ONE_SHIFT=§7Shift§8: §c-5 @@ -574,18 +571,21 @@ LOADER_SETTING_TNT_X=§7X§8: §e{0} LOADER_SETTING_TNT_Y=§7Y§8: §e{0} LOADER_SETTING_TNT_Z=§7Z§8: §e{0} LOADER_INTERACTION_NOOP=NOOP -LOADER_INTERACTION_INTERACT=Interact -LOADER_INTERACTION_POWERED=Powered -LOADER_INTERACTION_UNPOWERED=Unpowered -LOADER_INTERACTION_PAGE_PREV=Previous Page -LOADER_INTERACTION_PAGE_NEXT=Next Page -LOADER_INTERACTION_PAGE=Page {0} -LOADER_INTERACTION_ACTIVE=Active -LOADER_INTERACTION_INACTIVE=Inactive -LOADER_INTERACTION_WAIT_FOR=Wait for -LOADER_INTERACTION_NO_WAIT_FOR=No wait for -LOADER_INTERACTION_OPEN=Open -LOADER_INTERACTION_CLOSED=Closed +LOADER_INTERACTION_PLACE=Platzieren +LOADER_INTERACTION_INTERACT=Interagiere +LOADER_INTERACTION_POWERED=Aktiviert +LOADER_INTERACTION_UNPOWERED=Deaktiviert +LOADER_INTERACTION_PAGE_PREV=Vorherige Seite +LOADER_INTERACTION_PAGE_NEXT=Nächste Seite +LOADER_INTERACTION_PAGE=Seite {0} +LOADER_INTERACTION_ACTIVE=Aktiviert +LOADER_INTERACTION_INACTIVE=Deaktiviert +LOADER_INTERACTION_WAIT_FOR=Darauf warten +LOADER_INTERACTION_NO_WAIT_FOR=Nicht darauf warten +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 @@ -674,6 +674,11 @@ OTHER_TIME_RESULT=§7§oWhooosh OTHER_TPS_HEAD = §7TPS: 1s 10s 1m 5m 10m OTHER_TPS_MESSAGE = §7 §e{0}§7 §e{1}§7 §e{2}§7 §e{3}§7 §e{4} OTHER_TPS_SINGLE = §8TPS: §e{0} +OTHER_BIND_HELP=§8/§ebind §8[§7Command§8] §8-§e Binde ein Befehl auf Item Interaktion +OTHER_BIND_ERROR=§cFalscher oder unbekannter Befehl +OTHER_BIND_UNBINDABLE=§cBefehl konnte nicht gebunden werden +OTHER_BIND_MESSAGE_BIND=§7Befehl §e{0} §7ans Item gebunden +OTHER_BIND_MESSAGE_UNBIND=§7Befehl entbunden # DebugStick DEBUG_STICK_COMMAND_HELP=§8/§edebugstick §8-§7 Erhalte einen DebugStick DEBUG_STICK_NAME=§eDebugstick @@ -749,10 +754,12 @@ REGION_ITEM_RESET=§eReset REGION_ITEM_TESTBLOCK=§eTestblock REGION_ITEM_TNT_OFF=§7TNT: §eAusgeschaltet REGION_ITEM_TNT_ONLY_TB=§7TNT: §enur Testblock +REGION_ITEM_TNT_ONLY_BUILD=§7TNT: §enur Baubereich REGION_ITEM_TNT_ON=§7TNT: §eEingeschaltet REGION_ITEM_SELECTOR_TITLE=Tnt Modus REGION_ITEM_SELECTOR_ON=§eEinschalten REGION_ITEM_SELECTOR_ONLY_TB=§enur Testblock +REGION_ITEM_SELECTOR_ONLY_BUILD=§enur Baubereich REGION_ITEM_SELECTOR_OFF=§eAusschalten #Region REGION_COLOR_HELP_COLOR=§8/§ecolor §8[§7Color§8] §8- §7Setze die Farbe der Region @@ -837,7 +844,8 @@ REGION_TNT_ON=§aTNT-Schaden aktiviert REGION_TNT_OFF=§cTNT-Schaden deaktiviert REGION_TNT_TB=§aTNT-Schaden außerhalb Baurahmen aktiviert REGION_TNT_NO_PERMS=§cDu darfst hier nicht TNT-Schaden (de-)aktivieren -REGION_TNT_BUILD=§cEine Explosion hätte Blöcke im Baubereich zerstört +REGION_TNT_BUILD_DESTROY=§cEine Explosion hätte Blöcke im Baubereich zerstört +REGION_TNT_TB_DESTROY=§cEine Explosion hätte Blöcke im Testblockbereich zerstört AFK_KICK_MESSAGE=§cAuf diesem Server ist seit 5 Minuten nichts passiert. AFK_WARNING_MESSAGE=§cDieser Server wird bei weiterer Inaktivität in einer Minute gestoppt diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/attributescopy/AttributeRemoveCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/attributescopy/AttributeRemoveCommand.java index 4f1bdd92..11cacde1 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/attributescopy/AttributeRemoveCommand.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/attributescopy/AttributeRemoveCommand.java @@ -73,7 +73,7 @@ public class AttributeRemoveCommand extends SWCommand { BauSystem.MESSAGE.send("ATTRIBUTE_REMOVE_NOT_FOUND", player); return; } - lore.removeIf(s -> s.equals("§8-§7 " + attribute)); + lore.removeIf(s -> s.startsWith("§8-§7 " + attribute + "§8:")); if (lore.size() == 1) { itemStack.setItemMeta(null); } else { @@ -99,15 +99,13 @@ public class AttributeRemoveCommand extends SWCommand { return lore.stream() .skip(1) .map(s1 -> s1.substring(6)) - .map(s1 -> s1.replace('§', '&')) - .map(s1 -> s1.replace(' ', '_')) + .map(s1 -> s1.substring(0, s1.indexOf("§8:"))) .collect(Collectors.toList()); } @Override public String map(CommandSender commandSender, PreviousArguments previousArguments, String s) { - return s.replace('_', ' ') - .replace('&', '§'); + return s; } }; } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/autostart/AutostartListener.java b/BauSystem_Main/src/de/steamwar/bausystem/features/autostart/AutostartListener.java index 66f53359..232962a1 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/autostart/AutostartListener.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/autostart/AutostartListener.java @@ -30,10 +30,12 @@ import de.steamwar.inventory.SWItem; import de.steamwar.linkage.Linked; import lombok.Getter; import org.bukkit.Material; +import org.bukkit.block.data.type.Chest; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.entity.EntityExplodeEvent; +import org.bukkit.event.inventory.InventoryCloseEvent; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.ItemStack; @@ -70,9 +72,28 @@ public class AutostartListener implements Listener { if (event.getClickedBlock() == null) { return; } + if (event.getClickedBlock().getBlockData() instanceof Chest) { + return; + } activate(event.getPlayer()); } + @EventHandler + public void onInventoryClose(InventoryCloseEvent event) { + if (!(event.getPlayer() instanceof Player)) { + return; + } + if (!ItemUtils.isItem(event.getPlayer().getInventory().getItemInMainHand(), "autostart")) { + return; + } + if (event.getInventory().getLocation() == null) { + return; + } + if (event.getInventory().getLocation().getBlock().getBlockData() instanceof Chest) { + activate((Player) event.getPlayer()); + } + } + public void activate(Player player) { Region region = Region.getRegion(player.getLocation()); if (region.isGlobal()) { @@ -102,9 +123,7 @@ public class AutostartListener implements Listener { if (!region.hasType(RegionType.TESTBLOCK)) return; if (!region.inRegion(block.getLocation(), RegionType.TESTBLOCK, RegionExtensionType.EXTENSION)) return; long tickDiff = TPSUtils.currentRealTick.get() - regionStartTime.remove(region); - RegionUtils.message(region, player -> { - return BauSystem.MESSAGE.parse("AUTOSTART_MESSAGE_RESULT1", player, new SimpleDateFormat(BauSystem.MESSAGE.parse("AUTOSTART_MESSAGE_DATE_PATTERN", player)).format(new Date(tickDiff * 50))); - }); + RegionUtils.message(region, "AUTOSTART_MESSAGE_RESULT1", tickDiff); RegionUtils.message(region, "AUTOSTART_MESSAGE_RESULT2", 30, (600 - tickDiff)); RegionUtils.message(region, "AUTOSTART_MESSAGE_RESULT3"); }); diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/bau/InfoCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/bau/InfoCommand.java index b3de2a11..53acafeb 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/bau/InfoCommand.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/bau/InfoCommand.java @@ -52,7 +52,7 @@ public class InfoCommand extends SWCommand { List members = BauweltMember.getMembers(bauServer.getOwnerID()); StringBuilder membermessage = new StringBuilder(); - membermessage.append(BauSystem.MESSAGE.parsePrefixed("BAU_INFO_COMMAND_MEMBER", p)); + membermessage.append(BauSystem.MESSAGE.parsePrefixed("BAU_INFO_COMMAND_MEMBER", p, members.size())); for (BauweltMember member : members) { membermessage.append(BauSystem.MESSAGE.parse("BAU_INFO_MEMBER_INFO", p, diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/cannon/CannonDetector.java b/BauSystem_Main/src/de/steamwar/bausystem/features/cannon/CannonDetector.java index 09893fd5..3ab4fe70 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/cannon/CannonDetector.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/cannon/CannonDetector.java @@ -28,28 +28,29 @@ import de.steamwar.linkage.Linked; import org.bukkit.Bukkit; 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.util.Vector; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; @Linked public class CannonDetector implements Listener { private Map velocities = new HashMap<>(); + private Map> propulsionOfProjectile = new HashMap<>(); - @EventHandler + @EventHandler(priority = EventPriority.LOW) public void onEntityExplode(EntityExplodeEvent event) { if (!(event.getEntity() instanceof TNTPrimed)) { return; } TNTPrimed tnt = (TNTPrimed) event.getEntity(); + propulsionOfProjectile.remove(tnt); + DepthManager.update(tnt, event.blockList()); List tnts = Bukkit.getWorlds().get(0).getEntitiesByClass(TNTPrimed.class) @@ -66,6 +67,7 @@ public class CannonDetector implements Listener { boolean isEmpty = velocities.isEmpty(); tnts.forEach(tntPrimed -> { velocities.put(tntPrimed, tntPrimed.getVelocity().clone()); + propulsionOfProjectile.computeIfAbsent(tntPrimed, __ -> new HashSet<>()).add(tnt.getUniqueId()); }); if (!isEmpty) { @@ -75,7 +77,10 @@ public class CannonDetector implements Listener { BauSystem.runTaskLater(BauSystem.getInstance(), () -> { Map> grouped = new HashMap<>(); velocities.forEach((tntPrimed, vector) -> { - grouped.computeIfAbsent(new CannonKey(round(tntPrimed.getLocation().toVector()), round(vector)), ignored -> new ArrayList<>()).add(tntPrimed); + boolean xBiggest = Math.abs(vector.getX()) > Math.abs(vector.getZ()); + boolean zBiggest = Math.abs(vector.getZ()) > Math.abs(vector.getX()); + Vector vec = new Vector(xBiggest ? Math.signum(vector.getX()) : 0, Math.round(vector.getY() * 100), zBiggest ? Math.signum(vector.getZ()) : 0); + grouped.computeIfAbsent(new CannonKey(propulsionOfProjectile.get(tntPrimed), vec), ignored -> new ArrayList<>()).add(tntPrimed); }); grouped.forEach((cannonKey, tntPrimeds) -> { if (tntPrimeds.size() <= 5) return; @@ -88,12 +93,4 @@ public class CannonDetector implements Listener { velocities.clear(); }, 1); } - - private Vector round(Vector vector) { - vector.multiply(10000); - vector.setX(Math.round(vector.getX())); - vector.setY(Math.round(vector.getY())); - vector.setZ(Math.round(vector.getZ())); - return vector; - } } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/cannon/CannonKey.java b/BauSystem_Main/src/de/steamwar/bausystem/features/cannon/CannonKey.java index 73270eab..c260e8a9 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/cannon/CannonKey.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/cannon/CannonKey.java @@ -22,12 +22,16 @@ package de.steamwar.bausystem.features.cannon; import lombok.AllArgsConstructor; import lombok.EqualsAndHashCode; import lombok.Getter; +import org.bukkit.entity.TNTPrimed; import org.bukkit.util.Vector; +import java.util.Set; +import java.util.UUID; + @AllArgsConstructor @EqualsAndHashCode @Getter public final class CannonKey { - private Vector locationVector; + private Set propulsions; private Vector velocityVector; } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/cannon/depth/Depth.java b/BauSystem_Main/src/de/steamwar/bausystem/features/cannon/depth/Depth.java index 506b6e93..a13d6250 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/cannon/depth/Depth.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/cannon/depth/Depth.java @@ -51,7 +51,6 @@ public class Depth { List blocksList = blocks.stream() .filter(block -> region.inRegion(block.getLocation(), RegionType.TESTBLOCK, RegionExtensionType.EXTENSION)) .collect(Collectors.toList()); - if (blocksList.isEmpty()) return; tntCount++; for (Block block : blocksList) { internalUpdate(block); diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/design/endstone/DesignEndStone.java b/BauSystem_Main/src/de/steamwar/bausystem/features/design/endstone/DesignEndStone.java index b2c83c7e..fd9899f8 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/design/endstone/DesignEndStone.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/design/endstone/DesignEndStone.java @@ -55,7 +55,7 @@ public class DesignEndStone { this.maxZ = region.getMaxPointBuild().getZ(); } - private void calc() { + public void calc() { entities.forEach(REntity::die); entities.clear(); locations.clear(); @@ -98,12 +98,17 @@ public class DesignEndStone { if (players.contains(player)) { players.remove(player); entityServer.removePlayer(player); - BauSystem.MESSAGE.send("DESIGN_ENDSTONE_DISABLE", player, ChatMessageType.ACTION_BAR); + BauSystem.MESSAGE.sendPrefixless("DESIGN_ENDSTONE_DISABLE", player, ChatMessageType.ACTION_BAR); } else { players.add(player); entityServer.addPlayer(player); calc(); - BauSystem.MESSAGE.send("DESIGN_ENDSTONE_ENABLE", player, ChatMessageType.ACTION_BAR); + BauSystem.MESSAGE.sendPrefixless("DESIGN_ENDSTONE_ENABLE", player, ChatMessageType.ACTION_BAR); } } + + public boolean removePlayer(Player player) { + players.remove(player); + return players.isEmpty(); + } } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/design/endstone/DesignEndStoneCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/design/endstone/DesignEndStoneCommand.java index 56b2d419..bafa3206 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/design/endstone/DesignEndStoneCommand.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/design/endstone/DesignEndStoneCommand.java @@ -24,13 +24,19 @@ import de.steamwar.bausystem.region.Region; import de.steamwar.bausystem.region.utils.RegionType; import de.steamwar.command.SWCommand; import de.steamwar.linkage.Linked; +import org.bukkit.Location; import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.player.PlayerQuitEvent; import java.util.HashMap; import java.util.Map; @Linked -public class DesignEndStoneCommand extends SWCommand { +public class DesignEndStoneCommand extends SWCommand implements Listener { public DesignEndStoneCommand() { super("designendstone"); @@ -47,4 +53,37 @@ public class DesignEndStoneCommand extends SWCommand { } designEndStoneMap.computeIfAbsent(region, DesignEndStone::new).toggle(player); } + + @EventHandler + public void onPlayerQuit(PlayerQuitEvent event) { + Region region = Region.getRegion(event.getPlayer().getLocation()); + DesignEndStone designEndStone = designEndStoneMap.get(region); + if (designEndStone == null) { + return; + } + if (designEndStone.removePlayer(event.getPlayer())) { + designEndStoneMap.remove(region); + } + } + + @EventHandler + public void onBlockPlace(BlockPlaceEvent event) { + update(event.getBlock().getLocation()); + } + + @EventHandler + public void onBlockBreak(BlockBreakEvent event) { + BauSystem.runTaskLater(BauSystem.getInstance(), () -> { + update(event.getBlock().getLocation()); + }, 1); + } + + private void update(Location location) { + Region region = Region.getRegion(location); + DesignEndStone designEndStone = designEndStoneMap.get(region); + if (designEndStone == null) { + return; + } + designEndStone.calc(); + } } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/killchecker/KillcheckerVisualizer.java b/BauSystem_Main/src/de/steamwar/bausystem/features/killchecker/KillcheckerVisualizer.java index 6d4b8af2..d7c89254 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/killchecker/KillcheckerVisualizer.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/killchecker/KillcheckerVisualizer.java @@ -48,7 +48,7 @@ public class KillcheckerVisualizer { private static final Material[] MATERIALS = new Material[] {Material.YELLOW_STAINED_GLASS, Material.ORANGE_STAINED_GLASS, Material.RED_STAINED_GLASS, Material.PURPLE_STAINED_GLASS, Material.BLACK_STAINED_GLASS}; private static final World WORLD = Bukkit.getWorlds().get(0); - private static final double SURROUND = 4; + private static final double SURROUND = 4.5; private final Point minPoint; private final Point maxPoint; diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/loader/Loader.java b/BauSystem_Main/src/de/steamwar/bausystem/features/loader/Loader.java index 8cea017b..22e0df02 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/loader/Loader.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/loader/Loader.java @@ -35,9 +35,11 @@ import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; +import org.bukkit.event.inventory.ClickType; import org.bukkit.event.player.PlayerQuitEvent; import java.util.*; +import java.util.concurrent.atomic.AtomicBoolean; public class Loader implements Listener { @@ -72,18 +74,19 @@ public class Loader implements Listener { waitTime--; return; } + if (currentElement >= elements.size()) { + currentElement = 0; + } while (currentElement < elements.size()) { LoaderElement element = elements.get(currentElement); currentElement++; element.execute(delay -> waitTime = delay); if (waitTime > 0) { - break; + if (element instanceof LoaderTNT) currentElement--; + return; } } - if (currentElement >= elements.size()) { - currentElement = 0; - } }, 0, 1); } @@ -121,27 +124,67 @@ public class Loader implements Listener { LOADER_MAP.remove(p); } + public boolean setTicksBetweenShots(int delay) { + if (elements.size() == 0) return false; + LoaderElement loaderElement = elements.get(elements.size() - 1); + if (loaderElement instanceof LoaderWait) { + ((LoaderWait) loaderElement).setDelay(delay); + return true; + } + return false; + } + + public void setTicksBetweenBlocks(int delay) { + for (int i = 0; i < elements.size() - 1; i++) { + LoaderElement loaderElement = elements.get(i); + if (loaderElement instanceof LoaderWait) { + ((LoaderWait) loaderElement).setDelay(delay); + } + } + } + public void gui(SettingsSorting settingsSorting) { List> list = new ArrayList<>(); + AtomicBoolean allWait = new AtomicBoolean(true); Runnable updateRunnable = () -> { list.clear(); - for (LoaderElement element : elements) { - if (settingsSorting != null) { - if (settingsSorting == SettingsSorting.WAIT && !(element instanceof LoaderWait)) { - continue; - } - if (settingsSorting == SettingsSorting.INTERACTIONS && (element instanceof LoaderWait || element instanceof LoaderTNT)) { - continue; - } + for (int i = 0; i < elements.size(); i++) { + LoaderElement previous = i > 0 ? elements.get(i - 1) : null; + LoaderElement current = elements.get(i); + LoaderElement next = i < elements.size() - 1 ? elements.get(i + 1) : null; + + if (!settingsSorting.shouldShow(previous, current, next)) { + continue; } - SWItem item = element.menu(p); - if (element instanceof LoaderInteractionElement) { - LoaderInteractionElement interactionElement = (LoaderInteractionElement) element; - item.setLore(Arrays.asList(BauSystem.MESSAGE.parse("LOADER_SETTING_MODES", p, interactionElement.size()), "§8", BauSystem.MESSAGE.parse("LOADER_GUI_CLICK_TO_EDIT", p))); + + if ((!(current instanceof LoaderWait))) { + allWait.set(false); + } + + SWItem item = current.menu(p); + if (current instanceof LoaderInteractionElement) { + LoaderInteractionElement interactionElement = (LoaderInteractionElement) current; + List lore = new ArrayList<>(); + if (item.getItemMeta() != null && item.getItemMeta().getLore() != null) { + lore.addAll(item.getItemMeta().getLore()); + lore.add("§8"); + } + lore.add(BauSystem.MESSAGE.parse("LOADER_SETTING_MODES", p, interactionElement.size())); + lore.add(BauSystem.MESSAGE.parse("LOADER_GUI_CLICK_TO_EDIT", p)); + item.setLore(lore); } else { - item.setLore(Arrays.asList(BauSystem.MESSAGE.parse("LOADER_GUI_CLICK_TO_EDIT", p))); + List lore = new ArrayList<>(); + if (item.getItemMeta() != null && item.getItemMeta().getLore() != null) { + lore.addAll(item.getItemMeta().getLore()); + lore.add("§8"); + } + lore.add(BauSystem.MESSAGE.parse("LOADER_GUI_CLICK_TO_EDIT", p)); + item.setLore(lore); } - list.add(new SWListInv.SWListEntry<>(item, element)); + list.add(new SWListInv.SWListEntry<>(item, current)); + } + if (list.isEmpty()) { + allWait.set(false); } }; updateRunnable.run(); @@ -152,65 +195,51 @@ public class Loader implements Listener { swListInv.open(); })); - SWItem onlyInteractionsElements = new SWItem(Material.REPEATER, BauSystem.MESSAGE.parse("LOADER_GUI_SHOW_INTERACTIONS", p), clickType -> { - gui(settingsSorting == SettingsSorting.INTERACTIONS ? null : SettingsSorting.INTERACTIONS); + SWItem settingItem = new SWItem(settingsSorting.getMaterial(), "§e" + BauSystem.MESSAGE.parse(settingsSorting.getName(), p), clickType -> { + if (clickType == ClickType.LEFT) { + int index = settingsSorting.ordinal() + 1; + if (index >= SettingsSorting.LENGTH) { + index = 0; + } + gui(SettingsSorting.values()[index]); + } else if (clickType == ClickType.RIGHT) { + int index = settingsSorting.ordinal() - 1; + if (index < 0) { + index = SettingsSorting.LENGTH - 1; + } + gui(SettingsSorting.values()[index]); + } }); - if (settingsSorting == SettingsSorting.INTERACTIONS) onlyInteractionsElements.setEnchanted(true); - swListInv.setItem(47, onlyInteractionsElements); - - SWItem onlyWaitElements = new SWItem(Material.CLOCK, BauSystem.MESSAGE.parse("LOADER_GUI_SHOW_WAITS", p), clickType -> { - gui(settingsSorting == SettingsSorting.WAIT ? null : SettingsSorting.WAIT); - }); - if (settingsSorting == SettingsSorting.WAIT) onlyWaitElements.setEnchanted(true); - swListInv.setItem(48, onlyWaitElements); - - if (settingsSorting == SettingsSorting.WAIT) { - SWItem waitBetweenTNT = new SWItem(Material.TNT, BauSystem.MESSAGE.parse("LOADER_GUI_SHOW_WAITS_SET_BETWEEN_TNT", p), clickType -> { - SWAnvilInv swAnvilInv = new SWAnvilInv(p, BauSystem.MESSAGE.parse("LOADER_GUI_SHOW_WAITS_TITLE", p), ""); - swAnvilInv.setCallback(s -> { - try { - long delay = Long.parseLong(s); - if (delay < 0) delay = 0; - for (int i = 1; i < elements.size() - 1; i++) { - if (!(elements.get(i - 1) instanceof LoaderTNT)) continue; - if (!(elements.get(i + 1) instanceof LoaderTNT)) continue; - if (!(elements.get(i) instanceof LoaderWait)) continue; - ((LoaderWait) elements.get(i)).setDelay(delay); - } - } catch (NumberFormatException ignored) { - } - gui(settingsSorting); - }); - updateRunnable.run(); - swAnvilInv.open(); - }); - swListInv.setItem(50, waitBetweenTNT); - - SWItem waitTime = new SWItem(Material.PAPER, BauSystem.MESSAGE.parse("LOADER_GUI_SHOW_WAITS_SET_ALL", p), clickType -> { - SWAnvilInv swAnvilInv = new SWAnvilInv(p, BauSystem.MESSAGE.parse("LOADER_GUI_SHOW_WAITS_TITLE", p), ""); - swAnvilInv.setCallback(s -> { - try { - long delay = Long.parseLong(s); - if (delay < 0) delay = 0; - long finalDelay = delay; - elements.stream() - .filter(LoaderWait.class::isInstance) - .map(LoaderWait.class::cast) - .forEach(loaderWait -> loaderWait.setDelay(finalDelay)); - } catch (NumberFormatException ignored) { - } - gui(settingsSorting); - }); - updateRunnable.run(); - swAnvilInv.open(); - }); - swListInv.setItem(51, waitTime); - } else { - SWItem empty = new SWItem(Material.STRUCTURE_VOID, "§7", clickType -> {}); - swListInv.setItem(50, empty); - swListInv.setItem(51, empty); + List strings = new ArrayList<>(); + for (SettingsSorting setting : SettingsSorting.values()) { + if (setting == settingsSorting) { + strings.add("§e> §7" + BauSystem.MESSAGE.parse(setting.getName(), p)); + } else { + strings.add("§8> §7" + BauSystem.MESSAGE.parse(setting.getName(), p)); + } } + settingItem.setLore(strings); + swListInv.setItem(48, settingItem); + if (allWait.get()) { + SWItem setWait = new SWItem(Material.PAPER, BauSystem.MESSAGE.parse("LOADER_GUI_SHOW_WAITS_SET_ALL", p), clickType -> { + SWAnvilInv swAnvilInv = new SWAnvilInv(p, BauSystem.MESSAGE.parse("LOADER_GUI_SHOW_WAITS_TITLE", p), ""); + swAnvilInv.setCallback(s -> { + try { + long delay = Math.max(Long.parseLong(s), 0); + list.forEach(loaderElementSWListEntry -> { + ((LoaderWait) loaderElementSWListEntry.getObject()).setDelay(delay); + }); + } catch (NumberFormatException ignored) { + } + gui(settingsSorting); + }); + swAnvilInv.open(); + }); + swListInv.setItem(50, setWait); + } else { + swListInv.setItem(50, new SWItem(Material.GRAY_STAINED_GLASS_PANE, "§8")); + } swListInv.open(); } @@ -221,12 +250,97 @@ public class Loader implements Listener { } public String getProgress() { - return (currentElement + 1) + "§8/§7" + elements.size(); + return Math.max(currentElement, 1) + "§8/§7" + elements.size(); } public enum SettingsSorting { - WAIT, - INTERACTIONS, + ALL { + @Override + public Material getMaterial() { + return Material.STRUCTURE_VOID; + } + + @Override + public String getName() { + return "LOADER_GUI_SHOW_ALL"; + } + + @Override + public boolean shouldShow(LoaderElement previous, LoaderElement current, LoaderElement next) { + return true; + } + }, + WAIT { + @Override + public Material getMaterial() { + return Material.CLOCK; + } + + @Override + public String getName() { + return "LOADER_GUI_SHOW_WAITS"; + } + + @Override + public boolean shouldShow(LoaderElement previous, LoaderElement current, LoaderElement next) { + return current instanceof LoaderWait; + } + }, + WAIT_BETWEEN_TNT { + @Override + public Material getMaterial() { + return Material.REDSTONE_BLOCK; + } + + @Override + public String getName() { + return "LOADER_GUI_SHOW_WAITS_BETWEEN_TNT"; + } + + @Override + public boolean shouldShow(LoaderElement previous, LoaderElement current, LoaderElement next) { + return previous instanceof LoaderTNT && current instanceof LoaderWait && next instanceof LoaderTNT; + } + }, + INTERACTIONS { + @Override + public Material getMaterial() { + return Material.REPEATER; + } + + @Override + public String getName() { + return "LOADER_GUI_SHOW_INTERACTIONS"; + } + + @Override + public boolean shouldShow(LoaderElement previous, LoaderElement current, LoaderElement next) { + return current instanceof LoaderInteractionElement && !(current instanceof LoaderTNT); + } + }, + TNT { + @Override + public Material getMaterial() { + return Material.TNT; + } + + @Override + public String getName() { + return "LOADER_GUI_SHOW_TNT"; + } + + @Override + public boolean shouldShow(LoaderElement previous, LoaderElement current, LoaderElement next) { + return current instanceof LoaderTNT; + } + }, + ; + + public static int LENGTH = SettingsSorting.values().length; + + public abstract Material getMaterial(); + public abstract String getName(); + public abstract boolean shouldShow(LoaderElement previous, LoaderElement current, LoaderElement next); } @AllArgsConstructor diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/loader/LoaderCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/loader/LoaderCommand.java index ee03be16..b065c3d2 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/loader/LoaderCommand.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/loader/LoaderCommand.java @@ -80,7 +80,26 @@ public class LoaderCommand extends SWCommand { public void guiLoader(@Validator Player player) { Loader loader = Loader.getLoader(player); if (loaderNullCheck(loader, player)) return; - loader.gui(null); + loader.gui(Loader.SettingsSorting.ALL); + } + + @Register(value = "wait", description = "LOADER_HELP_WAIT") + public void shotDelayLoader(@Validator Player p, @Min(intValue = 1) @ErrorMessage("LOADER_SMALL_TIME") int delay) { + Loader loader = Loader.getLoader(p); + if (loaderNullCheck(loader, p)) return; + if (loader.setTicksBetweenShots(delay)) { + BauSystem.MESSAGE.send("LOADER_NEW_TIME", p, delay); + } else { + BauSystem.MESSAGE.send("LOADER_SMALL_TIME", p); + } + } + + @Register(value = "speed", description = "LOADER_HELP_SPEED") + public void speedLoader(@Validator Player p, @Min(intValue = 0) @ErrorMessage("LOADER_SMALL_TIME") int delay) { + Loader loader = Loader.getLoader(p); + if (loaderNullCheck(loader, p)) return; + BauSystem.MESSAGE.send("LOADER_NEW_LOAD_TIME", p, delay); + loader.setTicksBetweenBlocks(delay); } @ClassValidator(value = Player.class, local = true) diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/loader/LoaderRecorder.java b/BauSystem_Main/src/de/steamwar/bausystem/features/loader/LoaderRecorder.java index a0734231..ec2153ae 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/loader/LoaderRecorder.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/loader/LoaderRecorder.java @@ -22,6 +22,7 @@ package de.steamwar.bausystem.features.loader; import de.steamwar.bausystem.BauSystem; import de.steamwar.bausystem.SWUtils; import de.steamwar.bausystem.features.loader.elements.LoaderElement; +import de.steamwar.bausystem.features.loader.elements.LoaderInteractionElement; import de.steamwar.bausystem.features.loader.elements.impl.*; import de.steamwar.bausystem.features.tpslimit.TPSUtils; import org.bukkit.Bukkit; @@ -33,6 +34,7 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; import org.bukkit.event.block.Action; +import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerMoveEvent; @@ -70,7 +72,7 @@ public class LoaderRecorder implements Listener { return; } long diff = TPSUtils.currentRealTick.get() - lastInteraction; - if (last && diff > 160) diff = 160; + if (last) diff = 120; lastInteraction = TPSUtils.currentRealTick.get(); loaderElementList.add(new LoaderWait(diff)); } @@ -86,7 +88,34 @@ public class LoaderRecorder implements Listener { } @EventHandler - public void onPlayerInteractEntity(PlayerInteractEvent event) { + public void onBlockBreak(BlockBreakEvent event) { + if (event.getPlayer() != player) return; + + boolean removedOne = false; + for (int i = 0; i < loaderElementList.size(); i++) { + LoaderElement element = loaderElementList.get(i); + if (!(element instanceof LoaderInteractionElement)) continue; + LoaderInteractionElement interactionElement = (LoaderInteractionElement) element; + if (interactionElement.getLocation().equals(event.getBlock().getLocation())) { + loaderElementList.remove(i); + if (i > 0) { + loaderElementList.remove(i - 1); + } + removedOne = true; + break; + } + } + + if (removedOne) { + if (event.getBlock().getType() != Material.TNT) { + event.setCancelled(true); + } + SWUtils.sendToActionbar(player, BauSystem.MESSAGE.parse("LOADER_MESSAGE_UNINTERACT", player)); + } + } + + @EventHandler + public void onPlayerInteract(PlayerInteractEvent event) { if (event.getPlayer() != player) return; if (player.isSneaking()) return; if (event.getAction() != Action.RIGHT_CLICK_BLOCK && event.getAction() != Action.PHYSICAL) return; diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/loader/elements/ElementSettings.java b/BauSystem_Main/src/de/steamwar/bausystem/features/loader/elements/ElementSettings.java deleted file mode 100644 index 25b839ff..00000000 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/loader/elements/ElementSettings.java +++ /dev/null @@ -1,39 +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 . - */ - -package de.steamwar.bausystem.features.loader.elements; - -import de.steamwar.bausystem.BauSystem; -import de.steamwar.inventory.SWItem; -import org.bukkit.entity.Player; - -import java.util.function.Consumer; - -public interface ElementSettings { - SWItem menu(Player player); - void execute(Consumer delay); - void click(Player player, Runnable backAction, Runnable deleteAction); - - default void playerInteract() {} - void noop(); - - default String translateItemName(String name, String mode, Player player, Object... args) { - return BauSystem.MESSAGE.parse("LOADER_GUI_ITEM_NAME", player, BauSystem.MESSAGE.parse(name, player), BauSystem.MESSAGE.parse(mode, player, args)); - } -} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/loader/elements/LoaderInteractionElement.java b/BauSystem_Main/src/de/steamwar/bausystem/features/loader/elements/LoaderInteractionElement.java index cc00c662..67539fd8 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/loader/elements/LoaderInteractionElement.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/loader/elements/LoaderInteractionElement.java @@ -21,62 +21,93 @@ package de.steamwar.bausystem.features.loader.elements; import de.steamwar.bausystem.BauSystem; import de.steamwar.inventory.SWAnvilInv; +import de.steamwar.inventory.SWInventory; import de.steamwar.inventory.SWItem; import de.steamwar.inventory.SWListInv; +import lombok.Getter; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; -import org.bukkit.block.data.BlockData; -import org.bukkit.block.data.FaceAttachable; +import org.bukkit.block.data.*; +import org.bukkit.block.data.type.Door; import org.bukkit.block.data.type.Switch; import org.bukkit.entity.Player; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.function.Consumer; -public abstract class LoaderInteractionElement implements LoaderElement { +public abstract class LoaderInteractionElement & LoaderSettingsEnum> implements LoaderElement { + @Getter protected final Location location; protected int currentShot = 0; + protected T defaultSetting; + protected T newSetting; + protected T[] allSettings; protected List elements = new ArrayList<>(); + protected List extraPower = new ArrayList<>(); + protected List extraTicks = new ArrayList<>(); + protected int settingsGuiSize = 0; - protected LoaderInteractionElement(Location location) { + protected LoaderInteractionElement(Location location, T defaultSetting, T newSetting, T[] allSettings) { this.location = location; - T element = createNewElement(); - element.playerInteract(); - elements.add(element); + this.defaultSetting = defaultSetting; + this.newSetting = newSetting; + this.allSettings = allSettings; + + elements.add(defaultSetting); + extraPower.add(0); + extraTicks.add(0L); + + for (T element : allSettings) { + settingsGuiSize = Math.max(element.getPos(), settingsGuiSize); + } + while (settingsGuiSize % 9 != 0) settingsGuiSize++; + settingsGuiSize += 9; } @Override public void execute(Consumer delay) { if (currentShot >= elements.size()) currentShot = 0; - elements.get(currentShot).execute(delay); + if (checkBlockInWorld()) { + BlockData blockData = location.getBlock().getBlockData(); + elements.get(currentShot).execute(location, blockData, this, extraPower.get(currentShot), extraTicks.get(currentShot), delay); + } currentShot++; if (currentShot >= elements.size()) currentShot = 0; } @Override public void click(Player player, Runnable backAction) { - List> entries = new ArrayList<>(); + List> entries = new ArrayList<>(); Runnable updateRunnable = () -> { entries.clear(); - for (T element : elements) { - entries.add(new SWListInv.SWListEntry<>(element.menu(player), element)); + for (int i = 0; i < elements.size(); i++) { + SWItem swItem = elements.get(i).menu(player, this, extraPower.get(i), extraTicks.get(i)); + swItem.setLore(Arrays.asList(BauSystem.MESSAGE.parse("LOADER_GUI_CLICK_TO_EDIT", player))); + entries.add(new SWListInv.SWListEntry<>(swItem, i)); } }; updateRunnable.run(); - SWListInv listInv = new SWListInv<>(player, "Interaction Settings", false, entries, (clickType, entry) -> {}); + SWListInv listInv = new SWListInv<>(player, "Interaction Settings", false, entries, (clickType, entry) -> {}); listInv.setCallback((clickType, entry) -> { - entry.click(player, () -> { + openIndividualSettingsMenu(player, entry, () -> { updateRunnable.run(); listInv.open(); }, () -> { - if (elements.size() == 1) return; - elements.remove(entry); + elements.remove((int) entry); + extraPower.remove((int) entry); + extraTicks.remove((int) entry); + if (elements.isEmpty()) { + elements.add(newSetting); + extraPower.add(0); + extraTicks.add(1L); + } click(player, backAction); }); }); @@ -84,69 +115,190 @@ public abstract class LoaderInteractionElement implem backAction.run(); })); listInv.setItem(50, new SWItem(Material.GHAST_SPAWN_EGG, "§7Insert another Setting", clickType -> { - T element = createNewElement(); - elements.add(element); - element.click(player, () -> { + elements.add(defaultSetting); + extraPower.add(0); + extraTicks.add(1L); + openIndividualSettingsMenu(player, elements.size() - 1, () -> { updateRunnable.run(); listInv.open(); }, () -> { - if (elements.size() == 1) return; - elements.remove(element); + elements.remove(elements.size() - 1); + extraPower.remove(extraPower.size() - 1); + extraTicks.remove(extraTicks.size() - 1); + if (elements.isEmpty()) { + elements.add(newSetting); + extraPower.add(0); + extraTicks.add(1L); + } click(player, backAction); }); })); - listInv.setItem(51, new SWItem(Material.STRUCTURE_VOID, "§7Insert NOOP's", clickType -> { - SWAnvilInv anvilInv = new SWAnvilInv(player, "§7NOOP Count", "1"); - anvilInv.setCallback(s -> { - try { - int count = Integer.parseInt(s); - for (int i = 0; i < count; i++) { - T element = createNewElement(); - element.noop(); - elements.add(element); - } - updateRunnable.run(); - listInv.open(); - } catch (NumberFormatException e) { - player.sendMessage("§cInvalid Number"); - } - }); - anvilInv.open(); - })); listInv.open(); } + private void openIndividualSettingsMenu(Player player, int index, Runnable back, Runnable delete) { + T currentElement = elements.get(index); + int guiSize = settingsGuiSize; + int powerStart = guiSize - 9; + if (currentElement.hasPower(this)) { + guiSize += 18; + } + int ticksStart = guiSize - 9; + if (currentElement.hasTicks(this)) { + guiSize += 9; + } + + SWInventory swInventory = new SWInventory(player, guiSize, BauSystem.MESSAGE.parse("LOADER_GUI_SETTINGS_TITLE", player)); + for (int i = guiSize - 9; i < guiSize; i++) swInventory.setItem(i, new SWItem(Material.GRAY_STAINED_GLASS_PANE, "§7", clickType -> {})); + swInventory.setItem(guiSize - 9, new SWItem(Material.ARROW, BauSystem.MESSAGE.parse("LOADER_GUI_SETTINGS_BACK", player)).getItemStack(), clickType -> back.run()); + swInventory.setItem(guiSize - 5, new SWItem(Material.WOODEN_AXE, BauSystem.MESSAGE.parse("LOADER_GUI_SETTINGS_COPY", player)).getItemStack(), clickType -> { + SWAnvilInv swAnvilInv = new SWAnvilInv(player, BauSystem.MESSAGE.parse("LOADER_GUI_COPY_TITLE", player), "1"); + swAnvilInv.setCallback(s -> { + try { + int count = Integer.parseInt(s); + if (count < 1) count = 1; + if (count > 65536) count = 65536; + + int power = extraPower.get(index); + long ticks = extraTicks.get(index); + for (int i = 0; i < count; i++) { + elements.add(currentElement); + extraPower.add(power); + extraTicks.add(ticks); + } + + if (count == 1) { + openIndividualSettingsMenu(player, elements.size() - 1, back, delete); + } else { + back.run(); + } + } catch (NumberFormatException e) { + back.run(); + } + }); + swAnvilInv.open(); + }); + swInventory.setItem(guiSize - 1, new SWItem(Material.BARRIER, BauSystem.MESSAGE.parse("LOADER_GUI_SETTINGS_DELETE", player)).getItemStack(), clickType -> delete.run()); + + for (T element : allSettings) { + SWItem item = element.menu(player, this, extraPower.get(index), extraTicks.get(index)); + if (element == currentElement) { + item.setEnchanted(true); + } + + swInventory.setItem(element.getPos(), item.getItemStack(), clickType -> { + elements.set(index, element); + openIndividualSettingsMenu(player, index, back, delete); + }); + } + + if (currentElement.hasPower(this)) { + for (int power = 0; power < 16; power++) { + int finalPowerPosition = power; + if (power >= 9) finalPowerPosition++; + SWItem powerItem = new SWItem(Material.REDSTONE, BauSystem.MESSAGE.parse("LOADER_SETTING_POWER", player, power), Arrays.asList(), false, clickType -> {}); + powerItem.getItemStack().setAmount(Math.max(power, 1)); + if (extraPower.get(index) == power) powerItem.setEnchanted(true); + + int finalPower = power; + swInventory.setItem(finalPowerPosition + powerStart, powerItem.getItemStack(), clickType -> { + extraPower.set(index, finalPower); + openIndividualSettingsMenu(player, index, back, delete); + }); + } + } + + if (currentElement.hasTicks(this)) { + swInventory.setItem(ticksStart + 3, new SWItem(SWItem.getDye(1), BauSystem.MESSAGE.parse("LOADER_SETTING_TICKS_REMOVE_ONE", player), Arrays.asList(BauSystem.MESSAGE.parse("LOADER_SETTING_TICKS_REMOVE_ONE_SHIFT", player)), false, clickType -> {}).getItemStack(), clickType -> { + long ticks = extraTicks.get(index); + ticks -= clickType.isShiftClick() ? 5 : 1; + if (ticks < 1) ticks = 1; + extraTicks.set(index, ticks); + openIndividualSettingsMenu(player, index, back, delete); + }); + + SWItem ticksItem = new SWItem(Material.CLOCK, BauSystem.MESSAGE.parse("LOADER_SETTING_TICKS", player, extraTicks.get(index)), Arrays.asList(BauSystem.MESSAGE.parse("LOADER_GUI_CLICK_TO_EDIT", player)), false, clickType -> {}); + ticksItem.getItemStack().setAmount((int) Math.min(extraTicks.get(index), 64)); + swInventory.setItem(ticksStart + 4, ticksItem.getItemStack(), clickType -> { + SWAnvilInv swAnvilInv = new SWAnvilInv(player, BauSystem.MESSAGE.parse("LOADER_SETTING_TICKS_NAME", player), extraTicks.get(index) + ""); + swAnvilInv.setCallback(s -> { + try { + long ticks = Long.parseLong(s); + if (ticks < 1) ticks = 1; + extraTicks.set(index, ticks); + } catch (NumberFormatException ignored) { + } + openIndividualSettingsMenu(player, index, back, delete); + }); + swAnvilInv.open(); + }); + + swInventory.setItem(ticksStart + 5, new SWItem(SWItem.getDye(10), BauSystem.MESSAGE.parse("LOADER_SETTING_TICKS_ADD_ONE", player), Arrays.asList(BauSystem.MESSAGE.parse("LOADER_SETTING_TICKS_ADD_ONE_SHIFT", player)), false, clickType -> {}).getItemStack(), clickType -> { + long ticks = extraTicks.get(index); + ticks += clickType.isShiftClick() ? 5 : 1; + extraTicks.set(index, ticks); + openIndividualSettingsMenu(player, index, back, delete); + }); + } + + swInventory.open(); + } + protected void update(BlockData blockData) { - Material material = blockData.getMaterial(); Block block = location.getBlock(); - if (blockData instanceof Switch) { + if (blockData instanceof Door) { + Door door = (Door) blockData; + block.setBlockData(door); + if (door.getHalf() == Bisected.Half.BOTTOM) { + updateBlock(block.getRelative(BlockFace.UP), door.isOpen() ? 15 : 0); + } else { + updateBlock(block.getRelative(BlockFace.DOWN), door.isOpen() ? 15 : 0); + } + } else if (blockData instanceof Switch) { Switch sw = (Switch) blockData; updateBlock(block, sw); FaceAttachable.AttachedFace face = sw.getAttachedFace(); if (face == FaceAttachable.AttachedFace.FLOOR) { - updateBlock(block.getRelative(BlockFace.DOWN)); + updateBlock(block.getRelative(BlockFace.DOWN), sw.isPowered() ? 15 : 0); } else if (face == FaceAttachable.AttachedFace.CEILING) { - updateBlock(block.getRelative(BlockFace.UP)); + updateBlock(block.getRelative(BlockFace.UP), sw.isPowered() ? 15 : 0); } else { - updateBlock(block.getRelative(sw.getFacing().getOppositeFace())); + updateBlock(block.getRelative(sw.getFacing().getOppositeFace()), sw.isPowered() ? 15 : 0); } - } else if (material == Material.TRIPWIRE) { + } else if (blockData instanceof Powerable) { + updateBlock(block, blockData); + updateBlock(block.getRelative(BlockFace.DOWN), ((Powerable) blockData).isPowered() ? 15 : 0); + } else if (blockData instanceof AnaloguePowerable) { + updateBlock(block, blockData); + updateBlock(block.getRelative(BlockFace.DOWN), ((AnaloguePowerable) blockData).getPower()); + } else { updateBlock(block, blockData); - } else if (material.name().endsWith("_PLATE")) { - updateBlock(block.getRelative(BlockFace.DOWN)); } } - protected void updateBlock(Block block) { - updateBlock(block, block.getBlockData()); + private void updateBlock(Block block, int powered) { + BlockData data = block.getBlockData(); + if (data instanceof Door) { + Door door = (Door) data; + door.setOpen(powered > 0); + block.setBlockData(door); + return; + } else if (data instanceof Powerable) { + Powerable powerable = (Powerable) data; + powerable.setPowered(powered > 0); + } else if (data instanceof AnaloguePowerable) { + AnaloguePowerable analoguePowerable = (AnaloguePowerable) data; + analoguePowerable.setPower(powered); + } + updateBlock(block, data); } - protected void updateBlock(Block block, BlockData data) { - block.setType(Material.BARRIER, true); - block.setBlockData(data, true); + private void updateBlock(Block block, BlockData data) { + block.setType(Material.BARRIER); + block.setBlockData(data); } - public abstract T createNewElement(); + public abstract boolean checkBlockInWorld(); protected final String translateItemName(String name, Player player) { return BauSystem.MESSAGE.parse("LOADER_SETTING_NAME", player, BauSystem.MESSAGE.parse(name, player)); diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/loader/elements/LoaderSettingsEnum.java b/BauSystem_Main/src/de/steamwar/bausystem/features/loader/elements/LoaderSettingsEnum.java new file mode 100644 index 00000000..f1e628d0 --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/loader/elements/LoaderSettingsEnum.java @@ -0,0 +1,44 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2023 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.features.loader.elements; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.inventory.SWItem; +import org.bukkit.Location; +import org.bukkit.entity.Player; + +import java.util.function.Consumer; + +public interface LoaderSettingsEnum, E extends Enum & LoaderSettingsEnum> { + int getPos(); + SWItem menu(Player player, P parent, int power, long ticks); + default boolean hasPower(P parent) { + return false; + } + default boolean hasTicks(P parent) { + return false; + } + + void execute(Location location, T blockData, P parent, int power, long ticks, Consumer delay); + + default String translateItemName(String name, String mode, Player player, Object... args) { + return BauSystem.MESSAGE.parse("LOADER_GUI_ITEM_NAME", player, BauSystem.MESSAGE.parse(name, player), BauSystem.MESSAGE.parse(mode, player, args)); + } +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/loader/elements/impl/LoaderComparator.java b/BauSystem_Main/src/de/steamwar/bausystem/features/loader/elements/impl/LoaderComparator.java index 9e446448..fa7a032e 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/loader/elements/impl/LoaderComparator.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/loader/elements/impl/LoaderComparator.java @@ -19,10 +19,8 @@ package de.steamwar.bausystem.features.loader.elements.impl; -import de.steamwar.bausystem.BauSystem; -import de.steamwar.bausystem.features.loader.elements.ElementSettings; import de.steamwar.bausystem.features.loader.elements.LoaderInteractionElement; -import de.steamwar.inventory.SWInventory; +import de.steamwar.bausystem.features.loader.elements.LoaderSettingsEnum; import de.steamwar.inventory.SWItem; import org.bukkit.Location; import org.bukkit.Material; @@ -30,101 +28,83 @@ import org.bukkit.block.data.type.Comparator; import org.bukkit.entity.Player; import java.util.Arrays; -import java.util.Collections; import java.util.function.Consumer; -public class LoaderComparator extends LoaderInteractionElement { +public class LoaderComparator extends LoaderInteractionElement { public LoaderComparator(Location location) { - super(location); + super(location, ComparatorSettingsEnum.INTERACT, ComparatorSettingsEnum.NOOP, ComparatorSettingsEnum.values()); } - public class ComparatorSettings implements ElementSettings { - - private boolean interact = false; - private Comparator.Mode mode = Comparator.Mode.COMPARE; - - @Override - public SWItem menu(Player player) { - return menu(player, interact, mode); - } - - private SWItem menu(Player player, boolean interact, Comparator.Mode mode) { - SWItem swItem; - if (interact) { - swItem = new SWItem(Material.STICK, "§7Comparator§8: §eInteract"); - } else if (mode == null) { - swItem = new SWItem(Material.STRUCTURE_VOID, "§7Comparator§8: §eNOOP"); - } else { - swItem = new SWItem(Material.COMPARATOR, "§7Comparator§8: §e" + mode.name()); + public enum ComparatorSettingsEnum implements LoaderSettingsEnum { + NOOP { + @Override + public int getPos() { + return 2; } - swItem.setLore(Arrays.asList(BauSystem.MESSAGE.parse("LOADER_GUI_CLICK_TO_EDIT", player))); - return swItem; - } - @Override - public void execute(Consumer delay) { - if (location.getBlock().getType() != Material.COMPARATOR) return; - Comparator comparator = (Comparator) location.getBlock().getBlockData(); - if (interact) { - comparator.setMode(comparator.getMode() == Comparator.Mode.COMPARE ? Comparator.Mode.SUBTRACT : Comparator.Mode.COMPARE); - } else if (mode == null) { - return; - } else { - comparator.setMode(mode); + @Override + public SWItem menu(Player player, LoaderComparator parent, int power, long ticks) { + return new SWItem(Material.STRUCTURE_VOID, translateItemName("LOADER_BUTTON_COMPARATOR", "LOADER_INTERACTION_NOOP", player)); } - location.getBlock().setBlockData(comparator, true); - } - @Override - public void click(Player player, Runnable backAction, Runnable deleteAction) { - SWInventory swInventory = new SWInventory(player, 18, BauSystem.MESSAGE.parse("LOADER_GUI_SETTINGS_TITLE", player)); - for (int i = 9; i < 18; i++) swInventory.setItem(i, new SWItem(Material.GRAY_STAINED_GLASS_PANE, "§7")); - swInventory.setItem(9, new SWItem(Material.ARROW, BauSystem.MESSAGE.parse("LOADER_GUI_SETTINGS_BACK", player)).getItemStack(), clickType -> backAction.run()); - swInventory.setItem(17, new SWItem(Material.BARRIER, BauSystem.MESSAGE.parse("LOADER_GUI_SETTINGS_DELETE", player)).getItemStack(), clickType -> deleteAction.run()); - - swInventory.setItem(2, item(player, false, null).getItemStack(), clickType -> { - interact = false; - mode = null; - click(player, backAction, deleteAction); - }); - swInventory.setItem(3, item(player, true, null).getItemStack(), clickType -> { - interact = true; - click(player, backAction, deleteAction); - }); - swInventory.setItem(5, item(player, false, Comparator.Mode.COMPARE).getItemStack(), clickType -> { - interact = false; - mode = Comparator.Mode.COMPARE; - click(player, backAction, deleteAction); - }); - swInventory.setItem(6, item(player, false, Comparator.Mode.SUBTRACT).getItemStack(), clickType -> { - interact = false; - mode = Comparator.Mode.SUBTRACT; - click(player, backAction, deleteAction); - }); - - swInventory.open(); - } - - private SWItem item(Player player, boolean interact, Comparator.Mode mode) { - SWItem swItem = menu(player, interact, mode); - if (swItem.getItemStack().equals(menu(player, this.interact, this.mode).getItemStack())) { - swItem.setEnchanted(true); + @Override + public void execute(Location location, Comparator blockData, LoaderComparator parent, int power, long ticks, Consumer delay) { } - swItem.setLore(Collections.emptyList()); - return swItem; - } + }, - @Override - public void playerInteract() { - interact = true; - mode = null; - } + INTERACT { + @Override + public int getPos() { + return 3; + } - @Override - public void noop() { - interact = false; - mode = null; + @Override + public SWItem menu(Player player, LoaderComparator parent, int power, long ticks) { + return new SWItem(Material.STICK, translateItemName("LOADER_BUTTON_COMPARATOR", "LOADER_INTERACTION_INTERACT", player)); + } + + @Override + public void execute(Location location, Comparator blockData, LoaderComparator parent, int power, long ticks, Consumer delay) { + blockData.setMode(blockData.getMode() == Comparator.Mode.COMPARE ? Comparator.Mode.SUBTRACT : Comparator.Mode.COMPARE); + parent.update(blockData); + } + }, + + COMPARE { + @Override + public int getPos() { + return 5; + } + + @Override + public SWItem menu(Player player, LoaderComparator parent, int power, long ticks) { + return new SWItem(Material.COMPARATOR, translateItemName("LOADER_BUTTON_COMPARATOR", "LOADER_INTERACTION_COMPARE", player)); + } + + @Override + public void execute(Location location, Comparator blockData, LoaderComparator parent, int power, long ticks, Consumer delay) { + blockData.setMode(Comparator.Mode.COMPARE); + parent.update(blockData); + } + }, + + SUBTRACT { + @Override + public int getPos() { + return 6; + } + + @Override + public SWItem menu(Player player, LoaderComparator parent, int power, long ticks) { + return new SWItem(Material.COMPARATOR, translateItemName("LOADER_BUTTON_COMPARATOR", "LOADER_INTERACTION_SUBTRACT", player)); + } + + @Override + public void execute(Location location, Comparator blockData, LoaderComparator parent, int power, long ticks, Consumer delay) { + blockData.setMode(Comparator.Mode.SUBTRACT); + parent.update(blockData); + } } } @@ -136,7 +116,7 @@ public class LoaderComparator extends LoaderInteractionElement { +public class LoaderDaylightDetector extends LoaderInteractionElement { public LoaderDaylightDetector(Location location) { - super(location); + super(location, DaylightSettingsEnum.INTERACT, DaylightSettingsEnum.NOOP, DaylightSettingsEnum.values()); } - public class DaylightDetectorSettings implements ElementSettings { - - private boolean noop = false; - private boolean interact = false; - private boolean inverted = true; - private int power = 0; - - @Override - public SWItem menu(Player player) { - return menu(player, noop, interact, inverted); - } - - private SWItem menu(Player player, boolean noop, boolean interact, boolean powered) { - SWItem swItem; - if (noop) { - swItem = new SWItem(Material.STRUCTURE_VOID, translateItemName("LOADER_BUTTON_DAYLIGHT_DETECTOR", "LOADER_INTERACTION_NOOP", player)); - } else if (interact) { - swItem = new SWItem(Material.STICK, translateItemName("LOADER_BUTTON_DAYLIGHT_DETECTOR", "LOADER_INTERACTION_INTERACT", player)); - } else { - swItem = new SWItem(Material.DAYLIGHT_DETECTOR, translateItemName("LOADER_BUTTON_DAYLIGHT_DETECTOR", powered ? "LOADER_INTERACTION_POWERED": "LOADER_INTERACTION_UNPOWERED", player)); - } - swItem.setLore(Arrays.asList(BauSystem.MESSAGE.parse("LOADER_GUI_CLICK_TO_EDIT", player))); - return swItem; - } - - @Override - public void execute(Consumer delay) { - if (location.getBlock().getType() != Material.DAYLIGHT_DETECTOR) return; - DaylightDetector daylightDetector = (DaylightDetector) location.getBlock().getBlockData(); - if (noop) { - return; - } else if (interact) { - daylightDetector.setInverted(!daylightDetector.isInverted()); - } else { - daylightDetector.setInverted(inverted); - } - daylightDetector.setPower(daylightDetector.isInverted() ? 15 - power : power); - location.getBlock().setBlockData(daylightDetector); - updateBlock(location.getBlock().getRelative(0, -1, 0)); - } - - @Override - public void click(Player player, Runnable backAction, Runnable deleteAction) { - SWInventory swInventory = new SWInventory(player, 36, BauSystem.MESSAGE.parse("LOADER_GUI_SETTINGS_TITLE", player)); - for (int i = 27; i < 35; i++) swInventory.setItem(i, new SWItem(Material.GRAY_STAINED_GLASS_PANE, "§7")); - swInventory.setItem(27, new SWItem(Material.ARROW, BauSystem.MESSAGE.parse("LOADER_GUI_SETTINGS_BACK", player)).getItemStack(), clickType -> backAction.run()); - swInventory.setItem(35, new SWItem(Material.BARRIER, BauSystem.MESSAGE.parse("LOADER_GUI_SETTINGS_DELETE", player)).getItemStack(), clickType -> deleteAction.run()); - - swInventory.setItem(2, item(player, true, false, false).getItemStack(), clickType -> { - noop = true; - click(player, backAction, deleteAction); - }); - swInventory.setItem(3, item(player, false, true, false).getItemStack(), clickType -> { - noop = false; - interact = true; - click(player, backAction, deleteAction); - }); - swInventory.setItem(5, item(player, false, false, false).getItemStack(), clickType -> { - noop = false; - interact = false; - inverted = false; - click(player, backAction, deleteAction); - }); - swInventory.setItem(6, item(player, false, false, true).getItemStack(), clickType -> { - noop = false; - interact = false; - inverted = true; - click(player, backAction, deleteAction); - }); - - for (int i = 0; i < 16; i++) { - int finalI = i; - int finalI2 = i; - if (i >= 9) finalI2++; - swInventory.setItem(finalI2 + 9, item(player, finalI).getItemStack(), clickType -> { - power = finalI; - click(player, backAction, deleteAction); - }); + public enum DaylightSettingsEnum implements LoaderSettingsEnum { + NOOP { + @Override + public int getPos() { + return 2; } - swInventory.open(); - } - - private SWItem item(Player player, boolean noop, boolean interact, boolean inverted) { - SWItem swItem = menu(player, noop, interact, inverted); - if (swItem.getItemStack().equals(menu(player, this.noop, this.interact, this.inverted).getItemStack())) { - swItem.setEnchanted(true); + @Override + public SWItem menu(Player player, LoaderDaylightDetector parent, int power, long ticks) { + return new SWItem(Material.STRUCTURE_VOID, translateItemName("LOADER_BUTTON_DAYLIGHT_DETECTOR", "LOADER_INTERACTION_NOOP", player)); } - swItem.setLore(Collections.emptyList()); - return swItem; - } - private SWItem item(Player player, int power) { - SWItem swItem = new SWItem(power == 0 ? Material.GUNPOWDER : Material.REDSTONE, BauSystem.MESSAGE.parse("LOADER_SETTING_POWER", player, power)); - swItem.getItemStack().setAmount(power == 0 ? 1 : power); - if (!this.noop && this.power == power) swItem.setEnchanted(true); - return swItem; - } + @Override + public void execute(Location location, DaylightDetector blockData, LoaderDaylightDetector parent, int power, long ticks, Consumer delay) { + } + }, - @Override - public void playerInteract() { - noop = false; - interact = true; - inverted = false; - } + INTERACT { + @Override + public int getPos() { + return 3; + } - @Override - public void noop() { - noop = true; - interact = false; - inverted = false; + @Override + public SWItem menu(Player player, LoaderDaylightDetector parent, int power, long ticks) { + return new SWItem(Material.STICK, translateItemName("LOADER_BUTTON_DAYLIGHT_DETECTOR", "LOADER_INTERACTION_INTERACT", player)); + } + + @Override + public void execute(Location location, DaylightDetector blockData, LoaderDaylightDetector parent, int power, long ticks, Consumer delay) { + blockData.setInverted(!blockData.isInverted()); + blockData.setPower(15 - blockData.getPower()); + parent.update(blockData); + } + }, + + DAY_MODE { + @Override + public int getPos() { + return 5; + } + + @Override + public SWItem menu(Player player, LoaderDaylightDetector parent, int power, long ticks) { + return new SWItem(Material.DAYLIGHT_DETECTOR, translateItemName("LOADER_BUTTON_DAYLIGHT_DETECTOR", "LOADER_INTERACTION_UNPOWERED", player)); + } + + @Override + public void execute(Location location, DaylightDetector blockData, LoaderDaylightDetector parent, int power, long ticks, Consumer delay) { + if (blockData.isInverted()) { + blockData.setInverted(false); + blockData.setPower(15 - blockData.getPower()); + parent.update(blockData); + } + } + }, + + NIGHT_MODE { + @Override + public int getPos() { + return 6; + } + + @Override + public SWItem menu(Player player, LoaderDaylightDetector parent, int power, long ticks) { + return new SWItem(Material.DAYLIGHT_DETECTOR, translateItemName("LOADER_BUTTON_DAYLIGHT_DETECTOR", "LOADER_INTERACTION_POWERED", player)); + } + + @Override + public void execute(Location location, DaylightDetector blockData, LoaderDaylightDetector parent, int power, long ticks, Consumer delay) { + if (!blockData.isInverted()) { + blockData.setInverted(true); + blockData.setPower(15 - blockData.getPower()); + parent.update(blockData); + } + } } } @@ -159,7 +120,7 @@ public class LoaderDaylightDetector extends LoaderInteractionElement { +public class LoaderLectern extends LoaderInteractionElement { public LoaderLectern(Location location) { - super(location); + super(location, LecternSettingsEnum.NEXT_PAGE, LecternSettingsEnum.NOOP, LecternSettingsEnum.values()); } - public class LecternSettings implements ElementSettings { - - private boolean noop = true; - private LecternAction action = LecternAction.PAGE_NEXT; - private int page = 0; - - @Override - public SWItem menu(Player player) { - return menu(player, noop, action, page); - } - - private SWItem menu(Player player, boolean noop, LecternAction action, int page) { - SWItem swItem; - if (noop) { - swItem = new SWItem(Material.STRUCTURE_VOID, translateItemName("LOADER_BUTTON_LECTERN", "LOADER_INTERACTION_NOOP", player)); - } else if (action == LecternAction.PAGE_PREV) { - swItem = new SWItem(Material.STICK, translateItemName("LOADER_BUTTON_LECTERN", "LOADER_INTERACTION_PAGE_PREV", player)); - } else if (action == LecternAction.PAGE_NEXT) { - swItem = new SWItem(Material.STICK, translateItemName("LOADER_BUTTON_LECTERN", "LOADER_INTERACTION_PAGE_NEXT", player)); - } else { - swItem = new SWItem(Material.LECTERN, translateItemName("LOADER_BUTTON_LECTERN", "LOADER_INTERACTION_PAGE", player, page)); - swItem.getItemStack().setAmount(page); - } - swItem.setLore(Arrays.asList(BauSystem.MESSAGE.parse("LOADER_GUI_CLICK_TO_EDIT", player))); - return swItem; - } - - @Override - public void execute(Consumer delay) { - if (location.getBlock().getType() != Material.LECTERN) return; - Lectern lectern = (Lectern) location.getBlock().getState(); - if (!((org.bukkit.block.data.type.Lectern) lectern.getBlockData()).hasBook()) return; - int pages = ((BookMeta) lectern.getInventory().getItem(0).getItemMeta()).getPages().size(); - if (noop) { - return; - } else if (action == LecternAction.PAGE_PREV) { - int page = lectern.getPage(); - if (page > 1) lectern.setPage(page - 1); - } else if (action == LecternAction.PAGE_NEXT) { - int page = lectern.getPage(); - if (page < pages) lectern.setPage(page + 1); - } else if (action == LecternAction.PAGE_SET) { - if (page <= pages) lectern.setPage(page); - } - lectern.update(false, true); - } - - @Override - public void click(Player player, Runnable backAction, Runnable deleteAction) { - SWInventory swInventory = new SWInventory(player, 36, BauSystem.MESSAGE.parse("LOADER_GUI_SETTINGS_TITLE", player)); - for (int i = 27; i < 35; i++) swInventory.setItem(i, new SWItem(Material.GRAY_STAINED_GLASS_PANE, "§7")); - swInventory.setItem(27, new SWItem(Material.ARROW, BauSystem.MESSAGE.parse("LOADER_GUI_SETTINGS_BACK", player)).getItemStack(), clickType -> backAction.run()); - swInventory.setItem(35, new SWItem(Material.BARRIER, BauSystem.MESSAGE.parse("LOADER_GUI_SETTINGS_DELETE", player)).getItemStack(), clickType -> deleteAction.run()); - - swInventory.setItem(2, item(player, true, LecternAction.PAGE_SET, 0).getItemStack(), clickType -> { - noop = true; - click(player, backAction, deleteAction); - }); - swInventory.setItem(5, item(player, false, LecternAction.PAGE_PREV, 0).getItemStack(), clickType -> { - noop = false; - action = LecternAction.PAGE_PREV; - click(player, backAction, deleteAction); - }); - swInventory.setItem(6, item(player, false, LecternAction.PAGE_NEXT, 0).getItemStack(), clickType -> { - noop = false; - action = LecternAction.PAGE_NEXT; - click(player, backAction, deleteAction); - }); - - for (int i = 0; i < 15; i++) { - int finalI = i; - int finalI2 = i; - if (i >= 9) finalI2++; - if (i >= 12) finalI2++; - swInventory.setItem(finalI2 + 9, item(player, false, LecternAction.PAGE_SET, finalI + 1).getItemStack(), clickType -> { - noop = false; - action = LecternAction.PAGE_SET; - page = finalI + 1; - click(player, backAction, deleteAction); - }); + public enum LecternSettingsEnum implements LoaderSettingsEnum { + NOOP { + @Override + public int getPos() { + return 2; } - swInventory.open(); - } - - private SWItem item(Player player, boolean noop, LecternAction action, int page) { - SWItem swItem = menu(player, noop, action, page); - if (swItem.getItemStack().equals(menu(player, this.noop, this.action, this.page).getItemStack())) { - swItem.setEnchanted(true); + @Override + public SWItem menu(Player player, LoaderLectern parent, int power, long ticks) { + return new SWItem(Material.STRUCTURE_VOID, translateItemName("LOADER_BUTTON_LECTERN", "LOADER_INTERACTION_NOOP", player)); } - swItem.setLore(Collections.emptyList()); - return swItem; - } - @Override - public void noop() { - noop = true; - } - } + @Override + public void execute(Location location, org.bukkit.block.data.type.Lectern blockData, LoaderLectern parent, int power, long ticks, Consumer delay) { + } + }, - public enum LecternAction { - PAGE_NEXT, - PAGE_PREV, - PAGE_SET + PREVIOUS_PAGE { + @Override + public int getPos() { + return 5; + } + + @Override + public SWItem menu(Player player, LoaderLectern parent, int power, long ticks) { + return new SWItem(Material.STICK, translateItemName("LOADER_BUTTON_LECTERN", "LOADER_INTERACTION_PAGE_PREV", player)); + } + + @Override + public void execute(Location location, org.bukkit.block.data.type.Lectern blockData, LoaderLectern parent, int power, long ticks, Consumer delay) { + if (!blockData.hasBook()) return; + Lectern lectern = (Lectern) location.getBlock().getState(); + if (lectern.getPage() > 0) { + lectern.setPage(lectern.getPage() - 1); + parent.update(blockData); + } + } + }, + + NEXT_PAGE { + @Override + public int getPos() { + return 6; + } + + @Override + public SWItem menu(Player player, LoaderLectern parent, int power, long ticks) { + return new SWItem(Material.STICK, translateItemName("LOADER_BUTTON_LECTERN", "LOADER_INTERACTION_PAGE_NEXT", player)); + } + + @Override + public void execute(Location location, org.bukkit.block.data.type.Lectern blockData, LoaderLectern parent, int power, long ticks, Consumer delay) { + if (!blockData.hasBook()) return; + Lectern lectern = (Lectern) location.getBlock().getState(); + ItemStack itemStack = lectern.getInventory().getItem(0); + if (itemStack == null) return; + int pages = ((BookMeta) itemStack.getItemMeta()).getPages().size(); + if (lectern.getPage() < pages) { + lectern.setPage(lectern.getPage() + 1); + parent.update(blockData); + } + } + }, + + PAGE_1 { + @Override + public int getPos() { + return 9; + } + + @Override + public SWItem menu(Player player, LoaderLectern parent, int power, long ticks) { + SWItem swItem = new SWItem(Material.LECTERN, translateItemName("LOADER_BUTTON_LECTERN", "LOADER_INTERACTION_PAGE", player, 1)); + swItem.getItemStack().setAmount(1); + return swItem; + } + + @Override + public void execute(Location location, org.bukkit.block.data.type.Lectern blockData, LoaderLectern parent, int power, long ticks, Consumer delay) { + if (!blockData.hasBook()) return; + Lectern lectern = (Lectern) location.getBlock().getState(); + ItemStack itemStack = lectern.getInventory().getItem(0); + if (itemStack == null) return; + int pages = ((BookMeta) itemStack.getItemMeta()).getPages().size(); + if (1 <= pages) { + lectern.setPage(1); + parent.update(blockData); + } + } + }, + + PAGE_2 { + @Override + public int getPos() { + return 10; + } + + @Override + public SWItem menu(Player player, LoaderLectern parent, int power, long ticks) { + SWItem swItem = new SWItem(Material.LECTERN, translateItemName("LOADER_BUTTON_LECTERN", "LOADER_INTERACTION_PAGE", player, 2)); + swItem.getItemStack().setAmount(2); + return swItem; + } + + @Override + public void execute(Location location, org.bukkit.block.data.type.Lectern blockData, LoaderLectern parent, int power, long ticks, Consumer delay) { + if (!blockData.hasBook()) return; + Lectern lectern = (Lectern) location.getBlock().getState(); + ItemStack itemStack = lectern.getInventory().getItem(0); + if (itemStack == null) return; + int pages = ((BookMeta) itemStack.getItemMeta()).getPages().size(); + if (2 <= pages) { + lectern.setPage(2); + parent.update(blockData); + } + } + }, + + PAGE_3 { + @Override + public int getPos() { + return 11; + } + + @Override + public SWItem menu(Player player, LoaderLectern parent, int power, long ticks) { + SWItem swItem = new SWItem(Material.LECTERN, translateItemName("LOADER_BUTTON_LECTERN", "LOADER_INTERACTION_PAGE", player, 3)); + swItem.getItemStack().setAmount(3); + return swItem; + } + + @Override + public void execute(Location location, org.bukkit.block.data.type.Lectern blockData, LoaderLectern parent, int power, long ticks, Consumer delay) { + if (!blockData.hasBook()) return; + Lectern lectern = (Lectern) location.getBlock().getState(); + ItemStack itemStack = lectern.getInventory().getItem(0); + if (itemStack == null) return; + int pages = ((BookMeta) itemStack.getItemMeta()).getPages().size(); + if (3 <= pages) { + lectern.setPage(3); + parent.update(blockData); + } + } + }, + + PAGE_4 { + @Override + public int getPos() { + return 12; + } + + @Override + public SWItem menu(Player player, LoaderLectern parent, int power, long ticks) { + SWItem swItem = new SWItem(Material.LECTERN, translateItemName("LOADER_BUTTON_LECTERN", "LOADER_INTERACTION_PAGE", player, 4)); + swItem.getItemStack().setAmount(4); + return swItem; + } + + @Override + public void execute(Location location, org.bukkit.block.data.type.Lectern blockData, LoaderLectern parent, int power, long ticks, Consumer delay) { + if (!blockData.hasBook()) return; + Lectern lectern = (Lectern) location.getBlock().getState(); + ItemStack itemStack = lectern.getInventory().getItem(0); + if (itemStack == null) return; + int pages = ((BookMeta) itemStack.getItemMeta()).getPages().size(); + if (4 <= pages) { + lectern.setPage(4); + parent.update(blockData); + } + } + }, + + PAGE_5 { + @Override + public int getPos() { + return 13; + } + + @Override + public SWItem menu(Player player, LoaderLectern parent, int power, long ticks) { + SWItem swItem = new SWItem(Material.LECTERN, translateItemName("LOADER_BUTTON_LECTERN", "LOADER_INTERACTION_PAGE", player, 5)); + swItem.getItemStack().setAmount(5); + return swItem; + } + + @Override + public void execute(Location location, org.bukkit.block.data.type.Lectern blockData, LoaderLectern parent, int power, long ticks, Consumer delay) { + if (!blockData.hasBook()) return; + Lectern lectern = (Lectern) location.getBlock().getState(); + ItemStack itemStack = lectern.getInventory().getItem(0); + if (itemStack == null) return; + int pages = ((BookMeta) itemStack.getItemMeta()).getPages().size(); + if (5 <= pages) { + lectern.setPage(5); + parent.update(blockData); + } + } + }, + + PAGE_6 { + @Override + public int getPos() { + return 14; + } + + @Override + public SWItem menu(Player player, LoaderLectern parent, int power, long ticks) { + SWItem swItem = new SWItem(Material.LECTERN, translateItemName("LOADER_BUTTON_LECTERN", "LOADER_INTERACTION_PAGE", player, 6)); + swItem.getItemStack().setAmount(6); + return swItem; + } + + @Override + public void execute(Location location, org.bukkit.block.data.type.Lectern blockData, LoaderLectern parent, int power, long ticks, Consumer delay) { + if (!blockData.hasBook()) return; + Lectern lectern = (Lectern) location.getBlock().getState(); + ItemStack itemStack = lectern.getInventory().getItem(0); + if (itemStack == null) return; + int pages = ((BookMeta) itemStack.getItemMeta()).getPages().size(); + if (6 <= pages) { + lectern.setPage(6); + parent.update(blockData); + } + } + }, + + PAGE_7 { + @Override + public int getPos() { + return 15; + } + + @Override + public SWItem menu(Player player, LoaderLectern parent, int power, long ticks) { + SWItem swItem = new SWItem(Material.LECTERN, translateItemName("LOADER_BUTTON_LECTERN", "LOADER_INTERACTION_PAGE", player, 7)); + swItem.getItemStack().setAmount(7); + return swItem; + } + + @Override + public void execute(Location location, org.bukkit.block.data.type.Lectern blockData, LoaderLectern parent, int power, long ticks, Consumer delay) { + if (!blockData.hasBook()) return; + Lectern lectern = (Lectern) location.getBlock().getState(); + ItemStack itemStack = lectern.getInventory().getItem(0); + if (itemStack == null) return; + int pages = ((BookMeta) itemStack.getItemMeta()).getPages().size(); + if (7 <= pages) { + lectern.setPage(7); + parent.update(blockData); + } + } + }, + + PAGE_8 { + @Override + public int getPos() { + return 16; + } + + @Override + public SWItem menu(Player player, LoaderLectern parent, int power, long ticks) { + SWItem swItem = new SWItem(Material.LECTERN, translateItemName("LOADER_BUTTON_LECTERN", "LOADER_INTERACTION_PAGE", player, 8)); + swItem.getItemStack().setAmount(8); + return swItem; + } + + @Override + public void execute(Location location, org.bukkit.block.data.type.Lectern blockData, LoaderLectern parent, int power, long ticks, Consumer delay) { + if (!blockData.hasBook()) return; + Lectern lectern = (Lectern) location.getBlock().getState(); + ItemStack itemStack = lectern.getInventory().getItem(0); + if (itemStack == null) return; + int pages = ((BookMeta) itemStack.getItemMeta()).getPages().size(); + if (8 <= pages) { + lectern.setPage(8); + parent.update(blockData); + } + } + }, + + PAGE_9 { + @Override + public int getPos() { + return 17; + } + + @Override + public SWItem menu(Player player, LoaderLectern parent, int power, long ticks) { + SWItem swItem = new SWItem(Material.LECTERN, translateItemName("LOADER_BUTTON_LECTERN", "LOADER_INTERACTION_PAGE", player, 9)); + swItem.getItemStack().setAmount(9); + return swItem; + } + + @Override + public void execute(Location location, org.bukkit.block.data.type.Lectern blockData, LoaderLectern parent, int power, long ticks, Consumer delay) { + if (!blockData.hasBook()) return; + Lectern lectern = (Lectern) location.getBlock().getState(); + ItemStack itemStack = lectern.getInventory().getItem(0); + if (itemStack == null) return; + int pages = ((BookMeta) itemStack.getItemMeta()).getPages().size(); + if (9 <= pages) { + lectern.setPage(9); + parent.update(blockData); + } + } + }, + + PAGE_10 { + @Override + public int getPos() { + return 19; + } + + @Override + public SWItem menu(Player player, LoaderLectern parent, int power, long ticks) { + SWItem swItem = new SWItem(Material.LECTERN, translateItemName("LOADER_BUTTON_LECTERN", "LOADER_INTERACTION_PAGE", player, 10)); + swItem.getItemStack().setAmount(10); + return swItem; + } + + @Override + public void execute(Location location, org.bukkit.block.data.type.Lectern blockData, LoaderLectern parent, int power, long ticks, Consumer delay) { + if (!blockData.hasBook()) return; + Lectern lectern = (Lectern) location.getBlock().getState(); + ItemStack itemStack = lectern.getInventory().getItem(0); + if (itemStack == null) return; + int pages = ((BookMeta) itemStack.getItemMeta()).getPages().size(); + if (10 <= pages) { + lectern.setPage(10); + parent.update(blockData); + } + } + }, + + PAGE_11 { + @Override + public int getPos() { + return 20; + } + + @Override + public SWItem menu(Player player, LoaderLectern parent, int power, long ticks) { + SWItem swItem = new SWItem(Material.LECTERN, translateItemName("LOADER_BUTTON_LECTERN", "LOADER_INTERACTION_PAGE", player, 11)); + swItem.getItemStack().setAmount(11); + return swItem; + } + + @Override + public void execute(Location location, org.bukkit.block.data.type.Lectern blockData, LoaderLectern parent, int power, long ticks, Consumer delay) { + if (!blockData.hasBook()) return; + Lectern lectern = (Lectern) location.getBlock().getState(); + ItemStack itemStack = lectern.getInventory().getItem(0); + if (itemStack == null) return; + int pages = ((BookMeta) itemStack.getItemMeta()).getPages().size(); + if (11 <= pages) { + lectern.setPage(11); + parent.update(blockData); + } + } + }, + + PAGE_12 { + @Override + public int getPos() { + return 21; + } + + @Override + public SWItem menu(Player player, LoaderLectern parent, int power, long ticks) { + SWItem swItem = new SWItem(Material.LECTERN, translateItemName("LOADER_BUTTON_LECTERN", "LOADER_INTERACTION_PAGE", player, 12)); + swItem.getItemStack().setAmount(12); + return swItem; + } + + @Override + public void execute(Location location, org.bukkit.block.data.type.Lectern blockData, LoaderLectern parent, int power, long ticks, Consumer delay) { + if (!blockData.hasBook()) return; + Lectern lectern = (Lectern) location.getBlock().getState(); + ItemStack itemStack = lectern.getInventory().getItem(0); + if (itemStack == null) return; + int pages = ((BookMeta) itemStack.getItemMeta()).getPages().size(); + if (12 <= pages) { + lectern.setPage(12); + parent.update(blockData); + } + } + }, + + PAGE_13 { + @Override + public int getPos() { + return 23; + } + + @Override + public SWItem menu(Player player, LoaderLectern parent, int power, long ticks) { + SWItem swItem = new SWItem(Material.LECTERN, translateItemName("LOADER_BUTTON_LECTERN", "LOADER_INTERACTION_PAGE", player, 13)); + swItem.getItemStack().setAmount(13); + return swItem; + } + + @Override + public void execute(Location location, org.bukkit.block.data.type.Lectern blockData, LoaderLectern parent, int power, long ticks, Consumer delay) { + if (!blockData.hasBook()) return; + Lectern lectern = (Lectern) location.getBlock().getState(); + ItemStack itemStack = lectern.getInventory().getItem(0); + if (itemStack == null) return; + int pages = ((BookMeta) itemStack.getItemMeta()).getPages().size(); + if (13 <= pages) { + lectern.setPage(13); + parent.update(blockData); + } + } + }, + + PAGE_14 { + @Override + public int getPos() { + return 24; + } + + @Override + public SWItem menu(Player player, LoaderLectern parent, int power, long ticks) { + SWItem swItem = new SWItem(Material.LECTERN, translateItemName("LOADER_BUTTON_LECTERN", "LOADER_INTERACTION_PAGE", player, 14)); + swItem.getItemStack().setAmount(14); + return swItem; + } + + @Override + public void execute(Location location, org.bukkit.block.data.type.Lectern blockData, LoaderLectern parent, int power, long ticks, Consumer delay) { + if (!blockData.hasBook()) return; + Lectern lectern = (Lectern) location.getBlock().getState(); + ItemStack itemStack = lectern.getInventory().getItem(0); + if (itemStack == null) return; + int pages = ((BookMeta) itemStack.getItemMeta()).getPages().size(); + if (14 <= pages) { + lectern.setPage(14); + parent.update(blockData); + } + } + }, + + PAGE_15 { + @Override + public int getPos() { + return 25; + } + + @Override + public SWItem menu(Player player, LoaderLectern parent, int power, long ticks) { + SWItem swItem = new SWItem(Material.LECTERN, translateItemName("LOADER_BUTTON_LECTERN", "LOADER_INTERACTION_PAGE", player, 15)); + swItem.getItemStack().setAmount(15); + return swItem; + } + + @Override + public void execute(Location location, org.bukkit.block.data.type.Lectern blockData, LoaderLectern parent, int power, long ticks, Consumer delay) { + if (!blockData.hasBook()) return; + Lectern lectern = (Lectern) location.getBlock().getState(); + ItemStack itemStack = lectern.getInventory().getItem(0); + if (itemStack == null) return; + int pages = ((BookMeta) itemStack.getItemMeta()).getPages().size(); + if (15 <= pages) { + lectern.setPage(15); + parent.update(blockData); + } + } + } } @Override @@ -153,7 +514,7 @@ public class LoaderLectern extends LoaderInteractionElement { +public class LoaderLever extends LoaderInteractionElement { public LoaderLever(Location location) { - super(location); + super(location, LeverSettingsEnum.INTERACT, LeverSettingsEnum.NOOP, LeverSettingsEnum.values()); } - public class LeverSettings implements ElementSettings { + public enum LeverSettingsEnum implements LoaderSettingsEnum { - private boolean noop = false; - private boolean interact = true; - private boolean power = false; - - @Override - public SWItem menu(Player player) { - return menu(player, noop, interact, power); - } - - private SWItem menu(Player player, boolean noop, boolean interact, boolean power) { - SWItem swItem; - if (noop) { - swItem = new SWItem(Material.STRUCTURE_VOID, translateItemName("LOADER_BUTTON_SWITCH", "LOADER_INTERACTION_NOOP", player)); - } else if (interact) { - swItem = new SWItem(Material.STICK, translateItemName("LOADER_BUTTON_SWITCH", "LOADER_INTERACTION_INTERACT", player)); - } else { - swItem = new SWItem(Material.LEVER, translateItemName("LOADER_BUTTON_SWITCH", power ? "LOADER_INTERACTION_ACTIVE" : "LOADER_INTERACTION_INACTIVE", player)); + NOOP { + @Override + public int getPos() { + return 2; } - swItem.setLore(Arrays.asList(BauSystem.MESSAGE.parse("LOADER_GUI_CLICK_TO_EDIT", player))); - return swItem; - } - @Override - public void execute(Consumer delay) { - if (location.getBlock().getType() != Material.LEVER) return; - if (noop) return; - - Switch lever = (Switch) location.getBlock().getBlockData(); - if (interact) { - lever.setPowered(!lever.isPowered()); - } else { - lever.setPowered(power); + @Override + public SWItem menu(Player player, LoaderLever parent, int power, long ticks) { + return new SWItem(Material.STRUCTURE_VOID, translateItemName("LOADER_BUTTON_SWITCH", "LOADER_INTERACTION_NOOP", player)); } - location.getBlock().setBlockData(lever, true); - } - @Override - public void click(Player player, Runnable backAction, Runnable deleteAction) { - SWInventory swInventory = new SWInventory(player, 18, BauSystem.MESSAGE.parse("LOADER_GUI_SETTINGS_TITLE", player)); - for (int i = 9; i < 18; i++) swInventory.setItem(i, new SWItem(Material.GRAY_STAINED_GLASS_PANE, "§7")); - swInventory.setItem(9, new SWItem(Material.ARROW, BauSystem.MESSAGE.parse("LOADER_GUI_SETTINGS_BACK", player)).getItemStack(), clickType -> backAction.run()); - swInventory.setItem(17, new SWItem(Material.BARRIER, BauSystem.MESSAGE.parse("LOADER_GUI_SETTINGS_DELETE", player)).getItemStack(), clickType -> deleteAction.run()); - - swInventory.setItem(2, item(player, true, false, false).getItemStack(), clickType -> { - noop = true; - click(player, backAction, deleteAction); - }); - swInventory.setItem(3, item(player, false, true, false).getItemStack(), clickType -> { - noop = false; - interact = true; - click(player, backAction, deleteAction); - }); - swInventory.setItem(5, item(player, false, false, false).getItemStack(), clickType -> { - noop = false; - interact = false; - power = false; - click(player, backAction, deleteAction); - }); - swInventory.setItem(6, item(player, false, false, true).getItemStack(), clickType -> { - noop = false; - interact = false; - power = true; - click(player, backAction, deleteAction); - }); - - swInventory.open(); - } - - private SWItem item(Player player, boolean noop, boolean interact, boolean power) { - SWItem swItem = menu(player, noop, interact, power); - if (swItem.getItemStack().equals(menu(player, this.noop, this.interact, this.power).getItemStack())) { - swItem.setEnchanted(true); + @Override + public void execute(Location location, Switch blockData, LoaderLever parent, int power, long ticks, Consumer delay) { } - swItem.setLore(Collections.emptyList()); - return swItem; - } + }, - @Override - public void noop() { - noop = true; + INTERACT { + @Override + public int getPos() { + return 3; + } + + @Override + public SWItem menu(Player player, LoaderLever parent, int power, long ticks) { + return new SWItem(Material.STICK, translateItemName("LOADER_BUTTON_SWITCH", "LOADER_INTERACTION_INTERACT", player)); + } + + @Override + public void execute(Location location, Switch blockData, LoaderLever parent, int power, long ticks, Consumer delay) { + blockData.setPowered(!blockData.isPowered()); + parent.update(blockData); + } + }, + + POWER_OFF { + @Override + public int getPos() { + return 5; + } + + @Override + public SWItem menu(Player player, LoaderLever parent, int power, long ticks) { + return new SWItem(Material.LEVER, translateItemName("LOADER_BUTTON_SWITCH", "LOADER_INTERACTION_INACTIVE", player)); + } + + @Override + public void execute(Location location, Switch blockData, LoaderLever parent, int power, long ticks, Consumer delay) { + blockData.setPowered(false); + parent.update(blockData); + } + }, + + POWER_ON { + @Override + public int getPos() { + return 6; + } + + @Override + public SWItem menu(Player player, LoaderLever parent, int power, long ticks) { + return new SWItem(Material.LEVER, translateItemName("LOADER_BUTTON_SWITCH", "LOADER_INTERACTION_ACTIVE", player)); + } + + @Override + public void execute(Location location, Switch blockData, LoaderLever parent, int power, long ticks, Consumer delay) { + blockData.setPowered(true); + } } } @@ -130,7 +113,7 @@ public class LoaderLever extends LoaderInteractionElement { +public class LoaderMovement extends LoaderInteractionElement { private String name; private Material material; private boolean analogue; public LoaderMovement(Location location, String name, Material material) { - super(location); + super(location, MovementSettingsEnum.NO_WAIT_FOR, MovementSettingsEnum.NOOP, MovementSettingsEnum.values()); this.name = name; this.material = material; this.analogue = location.getBlock().getBlockData() instanceof AnaloguePowerable; @@ -52,167 +47,108 @@ public class LoaderMovement extends LoaderInteractionElement { - private boolean noop = false; - private boolean waitFor = false; - private int power = 15; - private long ticks = 1; - - @Override - public SWItem menu(Player player) { - return menu(player, noop, waitFor); - } - - private SWItem menu(Player player, boolean noop, boolean waitFor) { - SWItem swItem; - if (noop) { - swItem = new SWItem(Material.STRUCTURE_VOID, translateItemName(name, "LOADER_INTERACTION_NOOP", player)); - } else if (waitFor) { - swItem = new SWItem(material, translateItemName(name, "LOADER_INTERACTION_WAIT_FOR", player)); - swItem.getItemStack().setAmount((int) Math.min(ticks, 64)); - } else { - swItem = new SWItem(material, translateItemName(name, "LOADER_INTERACTION_NO_WAIT_FOR", player)); - swItem.getItemStack().setAmount((int) Math.min(ticks, 64)); - swItem.setEnchanted(true); - } - swItem.setLore(Arrays.asList(BauSystem.MESSAGE.parse("LOADER_GUI_CLICK_TO_EDIT", player))); - return swItem; - } - - @Override - public void execute(Consumer delay) { - if (!(material == Material.STRING && location.getBlock().getType() == Material.TRIPWIRE) && location.getBlock().getType() != material) return; - if (noop) return; - - BlockData blockData = location.getBlock().getBlockData(); - if (blockData instanceof AnaloguePowerable) { - AnaloguePowerable analoguePowerable = (AnaloguePowerable) location.getBlock().getBlockData(); - analoguePowerable.setPower(power); - location.getBlock().setBlockData(analoguePowerable, true); - update(analoguePowerable); - } else if (blockData instanceof Powerable) { - Powerable powerable = (Powerable) location.getBlock().getBlockData(); - if (ticks < 0) { - powerable.setPowered(power > 0); - } else { - powerable.setPowered(true); - } - location.getBlock().setBlockData(powerable, true); - update(powerable); + NOOP { + @Override + public int getPos() { + return 2; } - if (ticks >= 0) { - if (waitFor) { - delay.accept(ticks); + @Override + public SWItem menu(Player player, LoaderMovement parent, int power, long ticks) { + return new SWItem(Material.STRUCTURE_VOID, translateItemName(parent.name, "LOADER_INTERACTION_NOOP", player)); + } + + @Override + public void execute(Location location, BlockData blockData, LoaderMovement parent, int power, long ticks, Consumer delay) { + } + }, + + NO_WAIT_FOR { + @Override + public int getPos() { + return 5; + } + + @Override + public SWItem menu(Player player, LoaderMovement parent, int power, long ticks) { + SWItem swItem = new SWItem(parent.material, translateItemName(parent.name, "LOADER_INTERACTION_WAIT_FOR", player)); + swItem.getItemStack().setAmount((int) Math.min(ticks, 64)); + return swItem; + } + + @Override + public boolean hasPower(LoaderMovement parent) { + return parent.analogue; + } + + @Override + public boolean hasTicks(LoaderMovement parent) { + return true; + } + + @Override + public void execute(Location location, BlockData blockData, LoaderMovement parent, int power, long ticks, Consumer delay) { + if (blockData instanceof AnaloguePowerable) { + AnaloguePowerable analoguePowerable = (AnaloguePowerable) location.getBlock().getBlockData(); + analoguePowerable.setPower(power); + parent.update(analoguePowerable); + } else if (blockData instanceof Powerable) { + Powerable powerable = (Powerable) location.getBlock().getBlockData(); + if (ticks < 0) { + powerable.setPowered(power > 0); + } else { + powerable.setPowered(true); + } + parent.update(powerable); } + BauSystem.runTaskLater(BauSystem.getInstance(), () -> { if (blockData instanceof AnaloguePowerable) { AnaloguePowerable analoguePowerable = (AnaloguePowerable) blockData; analoguePowerable.setPower(0); - location.getBlock().setBlockData(analoguePowerable, true); - update(analoguePowerable); + parent.update(analoguePowerable); } else { Powerable powerable = (Powerable) blockData; powerable.setPowered(false); - location.getBlock().setBlockData(powerable, true); - update(powerable); + parent.update(powerable); } }, ticks); } - } + }, - @Override - public void click(Player player, Runnable backAction, Runnable deleteAction) { - SWInventory swInventory = new SWInventory(player, analogue ? 45 : 27, BauSystem.MESSAGE.parse("LOADER_GUI_SETTINGS_TITLE", player)); - for (int i = analogue ? 36 : 18; i < (analogue ? 44 : 26); i++) swInventory.setItem(i, new SWItem(Material.GRAY_STAINED_GLASS_PANE, "§7")); - swInventory.setItem(analogue ? 36 : 18, new SWItem(Material.ARROW, BauSystem.MESSAGE.parse("LOADER_GUI_SETTINGS_BACK", player)).getItemStack(), clickType -> backAction.run()); - swInventory.setItem(analogue ? 44 : 26, new SWItem(Material.BARRIER, BauSystem.MESSAGE.parse("LOADER_GUI_SETTINGS_DELETE", player)).getItemStack(), clickType -> deleteAction.run()); - - swInventory.setItem(2, item(player, true, false).getItemStack(), clickType -> { - noop = true; - click(player, backAction, deleteAction); - }); - if (ticks >= 0) { - swInventory.setItem(5, item(player, false, false).getItemStack(), clickType -> { - noop = false; - waitFor = false; - click(player, backAction, deleteAction); - }); - swInventory.setItem(6, item(player, false, true).getItemStack(), clickType -> { - noop = false; - waitFor = true; - click(player, backAction, deleteAction); - }); + WAIT_FOR { + @Override + public int getPos() { + return 6; } - swInventory.setItem(12, new SWItem(SWItem.getDye(1), BauSystem.MESSAGE.parse("LOADER_SETTING_TICKS_REMOVE_ONE", player), Arrays.asList(BauSystem.MESSAGE.parse("LOADER_SETTING_TICKS_REMOVE_ONE_SHIFT", player)), false, clickType -> {}).getItemStack(), clickType -> { - ticks -= clickType.isShiftClick() ? 5 : 1; - if (ticks < 1) ticks = 1; - swInventory.setItem(13, item(player)); - }); - swInventory.setItem(13, item(player).getItemStack(), clickType -> { - SWAnvilInv swAnvilInv = new SWAnvilInv(player, BauSystem.MESSAGE.parse("LOADER_SETTING_TICKS_NAME", player), ticks + ""); - swAnvilInv.setCallback(s -> { - try { - ticks = Long.parseLong(s); - if (ticks < 1) ticks = 1; - } catch (NumberFormatException ignored) { - } - click(player, backAction, deleteAction); - }); - swAnvilInv.open(); - }); - swInventory.setItem(14, new SWItem(SWItem.getDye(10), BauSystem.MESSAGE.parse("LOADER_SETTING_TICKS_ADD_ONE", player), Arrays.asList(BauSystem.MESSAGE.parse("LOADER_SETTING_TICKS_ADD_ONE_SHIFT", player)), false, clickType -> {}).getItemStack(), clickType -> { - ticks += clickType.isShiftClick() ? 5 : 1; - swInventory.setItem(13, item(player)); - }); - - if (analogue) { - for (int i = 0; i < 16; i++) { - int finalI = i; - int finalI2 = i; - if (i >= 9) finalI2++; - swInventory.setItem(finalI2 + 18, item(player, finalI).getItemStack(), clickType -> { - power = finalI; - click(player, backAction, deleteAction); - }); - } + @Override + public SWItem menu(Player player, LoaderMovement parent, int power, long ticks) { + SWItem swItem = new SWItem(parent.material, translateItemName(parent.name, "LOADER_INTERACTION_NO_WAIT_FOR", player)); + swItem.getItemStack().setAmount((int) Math.min(ticks, 64)); + return swItem; } - swInventory.open(); - } - - private SWItem item(Player player, boolean noop, boolean waitFor) { - SWItem swItem = menu(player, noop, waitFor); - if (swItem.getItemStack().equals(menu(player, this.noop, this.waitFor).getItemStack())) { - swItem.setEnchanted(true); + @Override + public boolean hasPower(LoaderMovement parent) { + return parent.analogue; } - swItem.setLore(Collections.emptyList()); - return swItem; - } - private SWItem item(Player player, int power) { - SWItem swItem = new SWItem(power == 0 ? Material.GUNPOWDER : Material.REDSTONE, BauSystem.MESSAGE.parse("LOADER_SETTING_POWER", player, power)); - swItem.getItemStack().setAmount(power == 0 ? 1 : power); - if (!this.noop && this.power == power) swItem.setEnchanted(true); - return swItem; - } + @Override + public boolean hasTicks(LoaderMovement parent) { + return true; + } - private SWItem item(Player player) { - SWItem swItem = new SWItem(Material.CLOCK, BauSystem.MESSAGE.parse("LOADER_SETTING_TICKS", player, ticks)); - swItem.getItemStack().setAmount((int) Math.min(ticks, 64)); - swItem.setLore(Arrays.asList(BauSystem.MESSAGE.parse("LOADER_GUI_CLICK_TO_EDIT", player))); - return swItem; - } - - @Override - public void noop() { - noop = true; - waitFor = false; + @Override + public void execute(Location location, BlockData blockData, LoaderMovement parent, int power, long ticks, Consumer delay) { + NO_WAIT_FOR.execute(location, blockData, parent, power, ticks, delay); + delay.accept(ticks); + } } } @@ -222,7 +158,8 @@ public class LoaderMovement extends LoaderInteractionElement { +public class LoaderNoteBlock extends LoaderInteractionElement { public LoaderNoteBlock(Location location) { - super(location); + super(location, NoteBlockSettingsEnum.INTERACT, NoteBlockSettingsEnum.NOOP, NoteBlockSettingsEnum.values()); } - public class NoteBlockSettings implements ElementSettings { + public enum NoteBlockSettingsEnum implements LoaderSettingsEnum { - private boolean interact = true; - - @Override - public SWItem menu(Player player) { - return menu(player, interact); - } - - private SWItem menu(Player player, boolean interact) { - SWItem swItem; - if (interact) { - swItem = new SWItem(Material.NOTE_BLOCK, translateItemName("LOADER_BUTTON_NOTEBLOCK", "LOADER_INTERACTION_INTERACT", player)); - } else { - swItem = new SWItem(Material.STRUCTURE_VOID, translateItemName("LOADER_BUTTON_NOTEBLOCK", "LOADER_INTERACTION_NOOP", player)); + NOOP { + @Override + public int getPos() { + return 2; } - swItem.setLore(Arrays.asList(BauSystem.MESSAGE.parse("LOADER_GUI_CLICK_TO_EDIT", player))); - return swItem; - } - @Override - public void execute(Consumer delay) { - if (location.getBlock().getType() != Material.NOTE_BLOCK) return; - NoteBlock noteBlock = (NoteBlock) location.getBlock().getBlockData(); - if (interact) { - if (noteBlock.getInstrument() == Instrument.BANJO) noteBlock.setInstrument(Instrument.BIT); - else noteBlock.setInstrument(Instrument.BANJO); - } else { - return; + @Override + public SWItem menu(Player player, LoaderNoteBlock parent, int power, long ticks) { + return new SWItem(Material.STRUCTURE_VOID, translateItemName("LOADER_BUTTON_NOTEBLOCK", "LOADER_INTERACTION_NOOP", player)); } - location.getBlock().setBlockData(noteBlock); - } - @Override - public void click(Player player, Runnable backAction, Runnable deleteAction) { - SWInventory swInventory = new SWInventory(player, 18, BauSystem.MESSAGE.parse("LOADER_GUI_SETTINGS_TITLE", player)); - for (int i = 9; i < 18; i++) swInventory.setItem(i, new SWItem(Material.GRAY_STAINED_GLASS_PANE, "§7")); - swInventory.setItem(9, new SWItem(Material.ARROW, BauSystem.MESSAGE.parse("LOADER_GUI_SETTINGS_BACK", player)).getItemStack(), clickType -> backAction.run()); - swInventory.setItem(17, new SWItem(Material.BARRIER, BauSystem.MESSAGE.parse("LOADER_GUI_SETTINGS_DELETE", player)).getItemStack(), clickType -> deleteAction.run()); + @Override + public void execute(Location location, NoteBlock blockData, LoaderNoteBlock parent, int power, long ticks, Consumer delay) { - swInventory.setItem(2, item(player, false).getItemStack(), clickType -> { - interact = false; - click(player, backAction, deleteAction); - }); - swInventory.setItem(3, item(player, true).getItemStack(), clickType -> { - interact = true; - click(player, backAction, deleteAction); - }); - - swInventory.open(); - } - - private SWItem item(Player player, boolean interact) { - SWItem swItem = menu(player, interact); - if (swItem.getItemStack().equals(menu(player, this.interact).getItemStack())) { - swItem.setEnchanted(true); } - swItem.setLore(Collections.emptyList()); - return swItem; - } + }, - @Override - public void noop() { - interact = false; + INTERACT { + @Override + public int getPos() { + return 3; + } + + @Override + public SWItem menu(Player player, LoaderNoteBlock parent, int power, long ticks) { + return new SWItem(Material.NOTE_BLOCK, translateItemName("LOADER_BUTTON_NOTEBLOCK", "LOADER_INTERACTION_INTERACT", player)); + } + + @Override + public void execute(Location location, NoteBlock blockData, LoaderNoteBlock parent, int power, long ticks, Consumer delay) { + if (blockData.getInstrument() == Instrument.BANJO) blockData.setInstrument(Instrument.BIT); + else blockData.setInstrument(Instrument.BANJO); + parent.update(blockData); + } } } @@ -113,7 +81,7 @@ public class LoaderNoteBlock extends LoaderInteractionElement { +public class LoaderOpenable extends LoaderInteractionElement { private String name; private Material material; public LoaderOpenable(Location location, String name, Material material) { - super(location); + super(location, OpenableSettingsEnum.INTERACT, OpenableSettingsEnum.NOOP, OpenableSettingsEnum.values()); this.name = name; this.material = material; } - public class TrapdoorSettings implements ElementSettings { + public enum OpenableSettingsEnum implements LoaderSettingsEnum { - private boolean noop = false; - private boolean interact = true; - private boolean open = false; - - @Override - public SWItem menu(Player player) { - return menu(player, noop, interact, open); - } - - private SWItem menu(Player player, boolean noop, boolean interact, boolean powered) { - SWItem swItem; - if (noop) { - swItem = new SWItem(Material.STRUCTURE_VOID, translateItemName(name, "LOADER_INTERACTION_NOOP", player)); - } else if (interact) { - swItem = new SWItem(Material.STICK, translateItemName(name, "LOADER_INTERACTION_INTERACT", player)); - } else { - swItem = new SWItem(material, translateItemName(name, open ? "LOADER_INTERACTION_OPEN" : "LOADER_INTERACTION_CLOSED", player)); + NOOP { + @Override + public int getPos() { + return 2; } - swItem.setLore(Arrays.asList(BauSystem.MESSAGE.parse("LOADER_GUI_CLICK_TO_EDIT", player))); - return swItem; - } - @Override - public void execute(Consumer delay) { - if (location.getBlock().getType() != material) return; - Openable openable = (Openable) location.getBlock().getBlockData(); - if (noop) { - return; - } else if (interact) { - openable.setOpen(!openable.isOpen()); - } else { - openable.setOpen(open); + @Override + public SWItem menu(Player player, LoaderOpenable parent, int power, long ticks) { + return new SWItem(Material.STRUCTURE_VOID, translateItemName(parent.name, "LOADER_INTERACTION_NOOP", player)); } - location.getBlock().setBlockData(openable); - } - @Override - public void click(Player player, Runnable backAction, Runnable deleteAction) { - SWInventory swInventory = new SWInventory(player, 18, BauSystem.MESSAGE.parse("LOADER_GUI_SETTINGS_TITLE", player)); - for (int i = 9; i < 18; i++) swInventory.setItem(i, new SWItem(Material.GRAY_STAINED_GLASS_PANE, "§7")); - swInventory.setItem(9, new SWItem(Material.ARROW, BauSystem.MESSAGE.parse("LOADER_GUI_SETTINGS_BACK", player)).getItemStack(), clickType -> backAction.run()); - swInventory.setItem(17, new SWItem(Material.BARRIER, BauSystem.MESSAGE.parse("LOADER_GUI_SETTINGS_DELETE", player)).getItemStack(), clickType -> deleteAction.run()); - - swInventory.setItem(2, item(player, true, false, false).getItemStack(), clickType -> { - noop = true; - click(player, backAction, deleteAction); - }); - swInventory.setItem(3, item(player, false, true, false).getItemStack(), clickType -> { - noop = false; - interact = true; - click(player, backAction, deleteAction); - }); - swInventory.setItem(5, item(player, false, false, false).getItemStack(), clickType -> { - noop = false; - interact = false; - open = false; - click(player, backAction, deleteAction); - }); - swInventory.setItem(6, item(player, false, false, true).getItemStack(), clickType -> { - noop = false; - interact = false; - open = true; - click(player, backAction, deleteAction); - }); - - swInventory.open(); - } - - private SWItem item(Player player, boolean noop, boolean interact, boolean open) { - SWItem swItem = menu(player, noop, interact, open); - if (swItem.getItemStack().equals(menu(player, this.noop, this.interact, this.open).getItemStack())) { - swItem.setEnchanted(true); + @Override + public void execute(Location location, Openable blockData, LoaderOpenable parent, int power, long ticks, Consumer delay) { } - swItem.setLore(Collections.emptyList()); - return swItem; - } + }, - @Override - public void noop() { - noop = true; + INTERACT { + @Override + public int getPos() { + return 3; + } + + @Override + public SWItem menu(Player player, LoaderOpenable parent, int power, long ticks) { + return new SWItem(Material.STICK, translateItemName(parent.name, "LOADER_INTERACTION_INTERACT", player)); + } + + @Override + public void execute(Location location, Openable blockData, LoaderOpenable parent, int power, long ticks, Consumer delay) { + blockData.setOpen(!blockData.isOpen()); + parent.update(blockData); + } + }, + + CLOSED { + @Override + public int getPos() { + return 5; + } + + @Override + public SWItem menu(Player player, LoaderOpenable parent, int power, long ticks) { + return new SWItem(parent.material, translateItemName(parent.name, "LOADER_INTERACTION_CLOSED", player)); + } + + @Override + public void execute(Location location, Openable blockData, LoaderOpenable parent, int power, long ticks, Consumer delay) { + blockData.setOpen(false); + parent.update(blockData); + } + }, + + OPEN { + @Override + public int getPos() { + return 6; + } + + @Override + public SWItem menu(Player player, LoaderOpenable parent, int power, long ticks) { + return new SWItem(parent.material, translateItemName(parent.name, "LOADER_INTERACTION_OPEN", player)); + } + + @Override + public void execute(Location location, Openable blockData, LoaderOpenable parent, int power, long ticks, Consumer delay) { + blockData.setOpen(true); + parent.update(blockData); + } } } @@ -135,7 +119,7 @@ public class LoaderOpenable extends LoaderInteractionElement { +public class LoaderRepeater extends LoaderInteractionElement { public LoaderRepeater(Location location) { - super(location); + super(location, RepeaterSettingsEnum.INTERACT, RepeaterSettingsEnum.NOOP, RepeaterSettingsEnum.values()); } - public class RepeaterSettings implements ElementSettings { + public enum RepeaterSettingsEnum implements LoaderSettingsEnum { - private boolean interact = false; - private int delay = 1; - - @Override - public SWItem menu(Player player) { - return menu(player, interact, delay); - } - - private SWItem menu(Player player, boolean interact, int delay) { - SWItem swItem; - if (interact) { - swItem = new SWItem(Material.STICK, translateItemName("LOADER_BUTTON_REPEATER", "LOADER_INTERACTION_INTERACT", player)); - } else if (delay == 0) { - swItem = new SWItem(Material.STRUCTURE_VOID, translateItemName("LOADER_BUTTON_REPEATER", "LOADER_INTERACTION_NOOP", player)); - } else { - swItem = new SWItem(Material.REPEATER, BauSystem.MESSAGE.parse("LOADER_SETTING_REPEATER", player, delay)); - swItem.getItemStack().setAmount(delay); + NOOP { + @Override + public int getPos() { + return 1; } - swItem.setLore(Arrays.asList(BauSystem.MESSAGE.parse("LOADER_GUI_CLICK_TO_EDIT", player))); - return swItem; - } - @Override - public void execute(Consumer __) { - if (location.getBlock().getType() != Material.REPEATER) return; - Repeater repeater = (Repeater) location.getBlock().getBlockData(); - if (interact) { - int delay = repeater.getDelay(); - delay++; - if (delay > 4) delay = 1; - repeater.setDelay(delay); - } else if (delay == 0) { - return; - } else { - repeater.setDelay(delay); + @Override + public SWItem menu(Player player, LoaderRepeater parent, int power, long ticks) { + return new SWItem(Material.STRUCTURE_VOID, translateItemName("LOADER_BUTTON_REPEATER", "LOADER_INTERACTION_NOOP", player)); } - location.getBlock().setBlockData(repeater, true); - } - @Override - public void click(Player player, Runnable backAction, Runnable deleteAction) { - SWInventory swInventory = new SWInventory(player, 18, BauSystem.MESSAGE.parse("LOADER_GUI_SETTINGS_TITLE", player)); - for (int i = 9; i < 18; i++) swInventory.setItem(i, new SWItem(Material.GRAY_STAINED_GLASS_PANE, "§7")); - swInventory.setItem(9, new SWItem(Material.ARROW, BauSystem.MESSAGE.parse("LOADER_GUI_SETTINGS_BACK", player)).getItemStack(), clickType -> backAction.run()); - swInventory.setItem(17, new SWItem(Material.BARRIER, BauSystem.MESSAGE.parse("LOADER_GUI_SETTINGS_DELETE", player)).getItemStack(), clickType -> deleteAction.run()); + @Override + public void execute(Location location, Repeater blockData, LoaderRepeater parent, int power, long ticks, Consumer delay) { - swInventory.setItem(1, item(player, false, 0).getItemStack(), clickType -> { - interact = false; - delay = 0; - click(player, backAction, deleteAction); - }); - swInventory.setItem(2, item(player, true, -1).getItemStack(), clickType -> { - interact = true; - click(player, backAction, deleteAction); - }); - swInventory.setItem(4, item(player, false, 1).getItemStack(), clickType -> { - interact = false; - delay = 1; - click(player, backAction, deleteAction); - }); - swInventory.setItem(5, item(player, false, 2).getItemStack(), clickType -> { - interact = false; - delay = 2; - click(player, backAction, deleteAction); - }); - swInventory.setItem(6, item(player, false, 3).getItemStack(), clickType -> { - interact = false; - delay = 3; - click(player, backAction, deleteAction); - }); - swInventory.setItem(7, item(player, false, 4).getItemStack(), clickType -> { - interact = false; - delay = 4; - click(player, backAction, deleteAction); - }); - - swInventory.open(); - } - - private SWItem item(Player player, boolean interact, int delay) { - SWItem swItem = menu(player, interact, delay); - if (swItem.getItemStack().equals(menu(player, this.interact, this.delay).getItemStack())) { - swItem.setEnchanted(true); } - swItem.setLore(Collections.emptyList()); - return swItem; - } + }, - @Override - public void playerInteract() { - interact = true; - delay = 0; - } + INTERACT { + @Override + public int getPos() { + return 2; + } - @Override - public void noop() { - interact = false; - delay = 0; + @Override + public SWItem menu(Player player, LoaderRepeater parent, int power, long ticks) { + return new SWItem(Material.STICK, translateItemName("LOADER_BUTTON_REPEATER", "LOADER_INTERACTION_INTERACT", player)); + } + + @Override + public void execute(Location location, Repeater blockData, LoaderRepeater parent, int power, long ticks, Consumer delay) { + int repeaterDelay = blockData.getDelay(); + repeaterDelay++; + if (repeaterDelay > 4) repeaterDelay = 1; + blockData.setDelay(repeaterDelay); + parent.update(blockData); + } + }, + + DELAY_1 { + @Override + public int getPos() { + return 4; + } + + @Override + public SWItem menu(Player player, LoaderRepeater parent, int power, long ticks) { + SWItem swItem = new SWItem(Material.REPEATER, BauSystem.MESSAGE.parse("LOADER_SETTING_REPEATER", player, 1)); + swItem.getItemStack().setAmount(1); + return swItem; + } + + @Override + public void execute(Location location, Repeater blockData, LoaderRepeater parent, int power, long ticks, Consumer delay) { + blockData.setDelay(1); + parent.update(blockData); + } + }, + + DELAY_2 { + @Override + public int getPos() { + return 5; + } + + @Override + public SWItem menu(Player player, LoaderRepeater parent, int power, long ticks) { + SWItem swItem = new SWItem(Material.REPEATER, BauSystem.MESSAGE.parse("LOADER_SETTING_REPEATER", player, 2)); + swItem.getItemStack().setAmount(2); + return swItem; + } + + @Override + public void execute(Location location, Repeater blockData, LoaderRepeater parent, int power, long ticks, Consumer delay) { + blockData.setDelay(2); + parent.update(blockData); + } + }, + + DELAY_3 { + @Override + public int getPos() { + return 6; + } + + @Override + public SWItem menu(Player player, LoaderRepeater parent, int power, long ticks) { + SWItem swItem = new SWItem(Material.REPEATER, BauSystem.MESSAGE.parse("LOADER_SETTING_REPEATER", player, 3)); + swItem.getItemStack().setAmount(3); + return swItem; + } + + @Override + public void execute(Location location, Repeater blockData, LoaderRepeater parent, int power, long ticks, Consumer delay) { + blockData.setDelay(3); + parent.update(blockData); + } + }, + + DELAY_4 { + @Override + public int getPos() { + return 7; + } + + @Override + public SWItem menu(Player player, LoaderRepeater parent, int power, long ticks) { + SWItem swItem = new SWItem(Material.REPEATER, BauSystem.MESSAGE.parse("LOADER_SETTING_REPEATER", player, 4)); + swItem.getItemStack().setAmount(4); + return swItem; + } + + @Override + public void execute(Location location, Repeater blockData, LoaderRepeater parent, int power, long ticks, Consumer delay) { + blockData.setDelay(4); + parent.update(blockData); + } } } @@ -148,7 +163,7 @@ public class LoaderRepeater extends LoaderInteractionElement { public LoaderTNT(Location location) { - this.location = location; + super(location, TNTSettingsEnum.PLACE, TNTSettingsEnum.NOOP, TNTSettingsEnum.values()); + } + + public enum TNTSettingsEnum implements LoaderSettingsEnum { + NOOP { + @Override + public int getPos() { + return 2; + } + + @Override + public SWItem menu(Player player, LoaderTNT parent, int power, long ticks) { + return new SWItem(Material.STRUCTURE_VOID, translateItemName("LOADER_BUTTON_TNT", "LOADER_INTERACTION_NOOP", player)); + } + + @Override + public void execute(Location location, BlockData blockData, LoaderTNT parent, int power, long ticks, Consumer delay) { + } + }, + + PLACE { + @Override + public int getPos() { + return 3; + } + + @Override + public SWItem menu(Player player, LoaderTNT parent, int power, long ticks) { + return new SWItem(Material.TNT, translateItemName("LOADER_BUTTON_TNT", "LOADER_INTERACTION_PLACE", player)); + } + + @Override + public void execute(Location location, BlockData blockData, LoaderTNT parent, int power, long ticks, Consumer delay) { + location.getBlock().setType(Material.TNT); + } + } } @Override @@ -54,10 +88,11 @@ public class LoaderTNT implements LoaderElement { return; } - block.setType(Material.TNT, true); + super.execute(delay); } @Override - public void click(Player player, Runnable backAction) { + public boolean checkBlockInWorld() { + return true; } } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/loader/elements/impl/LoaderTicks.java b/BauSystem_Main/src/de/steamwar/bausystem/features/loader/elements/impl/LoaderTicks.java index 2beafc06..32e65f61 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/loader/elements/impl/LoaderTicks.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/loader/elements/impl/LoaderTicks.java @@ -20,120 +20,87 @@ package de.steamwar.bausystem.features.loader.elements.impl; import de.steamwar.bausystem.BauSystem; -import de.steamwar.bausystem.features.loader.elements.ElementSettings; import de.steamwar.bausystem.features.loader.elements.LoaderInteractionElement; -import de.steamwar.inventory.SWInventory; +import de.steamwar.bausystem.features.loader.elements.LoaderSettingsEnum; import de.steamwar.inventory.SWItem; -import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.data.Powerable; import org.bukkit.entity.Player; -import java.util.Arrays; -import java.util.Collections; import java.util.function.Consumer; -public class LoaderTicks extends LoaderInteractionElement { +public class LoaderTicks extends LoaderInteractionElement { private String name; private Material material; private int ticks; public LoaderTicks(Location location, String name, Material material, int ticks) { - super(location); + super(location, TicksSettingsEnum.NO_WAIT_FOR, TicksSettingsEnum.NOOP, TicksSettingsEnum.values()); this.name = name; this.material = material; this.ticks = ticks; } - public class TicksSettings implements ElementSettings { + public enum TicksSettingsEnum implements LoaderSettingsEnum { - private boolean noop = false; - private boolean waitFor = false; - - @Override - public SWItem menu(Player player) { - return menu(player, noop, waitFor); - } - - private SWItem menu(Player player, boolean noop, boolean waitFor) { - SWItem swItem; - if (noop) { - swItem = new SWItem(Material.STRUCTURE_VOID, translateItemName(name, "LOADER_INTERACTION_NOOP", player)); - } else if (waitFor) { - swItem = new SWItem(material, translateItemName(name, "LOADER_INTERACTION_WAIT_FOR", player, ticks)); - } else { - swItem = new SWItem(material, translateItemName(name, "LOADER_INTERACTION_NO_WAIT_FOR", player, ticks)); - swItem.setEnchanted(true); - } - swItem.setLore(Arrays.asList(BauSystem.MESSAGE.parse("LOADER_GUI_CLICK_TO_EDIT", player))); - return swItem; - } - - @Override - public void execute(Consumer delay) { - if (location.getBlock().getType() != material) { - return; - } - if (noop) { - return; + NOOP { + @Override + public int getPos() { + return 2; } - Powerable powerable = (Powerable) location.getBlock().getBlockData(); - powerable.setPowered(true); - location.getBlock().setBlockData(powerable, true); - update(powerable); - - if (waitFor) { - delay.accept((long) ticks); - } - BauSystem.runTaskLater(BauSystem.getInstance(), () -> { - powerable.setPowered(false); - location.getBlock().setBlockData(powerable, true); - update(powerable); - }, ticks); - } - - @Override - public void click(Player player, Runnable backAction, Runnable deleteAction) { - SWInventory swInventory = new SWInventory(player, 18, BauSystem.MESSAGE.parse("LOADER_GUI_SETTINGS_TITLE", player)); - for (int i = 9; i < 18; i++) swInventory.setItem(i, new SWItem(Material.GRAY_STAINED_GLASS_PANE, "§7")); - swInventory.setItem(9, new SWItem(Material.ARROW, BauSystem.MESSAGE.parse("LOADER_GUI_SETTINGS_BACK", player)).getItemStack(), clickType -> backAction.run()); - swInventory.setItem(17, new SWItem(Material.BARRIER, BauSystem.MESSAGE.parse("LOADER_GUI_SETTINGS_DELETE", player)).getItemStack(), clickType -> deleteAction.run()); - - swInventory.setItem(2, item(player, true, false).getItemStack(), clickType -> { - noop = true; - click(player, backAction, deleteAction); - }); - if (ticks >= 0) { - swInventory.setItem(5, item(player, false, false).getItemStack(), clickType -> { - noop = false; - waitFor = false; - click(player, backAction, deleteAction); - }); - swInventory.setItem(6, item(player, false, true).getItemStack(), clickType -> { - noop = false; - waitFor = true; - click(player, backAction, deleteAction); - }); + @Override + public SWItem menu(Player player, LoaderTicks parent, int power, long ticks) { + return new SWItem(Material.STRUCTURE_VOID, translateItemName(parent.name, "LOADER_INTERACTION_NOOP", player)); } - swInventory.open(); - } - - private SWItem item(Player player, boolean noop, boolean waitFor) { - SWItem swItem = menu(player, noop, waitFor); - if (swItem.getItemStack().equals(menu(player, this.noop, this.waitFor).getItemStack())) { - swItem.setEnchanted(true); + @Override + public void execute(Location location, Powerable blockData, LoaderTicks parent, int power, long ticks, Consumer delay) { } - swItem.setLore(Collections.emptyList()); - return swItem; - } + }, - @Override - public void noop() { - noop = true; + NO_WAIT_FOR { + @Override + public int getPos() { + return 5; + } + + @Override + public SWItem menu(Player player, LoaderTicks parent, int power, long ticks) { + return new SWItem(parent.material, translateItemName(parent.name, "LOADER_INTERACTION_NO_WAIT_FOR", player, ticks)); + } + + @Override + public void execute(Location location, Powerable blockData, LoaderTicks parent, int power, long ticks, Consumer delay) { + Powerable powerable = (Powerable) location.getBlock().getBlockData(); + powerable.setPowered(true); + parent.update(powerable); + + BauSystem.runTaskLater(BauSystem.getInstance(), () -> { + powerable.setPowered(false); + parent.update(powerable); + }, parent.ticks); + } + }, + + WAIT_FOR { + @Override + public int getPos() { + return 6; + } + + @Override + public SWItem menu(Player player, LoaderTicks parent, int power, long ticks) { + return new SWItem(parent.material, translateItemName(parent.name, "LOADER_INTERACTION_WAIT_FOR", player, ticks)); + } + + @Override + public void execute(Location location, Powerable blockData, LoaderTicks parent, int power, long ticks, Consumer delay) { + NO_WAIT_FOR.execute(location, blockData, parent, power, ticks, delay); + delay.accept((long) parent.ticks); + } } } @@ -143,7 +110,7 @@ public class LoaderTicks extends LoaderInteractionElement. - */ - -package de.steamwar.bausystem.features.redstonetester; - -import de.steamwar.bausystem.BauSystem; -import de.steamwar.bausystem.Permission; -import de.steamwar.bausystem.linkage.specific.BauGuiItem; -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; - -@Linked -public class RedstoneTesterGuiItem extends BauGuiItem { - - public RedstoneTesterGuiItem() { - super(23); - } - - @Override - public ItemStack getItem(Player player) { - return new SWItem(Material.REPEATER, - BauSystem.MESSAGE.parse("RT_ITEM_NAME", player), - Arrays.asList(BauSystem.MESSAGE.parse("RT_ITEM_LORE_1", player), - BauSystem.MESSAGE.parse("RT_ITEM_LORE_2", player), - BauSystem.MESSAGE.parse("RT_ITEM_LORE_3", player)) - , false, null).getItemStack(); - } - - @Override - public boolean click(ClickType click, Player p) { - p.closeInventory(); - p.performCommand("redstonetester"); - return false; - } - - @Override - public Permission permission() { - return Permission.MEMBER; - } -} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/redstonetester/RedstonetesterCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/redstonetester/RedstonetesterCommand.java deleted file mode 100644 index 0e1c7b63..00000000 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/redstonetester/RedstonetesterCommand.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2021 SteamWar.de-Serverteam - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.steamwar.bausystem.features.redstonetester; - -import de.steamwar.bausystem.BauSystem; -import de.steamwar.bausystem.SWUtils; -import de.steamwar.command.SWCommand; -import de.steamwar.linkage.Linked; -import org.bukkit.entity.Player; - -@Linked -public class RedstonetesterCommand extends SWCommand { - - public RedstonetesterCommand() { - super("redstonetester", "rt"); - } - - @Register(description = "RT_HELP") - public void genericCommand(Player p) { - BauSystem.MESSAGE.send("RT_GIVEN", p); - SWUtils.giveItemToPlayer(p, RedstonetesterUtils.getWand(p)); - } -} \ No newline at end of file diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/redstonetester/RedstonetesterUtils.java b/BauSystem_Main/src/de/steamwar/bausystem/features/redstonetester/RedstonetesterUtils.java deleted file mode 100644 index a70b143b..00000000 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/redstonetester/RedstonetesterUtils.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2021 SteamWar.de-Serverteam - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.steamwar.bausystem.features.redstonetester; - -import de.steamwar.bausystem.BauSystem; -import de.steamwar.bausystem.features.tpslimit.TPSUtils; -import de.steamwar.bausystem.utils.ItemUtils; -import de.steamwar.inventory.SWItem; -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.UtilityClass; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.data.BlockData; -import org.bukkit.block.data.Powerable; -import org.bukkit.block.data.type.Piston; -import org.bukkit.block.data.type.RedstoneWire; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; - -@UtilityClass -public class RedstonetesterUtils { - - public static ItemStack getWand(Player player) { - ItemStack i = new SWItem(Material.BLAZE_ROD, - BauSystem.MESSAGE.parse("RT_ITEM_NAME", player), - Arrays.asList(BauSystem.MESSAGE.parse("RT_ITEM_LORE_1", player), - BauSystem.MESSAGE.parse("RT_ITEM_LORE_2", player), - BauSystem.MESSAGE.parse("RT_ITEM_LORE_3", player)), - false, null).getItemStack(); - ItemUtils.setItem(i, "redstonetester"); - return i; - } - - @Getter - private final Map playerMap = new HashMap<>(); - - public void sendLocation(Player player, String prefix, Location location) { - BauSystem.MESSAGE.send("RT_LOC", player, location.getBlockX(), location.getBlockY(), location.getBlockZ()); - } - - @SuppressWarnings("BooleanMethodIsAlwaysInverted") - public boolean validBlock(Player player, BlockData block) { - if (block instanceof Powerable) return true; - if (block instanceof Piston) return true; - if (block instanceof RedstoneWire) return true; - BauSystem.MESSAGE.send("RT_INVALID_LOC", player); - return false; - } - - @Getter - @Setter - public static class RedstoneTester { - - private final Player player; - private Location loc1 = null; - private Location loc2 = null; - - private long lastTick = 0; - private Long tick = null; - - public RedstoneTester(Player player) { - this.player = player; - } - - public void activate(Location location) { - if (loc1 == null || loc2 == null) { - tick = null; - return; - } - if (TPSUtils.currentRealTick.get() - lastTick > 100) { - tick = null; - } - if (loc1.equals(location)) { - lastTick = TPSUtils.currentRealTick.get(); - if (tick == null) { - tick = TPSUtils.currentRealTick.get(); - } - return; - } - if (tick != null && loc2.equals(location)) { - BauSystem.MESSAGE.send("RT_RESULT", player, (TPSUtils.currentRealTick.get() - tick), ((TPSUtils.currentRealTick.get() - tick) / 2.0)); - } - } - - } -} \ No newline at end of file diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/redstonetester/RestonetesterListener.java b/BauSystem_Main/src/de/steamwar/bausystem/features/redstonetester/RestonetesterListener.java deleted file mode 100644 index 2ab015b9..00000000 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/redstonetester/RestonetesterListener.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2021 SteamWar.de-Serverteam - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.steamwar.bausystem.features.redstonetester; - -import de.steamwar.bausystem.BauSystem; -import de.steamwar.bausystem.utils.ItemUtils; -import de.steamwar.linkage.Linked; -import org.bukkit.block.Block; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.block.BlockDispenseEvent; -import org.bukkit.event.block.BlockPistonExtendEvent; -import org.bukkit.event.block.BlockPistonRetractEvent; -import org.bukkit.event.block.BlockRedstoneEvent; -import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.event.player.PlayerQuitEvent; - -import java.util.Objects; - -@Linked -public class RestonetesterListener implements Listener { - - @EventHandler - public void onPlayerInteract(PlayerInteractEvent event) { - if (!ItemUtils.isItem(event.getItem(), "redstonetester")) return; - Player player = event.getPlayer(); - Block block = event.getClickedBlock(); - event.setCancelled(true); - - switch (event.getAction()) { - case RIGHT_CLICK_AIR: - if (player.isSneaking()) { - RedstonetesterUtils.getPlayerMap().remove(event.getPlayer()); - BauSystem.MESSAGE.send("RT_ACTIVATE", player); - } - break; - case LEFT_CLICK_BLOCK: - if (!RedstonetesterUtils.validBlock(event.getPlayer(), Objects.requireNonNull(block).getBlockData())) return; - RedstonetesterUtils.getPlayerMap().computeIfAbsent(event.getPlayer(), RedstonetesterUtils.RedstoneTester::new).setLoc1(block.getLocation()); - RedstonetesterUtils.sendLocation(event.getPlayer(), "POS1", block.getLocation()); - break; - case RIGHT_CLICK_BLOCK: - if (!RedstonetesterUtils.validBlock(event.getPlayer(), Objects.requireNonNull(block).getBlockData())) return; - RedstonetesterUtils.getPlayerMap().computeIfAbsent(event.getPlayer(), RedstonetesterUtils.RedstoneTester::new).setLoc2(block.getLocation()); - RedstonetesterUtils.sendLocation(event.getPlayer(), "POS2", block.getLocation()); - break; - default: - break; - } - } - - @EventHandler - public void onPlayerQuit(PlayerQuitEvent event) { - RedstonetesterUtils.getPlayerMap().remove(event.getPlayer()); - } - - @EventHandler - public void onPistonExtend(BlockPistonExtendEvent e) { - RedstonetesterUtils.getPlayerMap().forEach((player, redstoneTester) -> redstoneTester.activate(e.getBlock().getLocation())); - } - - @EventHandler - public void onPistonRetract(BlockPistonRetractEvent e) { - RedstonetesterUtils.getPlayerMap().forEach((player, redstoneTester) -> redstoneTester.activate(e.getBlock().getLocation())); - } - - @EventHandler - public void onRedstoneEvent(BlockRedstoneEvent e) { - RedstonetesterUtils.getPlayerMap().forEach((player, redstoneTester) -> redstoneTester.activate(e.getBlock().getLocation())); - } - - @EventHandler - public void onBlockDispense(BlockDispenseEvent e) { - RedstonetesterUtils.getPlayerMap().forEach((player, redstoneTester) -> redstoneTester.activate(e.getBlock().getLocation())); - } -} \ No newline at end of file diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/region/TNTCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/region/TNTCommand.java index f8d6fd40..af9f3837 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/region/TNTCommand.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/region/TNTCommand.java @@ -74,6 +74,9 @@ public class TNTCommand extends SWCommand { case ONLY_TB: requestedMessage = getTestblockEnableMessage(); break; + case ONLY_BUILD: + requestedMessage = getBuildEnableMessage(); + break; } tntToggle(region, tntMode, requestedMessage); } @@ -89,6 +92,7 @@ public class TNTCommand extends SWCommand { Map tntModeMap = new HashMap<>(tntModeMapReduced); tntModeMap.put("testblock", TNTMode.ONLY_TB); tntModeMap.put("tb", TNTMode.ONLY_TB); + tntModeMap.put("build", TNTMode.ONLY_BUILD); return new TypeMapper() { @Override @@ -125,6 +129,10 @@ public class TNTCommand extends SWCommand { return "REGION_TNT_TB"; } + private String getBuildEnableMessage() { + return "REGION_TNT_BUILD"; + } + private void tntToggle(Region region, TNTMode requestedMode, String requestedMessage) { if (requestedMode != null && region.hasType(RegionType.TESTBLOCK) && region.hasType(RegionType.BUILD)) { region.set(Flag.TNT, requestedMode); @@ -134,6 +142,7 @@ public class TNTCommand extends SWCommand { switch (region.getPlain(Flag.TNT, TNTMode.class)) { case ALLOW: case ONLY_TB: + case ONLY_BUILD: region.set(Flag.TNT, TNTMode.DENY); RegionUtils.actionBar(region, getDisableMessage()); break; diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/region/TNTListener.java b/BauSystem_Main/src/de/steamwar/bausystem/features/region/TNTListener.java index d65a8750..a8d34de5 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/region/TNTListener.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/region/TNTListener.java @@ -28,12 +28,8 @@ import de.steamwar.bausystem.region.utils.RegionExtensionType; import de.steamwar.bausystem.region.utils.RegionType; import de.steamwar.bausystem.utils.ScoreboardElement; import de.steamwar.linkage.Linked; -import de.steamwar.linkage.LinkedInstance; -import org.bukkit.Bukkit; -import org.bukkit.Location; import org.bukkit.block.Block; import org.bukkit.entity.Player; -import org.bukkit.event.Event; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; @@ -47,22 +43,29 @@ import java.util.concurrent.atomic.AtomicBoolean; public class TNTListener implements Listener, ScoreboardElement { private void explode(List blockList) { - AtomicBoolean inBuild = new AtomicBoolean(); blockList.removeIf(block -> { Region region = Region.getRegion(block.getLocation()); TNTMode value = region.getPlain(Flag.TNT); if (value == TNTMode.ALLOW) { return false; - } - if (region.hasType(RegionType.BUILD) && region.inRegion(block.getLocation(), RegionType.BUILD, RegionExtensionType.NORMAL)) { - RegionUtils.actionBar(region, "REGION_TNT_BUILD"); - inBuild.set(true); - return true; - } - if (region.hasType(RegionType.BUILD) && region.inRegion(block.getLocation(), RegionType.BUILD, RegionExtensionType.EXTENSION)) { - RegionUtils.actionBar(region, "REGION_TNT_BUILD"); - inBuild.set(true); - return true; + } else if (value == TNTMode.ONLY_TB) { + if (region.hasType(RegionType.BUILD) && region.inRegion(block.getLocation(), RegionType.BUILD, RegionExtensionType.NORMAL)) { + RegionUtils.actionBar(region, "REGION_TNT_BUILD_DESTROY"); + return true; + } + if (region.hasType(RegionType.BUILD) && region.inRegion(block.getLocation(), RegionType.BUILD, RegionExtensionType.EXTENSION)) { + RegionUtils.actionBar(region, "REGION_TNT_BUILD_DESTROY"); + return true; + } + } else if (value == TNTMode.ONLY_BUILD) { + if (region.hasType(RegionType.TESTBLOCK) && region.inRegion(block.getLocation(), RegionType.TESTBLOCK, RegionExtensionType.NORMAL)) { + RegionUtils.actionBar(region, "REGION_TNT_TB_DESTROY"); + return true; + } + if (region.hasType(RegionType.TESTBLOCK) && region.inRegion(block.getLocation(), RegionType.TESTBLOCK, RegionExtensionType.EXTENSION)) { + RegionUtils.actionBar(region, "REGION_TNT_TB_DESTROY"); + return true; + } } return value == TNTMode.DENY; }); diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/region/TestblockCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/region/TestblockCommand.java index 132e7cac..3572cf71 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/region/TestblockCommand.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/region/TestblockCommand.java @@ -159,7 +159,7 @@ public class TestblockCommand extends SWCommand { @ClassValidator(value = Player.class, local = true) public TypeValidator validator() { - return (commandSender, player, messageSender) -> !messageSender.send(!Permission.hasPermission(player, Permission.WORLD), "REGION_TB_NO_PERMS"); + return (commandSender, player, messageSender) -> !messageSender.send(!Permission.hasPermission(player, Permission.WORLDEDIT), "REGION_TB_NO_PERMS"); } private Region regionCheck(Player player) { @@ -192,44 +192,12 @@ public class TestblockCommand extends SWCommand { }; } - public static class TestblockParameter { - private boolean water = false; - private boolean tnt = false; - private boolean extension = false; - private boolean onlyColor = false; - - private boolean ignoreAir = false; - - public void enableWater() { - this.water = true; - } - - public void enableTNT() { - this.tnt = true; - } - - public void enableExtension() { - this.extension = true; - } - - public void enableOnlyColor() { - this.onlyColor = true; - } - - public void enableIgnoreAir() { - this.ignoreAir = true; - } - } - public enum TestblockParameterType { - EXTENSION(TestblockParameter::enableExtension, Arrays.asList("-e", "-extension")), - TNT(TestblockParameter::enableTNT, Arrays.asList("-t", "-tnt")), - WATER(TestblockParameter::enableWater, Arrays.asList("-w", "-water")), - IGNORE_AIR(TestblockParameter::enableIgnoreAir, Arrays.asList("-ig", "-ignore_air")), - ONLY_COLOR(TestblockParameter::enableOnlyColor, Arrays.asList("-o", "-color", "-only_color")); - - @Getter - private final Consumer testblockParameterConsumer; + EXTENSION(Arrays.asList("-e", "-extension")), + TNT(Arrays.asList("-t", "-tnt")), + WATER(Arrays.asList("-w", "-water")), + IGNORE_AIR(Arrays.asList("-ig", "-ignore_air")), + ONLY_COLOR(Arrays.asList("-o", "-color", "-only_color")); @Getter private List tabCompletes; @@ -238,8 +206,7 @@ public class TestblockCommand extends SWCommand { private final Supplier removed; private AtomicReference cached = new AtomicReference<>(); - TestblockParameterType(Consumer testblockParameterConsumer, List tabCompletes, String... removed) { - this.testblockParameterConsumer = testblockParameterConsumer; + TestblockParameterType(List tabCompletes, String... removed) { this.tabCompletes = tabCompletes; this.removed = () -> { if (cached.get() == null) { diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/region/items/TntBauGuiItem.java b/BauSystem_Main/src/de/steamwar/bausystem/features/region/items/TntBauGuiItem.java index f4626cce..673a9295 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/region/items/TntBauGuiItem.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/region/items/TntBauGuiItem.java @@ -25,6 +25,7 @@ import de.steamwar.bausystem.linkage.specific.BauGuiItem; import de.steamwar.bausystem.region.Region; import de.steamwar.bausystem.region.flags.Flag; import de.steamwar.bausystem.region.flags.flagvalues.TNTMode; +import de.steamwar.bausystem.region.utils.RegionType; import de.steamwar.inventory.SWInventory; import de.steamwar.inventory.SWItem; import de.steamwar.linkage.Linked; @@ -47,6 +48,8 @@ public class TntBauGuiItem extends BauGuiItem { return new SWItem(Material.MINECART, BauSystem.MESSAGE.parse("REGION_ITEM_TNT_OFF", player)).getItemStack(); case ONLY_TB: return new SWItem(Material.TNT_MINECART, BauSystem.MESSAGE.parse("REGION_ITEM_TNT_ONLY_TB", player)).getItemStack(); + case ONLY_BUILD: + return new SWItem(Material.OBSIDIAN, BauSystem.MESSAGE.parse("REGION_ITEM_TNT_ONLY_BUILD", player)).getItemStack(); default: return new SWItem(Material.TNT, BauSystem.MESSAGE.parse("REGION_ITEM_TNT_ON", player)).getItemStack(); } @@ -60,8 +63,10 @@ public class TntBauGuiItem extends BauGuiItem { updateTntMode(TNTMode.ALLOW, p); break; case ALLOW: - updateTntMode(TNTMode.ONLY_TB, p); - break; + if (Region.getRegion(p.getLocation()).hasType(RegionType.BUILD) && Region.getRegion(p.getLocation()).hasType(RegionType.TESTBLOCK)) { + updateTntMode(TNTMode.ONLY_TB, p); + break; + } default: updateTntMode(TNTMode.DENY, p); } @@ -72,11 +77,15 @@ public class TntBauGuiItem extends BauGuiItem { updateTntMode(TNTMode.ALLOW, p); p.closeInventory(); })); - if (!Region.getRegion(p.getLocation()).isGlobal()) { - selector.setItem(4, new SWItem(Material.TNT_MINECART, BauSystem.MESSAGE.parse("REGION_ITEM_SELECTOR_ONLY_TB", p), clickType -> { + if (Region.getRegion(p.getLocation()).hasType(RegionType.BUILD) && Region.getRegion(p.getLocation()).hasType(RegionType.TESTBLOCK)) { + selector.setItem(3, new SWItem(Material.TNT_MINECART, BauSystem.MESSAGE.parse("REGION_ITEM_SELECTOR_ONLY_TB", p), clickType -> { updateTntMode(TNTMode.ONLY_TB, p); p.closeInventory(); })); + selector.setItem(5, new SWItem(Material.OBSIDIAN, BauSystem.MESSAGE.parse("REGION_ITEM_SELECTOR_ONLY_BUILD", p), clickType -> { + updateTntMode(TNTMode.ONLY_BUILD, p); + p.closeInventory(); + })); } selector.setItem(7, new SWItem(Material.MINECART, BauSystem.MESSAGE.parse("REGION_ITEM_SELECTOR_OFF", p), clickType -> { updateTntMode(TNTMode.DENY, p); @@ -92,6 +101,9 @@ public class TntBauGuiItem extends BauGuiItem { case ONLY_TB: p.performCommand("tnt tb"); break; + case ONLY_BUILD: + p.performCommand("tnt build"); + break; case ALLOW: p.performCommand("tnt on"); break; diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/script/ScriptRunner.java b/BauSystem_Main/src/de/steamwar/bausystem/features/script/ScriptRunner.java index 85cc8586..7ee93eb3 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/script/ScriptRunner.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/script/ScriptRunner.java @@ -48,6 +48,10 @@ public class ScriptRunner { private static final Map>> HOTKEY_MAP = new HashMap<>(); private static final Map> COMMAND_MAP = new HashMap<>(); + public Set getCommandsOfPlayer(Player player) { + return COMMAND_MAP.getOrDefault(player, new HashMap<>()).keySet(); + } + public static void runScript(String script, Player player) { Globals globals = SteamWarPlatform.createClickGlobals(player); catchScript("SCRIPT_ERROR_CLICK", player, () -> globals.load(script).call()); diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/script/event/EventListener.java b/BauSystem_Main/src/de/steamwar/bausystem/features/script/event/EventListener.java index 3f0a60b6..89f9667e 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/script/event/EventListener.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/script/event/EventListener.java @@ -57,8 +57,9 @@ public class EventListener implements Listener { static { Bukkit.getScheduler().runTaskTimer(BauSystem.getInstance(), () -> { - LAST_FS.entrySet().removeIf(entry -> TPSUtils.currentTick.get() - entry.getValue() > 4); - }, 2, 2); + long millis = System.currentTimeMillis(); + LAST_FS.entrySet().removeIf(entry -> millis - entry.getValue() > 200); + }, 1, 1); } @EventHandler(priority = EventPriority.MONITOR) @@ -75,9 +76,11 @@ public class EventListener implements Listener { @EventHandler(priority = EventPriority.HIGH) public void onPlayerSwapHandItems(PlayerSwapHandItemsEvent event) { if (LAST_FS.containsKey(event.getPlayer())) { - ScriptRunner.callEvent(event.getPlayer(), SteamWarGlobalLuaPlugin.EventType.DoubleSwap, LuaValue.NIL, event); + Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> { + ScriptRunner.callEvent(event.getPlayer(), SteamWarGlobalLuaPlugin.EventType.DoubleSwap, LuaValue.NIL, event); + }, 1); } else { - LAST_FS.put(event.getPlayer(), TPSUtils.currentTick.get()); + LAST_FS.put(event.getPlayer(), System.currentTimeMillis()); } } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/script/lua/libs/BossbarLib.java b/BauSystem_Main/src/de/steamwar/bausystem/features/script/lua/libs/BossbarLib.java new file mode 100644 index 00000000..adbb334e --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/script/lua/libs/BossbarLib.java @@ -0,0 +1,130 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2023 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.features.script.lua.libs; + +import de.steamwar.linkage.Linked; +import org.bukkit.Bukkit; +import org.bukkit.boss.BarColor; +import org.bukkit.boss.BarFlag; +import org.bukkit.boss.BarStyle; +import org.bukkit.boss.BossBar; +import org.bukkit.entity.Player; +import org.luaj.vm2.LuaError; +import org.luaj.vm2.LuaTable; +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.lib.OneArgFunction; +import org.luaj.vm2.lib.ThreeArgFunction; +import org.luaj.vm2.lib.ZeroArgFunction; + +@Linked +public class BossbarLib implements LuaLib { + @Override + public String name() { + return "bossbar"; + } + + @Override + public LuaTable get(Player player) { + LuaTable table = new LuaTable(); + + table.set("create", new ThreeArgFunction() { + + @Override + public LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) { + String title = arg1.checkjstring(); + BarStyle style; + BarColor color; + try { + color = BarColor.valueOf(arg2.checkjstring()); + style = BarStyle.valueOf(arg3.checkjstring()); + } catch (IllegalArgumentException e) { + throw new LuaError("Invalid color or style"); + } + BossBar bossBar = Bukkit.createBossBar(title, color, style); + bossBar.addPlayer(player); + + LuaTable bbTable = new LuaTable(); + + bbTable.set("title", getterAndSetter("title", bossBar::getTitle, bossBar::setTitle)); + bbTable.set("style", getterAndSetter("style", () -> bossBar.getStyle().name(), s -> { + try { + bossBar.setStyle(BarStyle.valueOf(s)); + } catch (IllegalArgumentException e) { + throw new LuaError("Invalid style"); + } + })); + bbTable.set("color", getterAndSetter("color", () -> bossBar.getColor().name(), s -> { + try { + bossBar.setColor(BarColor.valueOf(s)); + } catch (IllegalArgumentException e) { + throw new LuaError("Invalid color"); + } + })); + bbTable.set("progress", getterAndSetter("progress", bossBar::getProgress, bossBar::setProgress)); + bbTable.set("visible", getterAndSetter("visible", bossBar::isVisible, bossBar::setVisible)); + bbTable.set("hasFlag", new OneArgFunction() { + @Override + public LuaValue call(LuaValue arg) { + try { + return LuaValue.valueOf(bossBar.hasFlag(BarFlag.valueOf(arg.checkjstring()))); + } catch (IllegalArgumentException e) { + throw new LuaError("Invalid flag"); + } + } + }); + + bbTable.set("addFlag", new OneArgFunction() { + @Override + public LuaValue call(LuaValue arg) { + try { + bossBar.addFlag(BarFlag.valueOf(arg.checkjstring())); + return LuaValue.TRUE; + } catch (IllegalArgumentException e) { + throw new LuaError("Invalid flag"); + } + } + }); + + bbTable.set("removeFlag", new OneArgFunction() { + @Override + public LuaValue call(LuaValue arg) { + try { + bossBar.removeFlag(BarFlag.valueOf(arg.checkjstring())); + return LuaValue.TRUE; + } catch (IllegalArgumentException e) { + throw new LuaError("Invalid flag"); + } + } + }); + bbTable.set("destroy", new ZeroArgFunction() { + @Override + public LuaValue call() { + bossBar.removeAll(); + return LuaValue.NIL; + } + }); + + return bbTable; + } + }); + + return table; + } +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/script/lua/libs/RegionLib.java b/BauSystem_Main/src/de/steamwar/bausystem/features/script/lua/libs/RegionLib.java index 0f3104cf..f6c35f9f 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/script/lua/libs/RegionLib.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/script/lua/libs/RegionLib.java @@ -23,6 +23,7 @@ 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; import de.steamwar.bausystem.region.flags.flagvalues.FireMode; @@ -49,12 +50,20 @@ public class RegionLib implements LuaLib { LuaTable table = LuaValue.tableOf(); table.set("name", getter(() -> region.get().getName())); - table.set("type", getter(() -> region.get().getPrototype().getName())); + table.set("type", getter(() -> { + Region region1 = region.get(); + if (region1 instanceof GlobalRegion) { + return "global"; + } else { + return region1.getPrototype().getName(); + } + })); LuaValue tntLib = LuaValue.tableOf(); tntLib.set("mode", getter(() -> region.get().getPlain(Flag.TNT, TNTMode.class).name())); tntLib.set("enabled", getter(() -> region.get().getPlain(Flag.TNT, TNTMode.class) != TNTMode.DENY)); tntLib.set("onlyTb", getter(() -> region.get().getPlain(Flag.TNT, TNTMode.class) == TNTMode.ONLY_TB)); + tntLib.set("onlyBuild", getter(() -> region.get().getPlain(Flag.TNT, TNTMode.class) == TNTMode.ONLY_BUILD)); table.set("tnt", tntLib); @@ -86,7 +95,7 @@ public class RegionLib implements LuaLib { } }); - table.set("list", getter(() -> LuaValue.listOf(Region.getREGION_MAP().values().stream().map(region -> create(() -> region, player)).toArray(LuaValue[]::new)))); + table.set("list", getter(() -> LuaValue.listOf(Region.getREGION_MAP().values().stream().map(region -> create(() -> region, player)).toArray(LuaTable[]::new)))); return table; } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/smartplace/SmartPlaceBehaviour.java b/BauSystem_Main/src/de/steamwar/bausystem/features/smartplace/SmartPlaceBehaviour.java deleted file mode 100644 index 19ca8d0d..00000000 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/smartplace/SmartPlaceBehaviour.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2021 SteamWar.de-Serverteam - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.steamwar.bausystem.features.smartplace; - -import org.bukkit.event.block.BlockPlaceEvent; -import org.bukkit.event.player.PlayerInteractEvent; - -public interface SmartPlaceBehaviour { - - enum SmartPlaceResult { - APPLIED, - IGNORED - } - - enum SmartPlaceType { - PLACE, - INTERACT_DIRECT, // Before checking if block is interacteable - INTERACT_INDIRECT, // After checking if block is interacteable - } - - SmartPlaceType getType(); - default SmartPlaceResult place(BlockPlaceEvent event) { - return SmartPlaceResult.IGNORED; - } - default SmartPlaceResult interact(PlayerInteractEvent event) { - return SmartPlaceResult.IGNORED; - } -} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/smartplace/SmartPlaceListener.java b/BauSystem_Main/src/de/steamwar/bausystem/features/smartplace/SmartPlaceListener.java index a5ac0456..75f60d53 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/smartplace/SmartPlaceListener.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/smartplace/SmartPlaceListener.java @@ -20,82 +20,84 @@ package de.steamwar.bausystem.features.smartplace; import de.steamwar.bausystem.configplayer.Config; -import de.steamwar.bausystem.linkage.LinkageUtils; +import de.steamwar.bausystem.utils.PlaceItemUtils; import de.steamwar.linkage.Linked; +import org.bukkit.Bukkit; import org.bukkit.GameMode; +import org.bukkit.Material; +import org.bukkit.SoundGroup; +import org.bukkit.block.Block; import org.bukkit.block.data.BlockData; -import org.bukkit.block.data.Directional; -import org.bukkit.block.data.Rotatable; +import org.bukkit.block.data.type.Repeater; +import org.bukkit.block.data.type.Sign; +import org.bukkit.block.data.type.Switch; import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.block.Action; -import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.player.PlayerInteractEvent; -import java.util.ArrayList; -import java.util.List; - @Linked public class SmartPlaceListener implements Listener { - private static List smartPlaceBehaviours = new ArrayList<>(); - - public static void add(SmartPlaceBehaviour smartPlaceBehaviour) { - smartPlaceBehaviours.add(smartPlaceBehaviour); - } - - @EventHandler - public void onBlockPlace(BlockPlaceEvent event) { - if (!Config.getInstance().get(event.getPlayer()).getPlainValueOrDefault("smartPlace", false)) return; - if (smartPlaceBehaviours.isEmpty()) LinkageUtils.linkSmartPlace(); - SmartPlaceBehaviour.SmartPlaceResult smartPlaceResult = SmartPlaceBehaviour.SmartPlaceResult.IGNORED; - for (SmartPlaceBehaviour smartPlaceBehaviour : smartPlaceBehaviours) { - if (smartPlaceBehaviour.getType() == SmartPlaceBehaviour.SmartPlaceType.PLACE) { - smartPlaceResult = smartPlaceBehaviour.place(event); - } - if (smartPlaceResult == SmartPlaceBehaviour.SmartPlaceResult.APPLIED) { - break; - } - } - } - - @EventHandler + @EventHandler(priority = EventPriority.HIGHEST) public void onPlayerInteract(PlayerInteractEvent event) { if (!Config.getInstance().get(event.getPlayer()).getPlainValueOrDefault("smartPlace", false)) return; - if (smartPlaceBehaviours.isEmpty()) LinkageUtils.linkSmartPlace(); if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return; if (event.getPlayer().getGameMode() == GameMode.SPECTATOR) return; - for (SmartPlaceBehaviour smartPlaceBehaviour : smartPlaceBehaviours) { - SmartPlaceBehaviour.SmartPlaceResult smartPlaceResult = SmartPlaceBehaviour.SmartPlaceResult.IGNORED; - if (smartPlaceBehaviour.getType() == SmartPlaceBehaviour.SmartPlaceType.INTERACT_DIRECT) { - smartPlaceResult = smartPlaceBehaviour.interact(event); - } - if (smartPlaceResult == SmartPlaceBehaviour.SmartPlaceResult.APPLIED) { + boolean shouldRotate = event.getPlayer().isSneaking(); + Material blockType = event.getClickedBlock().getType(); + switch (blockType) { + case REPEATER: + if (shouldRotate && (event.getItem() == null || event.getItem().getType() == Material.REPEATER)) { + Repeater repeater = (Repeater) event.getClickedBlock().getBlockData(); + int i = repeater.getDelay() - 1; + if (i <= 0) i += 4; + repeater.setDelay(i); + event.getClickedBlock().setBlockData(repeater); + event.setCancelled(true); + } + return; + } + BlockData blockData = event.getClickedBlock().getBlockData(); + if (blockData instanceof Switch) { + if (!shouldRotate && (event.getItem() == null || event.getItem().getType() == event.getClickedBlock().getType())) { return; } + shouldRotate = false; } - if (!event.getClickedBlock().getType().isInteractable()) return; - if (event.getItem() == null) return; - if (!event.getMaterial().isBlock()) return; - try { - BlockData blockData = event.getItem().getType().createBlockData(); - if (!(blockData instanceof Directional) && !(blockData instanceof Rotatable)) { - return; + PlaceItemUtils.PlaceItemResult result = PlaceItemUtils.placeItem(event.getPlayer(), event.getItem(), event.getClickedBlock(), event.getBlockFace(), event.getHand(), true, true, shouldRotate, false); + if (result.isSuccess()) { + event.setCancelled(true); + Block block = event.getClickedBlock().getRelative(event.getBlockFace()); + SoundGroup soundGroup = block.getBlockData().getSoundGroup(); + Bukkit.getOnlinePlayers().forEach(player -> { + if (!(event.getClickedBlock().getBlockData() instanceof Sign) && player == event.getPlayer()) { + return; + } + player.playSound(block.getLocation(), soundGroup.getPlaceSound(), soundGroup.getVolume() * 0.8F, soundGroup.getPitch() * 0.8F); + }); + if (result.wasForced()) { + event.getPlayer().playSound(block.getLocation(), soundGroup.getPlaceSound(), soundGroup.getVolume() * 0.8F, soundGroup.getPitch() * 0.8F); } - } catch (Exception e) { - return; } + // Fix Double sound for original player + } - for (SmartPlaceBehaviour smartPlaceBehaviour : smartPlaceBehaviours) { - SmartPlaceBehaviour.SmartPlaceResult smartPlaceResult = SmartPlaceBehaviour.SmartPlaceResult.IGNORED; - if (smartPlaceBehaviour.getType() == SmartPlaceBehaviour.SmartPlaceType.INTERACT_INDIRECT) { - smartPlaceResult = smartPlaceBehaviour.interact(event); - } - if (smartPlaceResult == SmartPlaceBehaviour.SmartPlaceResult.APPLIED) { - return; - } - } + @EventHandler + public void onBlockBreak(BlockBreakEvent event) { + if (!Config.getInstance().get(event.getPlayer()).getPlainValueOrDefault("smartPlace", false)) return; + if (!event.getPlayer().isSneaking()) return; + event.setCancelled(true); + event.getBlock().setType(Material.AIR, false); + + SoundGroup soundGroup = event.getBlock().getBlockData().getSoundGroup(); + Bukkit.getOnlinePlayers().forEach(player -> { + if (player == event.getPlayer()) return; + player.playSound(event.getBlock().getLocation(), soundGroup.getBreakSound(), soundGroup.getVolume() * 0.8F, soundGroup.getPitch() * 0.8F); + }); } } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/smartplace/behaviour/BlockPlaceBehaviour.java b/BauSystem_Main/src/de/steamwar/bausystem/features/smartplace/behaviour/BlockPlaceBehaviour.java deleted file mode 100644 index bfe5accd..00000000 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/smartplace/behaviour/BlockPlaceBehaviour.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2021 SteamWar.de-Serverteam - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.steamwar.bausystem.features.smartplace.behaviour; - -import de.steamwar.bausystem.features.smartplace.SmartPlaceBehaviour; -import de.steamwar.linkage.Linked; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.block.data.BlockData; -import org.bukkit.block.data.Directional; -import org.bukkit.block.data.Rotatable; -import org.bukkit.event.block.BlockPlaceEvent; - -@Linked -public class BlockPlaceBehaviour implements SmartPlaceBehaviour { - - @Override - public SmartPlaceType getType() { - return SmartPlaceType.PLACE; - } - - @Override - public SmartPlaceResult place(BlockPlaceEvent event) { - if (!event.getPlayer().isSneaking()) { - return SmartPlaceResult.IGNORED; - } - - SmartPlaceResult smartPlaceResult = SmartPlaceResult.IGNORED; - Block block = event.getBlockPlaced(); - BlockData blockData = block.getBlockData(); - if (blockData instanceof Directional) { - Directional directional = (Directional) blockData; - BlockFace blockFace = directional.getFacing().getOppositeFace(); - if (directional.getFaces().contains(blockFace)) { - directional.setFacing(blockFace); - } - smartPlaceResult = SmartPlaceResult.APPLIED; - } else if (blockData instanceof Rotatable) { - Rotatable rotatable = (Rotatable) blockData; - rotatable.setRotation(rotatable.getRotation().getOppositeFace()); - smartPlaceResult = SmartPlaceResult.APPLIED; - } - block.setBlockData(blockData); - return smartPlaceResult; - } -} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/smartplace/behaviour/BlockRotatingBehaviour.java b/BauSystem_Main/src/de/steamwar/bausystem/features/smartplace/behaviour/BlockRotatingBehaviour.java deleted file mode 100644 index fc266d0e..00000000 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/smartplace/behaviour/BlockRotatingBehaviour.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2021 SteamWar.de-Serverteam - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.steamwar.bausystem.features.smartplace.behaviour; - -import de.steamwar.bausystem.features.smartplace.SmartPlaceBehaviour; -import de.steamwar.linkage.Linked; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.block.data.BlockData; -import org.bukkit.block.data.Directional; -import org.bukkit.block.data.Rotatable; -import org.bukkit.event.Event; -import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.inventory.InventoryHolder; - -@Linked -public class BlockRotatingBehaviour implements SmartPlaceBehaviour { - - @Override - public SmartPlaceType getType() { - return SmartPlaceType.INTERACT_INDIRECT; - } - - @Override - public SmartPlaceResult interact(PlayerInteractEvent event) { - if (!(event.getClickedBlock().getState() instanceof InventoryHolder)) { - return SmartPlaceResult.IGNORED; - } - - BlockData blockData = event.getMaterial().createBlockData(); - if (!(blockData instanceof Directional) && !(blockData instanceof Rotatable)) { - return SmartPlaceResult.IGNORED; - } - - event.setUseInteractedBlock(Event.Result.DENY); - World world = event.getPlayer().getWorld(); - Block block = world.getBlockAt(event.getClickedBlock().getX() + event.getBlockFace().getModX(), event.getClickedBlock().getY() + event.getBlockFace().getModY(), event.getClickedBlock().getZ() + event.getBlockFace().getModZ()); - if (!block.getType().isAir()) { - return SmartPlaceResult.IGNORED; - } - block.setType(event.getMaterial()); - blockData = event.getItem().getType().createBlockData(); - BlockFace blockFace = event.getBlockFace(); - if ((blockFace == BlockFace.UP || blockFace == BlockFace.DOWN) && blockData instanceof Directional) { - blockFace = event.getPlayer().getFacing().getOppositeFace(); - } - if (block.getType() == Material.HOPPER || block.getType() == Material.OBSERVER) { - blockFace = blockFace.getOppositeFace(); - } - if (blockData instanceof Directional) { - Directional directional = (Directional) blockData; - if (directional.getFaces().contains(blockFace)) { - directional.setFacing(blockFace); - } - } else if (blockData instanceof Rotatable) { - try { - ((Rotatable) blockData).setRotation(blockFace); - } catch (Exception e) { - // Ignore - } - } - block.setBlockData(blockData); - return SmartPlaceResult.APPLIED; - } -} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/smartplace/behaviour/ReverseRepeaterBehaviour.java b/BauSystem_Main/src/de/steamwar/bausystem/features/smartplace/behaviour/ReverseRepeaterBehaviour.java deleted file mode 100644 index 13242417..00000000 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/smartplace/behaviour/ReverseRepeaterBehaviour.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2021 SteamWar.de-Serverteam - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.steamwar.bausystem.features.smartplace.behaviour; - -import de.steamwar.bausystem.features.smartplace.SmartPlaceBehaviour; -import de.steamwar.linkage.Linked; -import org.bukkit.Material; -import org.bukkit.block.data.type.Repeater; -import org.bukkit.event.player.PlayerInteractEvent; - -@Linked -public class ReverseRepeaterBehaviour implements SmartPlaceBehaviour { - - @Override - public SmartPlaceType getType() { - return SmartPlaceType.INTERACT_DIRECT; - } - - @Override - public SmartPlaceResult interact(PlayerInteractEvent event) { - if (event.getPlayer().isSneaking()) { - if (event.getClickedBlock().getType() == Material.REPEATER) { - if (event.getItem() != null && event.getMaterial() != Material.REPEATER) { - return SmartPlaceResult.APPLIED; - } - Repeater repeater = (Repeater) event.getClickedBlock().getBlockData(); - int i = repeater.getDelay() - 1; - if (i <= 0) i += 4; - repeater.setDelay(i); - event.getClickedBlock().setBlockData(repeater); - event.setCancelled(true); - } - return SmartPlaceResult.APPLIED; - } - return SmartPlaceResult.IGNORED; - } -} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/TNTPosition.java b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/TNTPosition.java index be47e4bc..1af2b710 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/TNTPosition.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/TNTPosition.java @@ -22,6 +22,7 @@ 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; @@ -30,16 +31,21 @@ 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; - public TNTPosition(Record.TNTRecord record, TNTPrimed entity, Vector previousLocation, Vector velocity, Vector updateVelocity, boolean source, 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; diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/TraceCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/TraceCommand.java index f18147f3..0ffe04de 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/TraceCommand.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/TraceCommand.java @@ -21,9 +21,7 @@ package de.steamwar.bausystem.features.tracer; import de.steamwar.bausystem.BauSystem; import de.steamwar.bausystem.Permission; -import de.steamwar.bausystem.features.tracer.gui.TraceGui; import de.steamwar.bausystem.features.tracer.record.*; -import de.steamwar.bausystem.features.tracer.show.Record; import de.steamwar.bausystem.features.tracer.show.*; import de.steamwar.bausystem.region.Region; import de.steamwar.bausystem.shared.ShowMode; @@ -91,11 +89,84 @@ public class TraceCommand extends SWCommand { } } + @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"}) + public void showAtCommand(@Validator Player p, @OptionalValue("time") @StaticValue({"time", "fuse"}) String type, @StaticValue("at") String __, @Min(intValue = 0) int at) { + showFromToCommand(p, type, __, at, __, at); + } + + @Register(value = {"show"}) + 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); + return; + } + showFromToCommand(p, type, __, from, __, Integer.MAX_VALUE); + } + + @Register(value = {"show"}) + 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) { + 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; + } + }); + } + + // /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) { - showModeParameterType.getShowModeParameterConsumer().accept(showModeParameter); + if (showModeParameterType == ShowModeParameterType.WATER && region.getWaterLevel() != 0) { + showModeParameter.disableWater(); + } else { + showModeParameterType.getShowModeParameterConsumer().accept(showModeParameter); + } } TraceShowManager.show(p, showModeType.showModeBiFunction.apply(p, showModeParameter)); BauSystem.MESSAGE.send("TRACE_MESSAGE_SHOW", p); @@ -104,9 +175,6 @@ public class TraceCommand extends SWCommand { @Register(value = {"hide"}, description = "TRACE_COMMAND_HELP_HIDE") public void hideCommand(@Validator Player p) { TraceShowManager.hide(p); - Region region = Region.getRegion(p.getLocation()); - StoredRecords.hideIsolated(region, p); - StoredRecords.removeReplayTime(region, p); BauSystem.MESSAGE.send("TRACE_MESSAGE_HIDE", p); } @@ -115,97 +183,9 @@ public class TraceCommand extends SWCommand { public void deleteCommand(@Validator Player p) { Region region = Region.getRegion(p.getLocation()); StoredRecords.clear(region); - StoredRecords.hideIsolated(region); - StoredRecords.removeReplayTime(region); BauSystem.MESSAGE.send("TRACE_MESSAGE_DELETE", p); } - @Register(value = {"gui"}, description = "TRACE_COMMAND_HELP_GUI") - public void guiCommand(@Validator Player p) { - TraceGui.openGui(p); - } - - @Register(value = "isolate", noTabComplete = true) - public void isolate(Player p, String s) { - try { - UUID uuid = UUID.fromString(s); - Record.TNTRecord tntRecord = StoredRecords.getRecord(uuid); - StoredRecords.toggleIsolate(p, tntRecord); - } catch (Exception e) { - // Ignore - } - } - - @Register(value = "replay", description = "TRACE_COMMAND_HELP_REPLAY") - public void replay(@Validator Player p, @OptionalValue("0") int replayTick) { - Region region = Region.getRegion(p.getLocation()); - if (replayTick < 0) replayTick = 0; - StoredRecords.setReplayTime(region, p, replayTick); - } - - @Register(value = {"replay", "disable"}, description = "TRACE_COMMAND_HELP_REPLAY_DISABLE") - public void replayDisable(@Validator Player p) { - Region region = Region.getRegion(p.getLocation()); - StoredRecords.removeReplayTime(region, p); - } - - @Register(value = {"replay", "next"}, description = "TRACE_COMMAND_HELP_REPLAY_NEXT") - public void replayNext(@Validator Player p, @OptionalValue("1") int step) { - Region region = Region.getRegion(p.getLocation()); - int replayTick = StoredRecords.getReplayTime(region, p); - StoredRecords.setReplayTime(region, p, replayTick + step); - } - - @Register(value = {"replay", "previous"}, description = "TRACE_COMMAND_HELP_REPLAY_PREVIOUS") - public void replayPrevious(@Validator Player p, @OptionalValue("1") int step) { - Region region = Region.getRegion(p.getLocation()); - int replayTick = StoredRecords.getReplayTime(region, p) - step; - if (replayTick < 0) replayTick = 0; - StoredRecords.setReplayTime(region, p, replayTick); - } - - @Register(value = {"replay", "loop"}, description = "TRACE_COMMAND_HELP_REPLAY_LOOP") - public void replayLoop(@Validator Player p, int start, int end, @OptionalValue("0") int speed) { - Region region = Region.getRegion(p.getLocation()); - - if (start < 0) start = 0; - if (end < 0) end = 0; - - int initial = StoredRecords.getReplayTime(region, p); - if (!(Math.min(start, end) < initial && Math.max(start, end) > initial)) { - initial = start; - } - int finalInitial = initial; - - int finalStart = start; - int finalEnd = end; - Supplier supplier = new Supplier() { - int temp = speed; - int current = finalInitial; - - @Override - public Integer get() { - if (temp-- > 0) { - return current; - } - temp = speed; - if (finalEnd > finalStart) { - current++; - if (current > finalEnd) { - current = finalStart; - } - } else { - current--; - if (current < finalEnd) { - current = finalStart; - } - } - return current; - } - }; - StoredRecords.setReplayLoop(region, p, supplier); - } - @AllArgsConstructor private enum ShowModeType { ENTITY((player, showModeParameter) -> new EntityShowMode(player, showModeParameter, 10)), diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/gui/TraceGui.java b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/gui/TraceGui.java deleted file mode 100644 index fc4500af..00000000 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/gui/TraceGui.java +++ /dev/null @@ -1,108 +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 . - */ - -package de.steamwar.bausystem.features.tracer.gui; - -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.features.tracer.show.TraceShowManager; -import de.steamwar.bausystem.region.Region; -import de.steamwar.inventory.SWItem; -import de.steamwar.inventory.SWListInv; -import lombok.experimental.UtilityClass; -import org.bukkit.Material; -import org.bukkit.entity.Player; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -@UtilityClass -public class TraceGui { - - public static void openGui(Player player) { - Region region = Region.getRegion(player.getLocation()); - List> recordList = new ArrayList<>(); - StoredRecords.getRecords(region).forEach(record -> { - if (record.getTnt().isEmpty()) { - return; - } - SWItem swItem = new SWItem(Material.TNT, BauSystem.MESSAGE.parse("TRACE_GUI_ITEM", player, record.size())); - recordList.add(new SWListInv.SWListEntry<>(swItem, record)); - }); - SWListInv recordSWListInv = new SWListInv<>(player, BauSystem.MESSAGE.parse("TRACE_GUI_TITLE", player), false, recordList, (clickType, record) -> { - openRecordGui(player, record); - }); - recordSWListInv.setItem(49, new SWItem(Material.BUCKET, BauSystem.MESSAGE.parse("TRACE_GUI_CLEAR", player), clickType -> { - StoredRecords.clear(region); - player.getOpenInventory().close(); - })); - recordSWListInv.open(); - } - - public static void openRecordGui(Player player, Record record) { - Region region = Region.getRegion(player.getLocation()); - List> recordList = new ArrayList<>(); - record.getTnt().forEach(tntRecord -> { - SWItem swItem = new SWItem(Material.TNT_MINECART, BauSystem.MESSAGE.parse("TRACE_GUI_RECORD_ITEM", player, tntRecord.getPositions().size()), new ArrayList<>(), StoredRecords.isIsolated(player, tntRecord), clickType -> { - }); - recordList.add(new SWListInv.SWListEntry<>(swItem, tntRecord)); - }); - SWListInv tntRecordSWListInv = new SWListInv<>(player, BauSystem.MESSAGE.parse("TRACE_GUI_TITLE", player), false, recordList, (clickType, tntRecord) -> { - if (clickType.isShiftClick()) { - StoredRecords.toggleIsolate(player, tntRecord); - openRecordGui(player, record); - } else { - openTntGui(player, record, tntRecord); - } - }); - tntRecordSWListInv.setItem(48, new SWItem(Material.BUCKET, BauSystem.MESSAGE.parse("TRACE_GUI_RECORD_CLEAR", player), clickType -> { - StoredRecords.remove(region, record); - TraceShowManager.reshow(region); - openGui(player); - })); - tntRecordSWListInv.setItem(50, new SWItem(Material.ARROW, BauSystem.MESSAGE.parse("TRACE_GUI_ITEM_BACK", player), clickType -> { - openGui(player); - })); - tntRecordSWListInv.open(); - } - - public static void openTntGui(Player player, Record record, Record.TNTRecord tntRecord) { - List> positionList = new ArrayList<>(); - tntRecord.getPositions().forEach(tntPosition -> { - SWItem swItem = new SWItem(Material.PAPER, BauSystem.MESSAGE.parse("TRACE_GUI_POSITION_ITEM", player)); - swItem.setLore(Arrays.asList( - BauSystem.MESSAGE.parse("TRACE_GUI_POSITION_X", player, tntPosition.getLocation().getX()), - BauSystem.MESSAGE.parse("TRACE_GUI_POSITION_Y", player, tntPosition.getLocation().getY()), - BauSystem.MESSAGE.parse("TRACE_GUI_POSITION_Z", player, tntPosition.getLocation().getZ()), - BauSystem.MESSAGE.parse("TRACE_GUI_POSITION_SOURCE", player, tntPosition.isSource()), - BauSystem.MESSAGE.parse("TRACE_GUI_POSITION_EXPLODED", player, tntPosition.isExploded()) - )); - positionList.add(new SWListInv.SWListEntry<>(swItem, tntPosition)); - }); - SWListInv tntPositionSWListInv = new SWListInv<>(player, BauSystem.MESSAGE.parse("TRACE_GUI_TITLE", player), false, positionList, (clickType, tntPosition) -> { - }); - tntPositionSWListInv.setItem(49, new SWItem(Material.ARROW, BauSystem.MESSAGE.parse("TRACE_GUI_ITEM_BACK", player), clickType -> { - openRecordGui(player, record); - })); - tntPositionSWListInv.open(); - } -} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/record/AutoTraceRecorder.java b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/record/AutoTraceRecorder.java index f0eeab8c..ab326abc 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/record/AutoTraceRecorder.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/record/AutoTraceRecorder.java @@ -22,6 +22,11 @@ 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; @@ -37,10 +42,17 @@ public abstract class AutoTraceRecorder implements TraceRecorder { private final Map recordMap = new HashMap<>(); private Record record; + + private Region region; private Supplier recordSupplier; + @Setter + @Getter + private TraceRecordAutoDeletion traceRecordAutoDeletion = TraceRecordAutoDeletion.NEVER; + private Record lastRecord; + private Record.TNTRecord getRecord(TNTPrimed tntPrimed) { - return recordMap.computeIfAbsent(tntPrimed, __ -> record.spawn(TPSUtils.currentRealTick.get() - startTime)); + return recordMap.computeIfAbsent(tntPrimed, __ -> record.spawn()); } protected abstract String getInactivityMessage(); @@ -58,6 +70,10 @@ public abstract class AutoTraceRecorder implements TraceRecorder { } 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(); @@ -65,7 +81,8 @@ public abstract class AutoTraceRecorder implements TraceRecorder { } @Override - public void recordSupplier(Supplier recordSupplier) { + public void init(Region region, Supplier recordSupplier) { + this.region = region; this.recordSupplier = recordSupplier; } @@ -93,13 +110,14 @@ public abstract class AutoTraceRecorder implements TraceRecorder { } @Override - public final void explode(TNTPrimed tntPrimed, boolean inBuildRegion) { + 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; @@ -111,6 +129,7 @@ public abstract class AutoTraceRecorder implements TraceRecorder { if (recording && lastExplosion > 80) { recording = false; recordMap.clear(); + lastRecord = record; record = null; stoppedRecording(); } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/record/Recorder.java b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/record/Recorder.java index 7dd12060..1bd04377 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/record/Recorder.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/record/Recorder.java @@ -26,7 +26,6 @@ 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.Bukkit; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.entity.TNTPrimed; @@ -65,7 +64,7 @@ public class Recorder implements Listener { } @Override - public void explode(TNTPrimed tntPrimed, boolean b) { + public void explode(TNTPrimed tntPrimed, boolean inBuildArea, boolean inTestblockRegion) { } @Override @@ -80,12 +79,6 @@ public class Recorder implements Listener { } private static final DisabledTracerRecorder DISABLED = new DisabledTracerRecorder(); - static Recorder instance; - - { - instance = this; - } - private Map regionTraceRecorderMap = new HashMap<>(); private Map tntTraceRecorderMap = new HashMap<>(); @@ -99,13 +92,13 @@ public class Recorder implements Listener { public void set(Region region, TraceRecorder traceRecorder) { regionTraceRecorderMap.put(region, traceRecorder); - traceRecorder.recordSupplier(() -> { + traceRecorder.init(region, () -> { Record record = new Record(region); StoredRecords.add(region, record); return record; }); - tntTraceRecorderMap.forEach((tntPrimed, region1) -> { - if (region1 == region) { + tntTraceRecorderMap.forEach((tntPrimed, rg) -> { + if (rg == region) { traceRecorder.spawn(tntPrimed); } }); @@ -155,7 +148,8 @@ public class Recorder implements Listener { 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)); - traceRecorder.explode((TNTPrimed) entity, inBuildRegion); + 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(); } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/record/SimpleTraceRecorder.java b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/record/SimpleTraceRecorder.java index 1077f59a..875d25b5 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/record/SimpleTraceRecorder.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/record/SimpleTraceRecorder.java @@ -22,6 +22,7 @@ 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; @@ -41,7 +42,7 @@ public class SimpleTraceRecorder implements TraceRecorder, ActiveTracer { } @Override - public void recordSupplier(Supplier recordSupplier) { + public void init(Region region, Supplier recordSupplier) { record = recordSupplier.get(); } @@ -51,7 +52,7 @@ public class SimpleTraceRecorder implements TraceRecorder, ActiveTracer { } private Record.TNTRecord getRecord(TNTPrimed tntPrimed) { - return recordMap.computeIfAbsent(tntPrimed, __ -> record.spawn(TPSUtils.currentRealTick.get() - startTime)); + return recordMap.computeIfAbsent(tntPrimed, __ -> record.spawn()); } @Override @@ -65,9 +66,10 @@ public class SimpleTraceRecorder implements TraceRecorder, ActiveTracer { } @Override - public void explode(TNTPrimed tntPrimed, boolean inBuildRegion) { + 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); } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/record/TraceRecordAutoDeletion.java b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/record/TraceRecordAutoDeletion.java new file mode 100644 index 00000000..a99eff0e --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/record/TraceRecordAutoDeletion.java @@ -0,0 +1,65 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2023 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.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); +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/record/TraceRecorder.java b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/record/TraceRecorder.java index bb2a1325..c667f4e0 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/record/TraceRecorder.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/record/TraceRecorder.java @@ -20,6 +20,7 @@ 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; @@ -28,13 +29,13 @@ import java.util.function.Supplier; public interface TraceRecorder { String scoreboard(Player player); - default void recordSupplier(Supplier recordSupplier) { + default void init(Region region, Supplier recordSupplier) { } default void postClear() { } void spawn(TNTPrimed tntPrimed); void tick(TNTPrimed tntPrimed); - void explode(TNTPrimed tntPrimed, boolean inBuildRegion); + void explode(TNTPrimed tntPrimed, boolean inBuildRegion, boolean inTestblockRegion); default void tick() { } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/show/EntityShowMode.java b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/show/EntityShowMode.java index 0828ce73..dfa05ac4 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/show/EntityShowMode.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/show/EntityShowMode.java @@ -84,15 +84,22 @@ public class EntityShowMode implements ShowMode { 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()) { + if (!showModeParameter.isSourceOnly() && !showModeParameter.isMicroMotionLocation() && !hideWater) { return; } } @@ -101,11 +108,22 @@ public class EntityShowMode implements ShowMode { if (position.isSource()) { generatePositions(position, false, false); } - return; + if (!showModeParameter.isMicroMotionLocation() && !hideWater) { + return; + } } - boolean exploded = position.getRecord().getPositions().stream().anyMatch(TNTPosition::isExploded); - if (!showModeParameter.isWater() && exploded && checkWater(position.getLocation())) { + 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) -> { @@ -201,12 +219,10 @@ public class EntityShowMode implements ShowMode { entity = createEntity(position, positionType); } count++; - if (showModeParameter.isTicks()) { + if (showModeParameter.isFuse()) { entity.setDisplayName(fuseTicks + ""); } else if (showModeParameter.isCount()) { entity.setDisplayName(new HashSet<>(records).size() + ""); - } else if (showModeParameter.isTicksSinceStart()) { - entity.setDisplayName((80 - fuseTicks) + tntPosition.getRecord().getOffset() + ""); } } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/show/Record.java b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/show/Record.java index 8314b640..fce2d789 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/show/Record.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/show/Record.java @@ -19,6 +19,7 @@ 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; @@ -38,6 +39,7 @@ public class Record { @Getter private final List tnt = new ArrayList<>(); private final Region region; + private final long startTicks = TPSUtils.currentTick.get(); public int size() { return tnt.size(); @@ -47,8 +49,8 @@ public class Record { tnt.forEach(tntRecord -> tntRecord.getPositions().forEach(traceShowMode::show)); } - public TNTRecord spawn(long offset) { - TNTRecord record = new TNTRecord(this, offset, region); + public TNTRecord spawn() { + TNTRecord record = new TNTRecord(this, region); tnt.add(record); return record; } @@ -57,18 +59,21 @@ public class Record { tnt.clear(); } - private void checkMicroMotion() { + private void checkMicroMotion(Vector explosionPosition) { for (TNTRecord tntRecord : tnt) { List 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 || velocity.getZ() != 0) && (Math.abs(velocity.getX()) < 0.001 || Math.abs(velocity.getZ()) < 0.001)) { + 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); } } } @@ -80,9 +85,6 @@ public class Record { private Record record; - @Getter - private final long offset; - @Getter private final Region region; @@ -93,12 +95,15 @@ public class Record { @Setter private boolean inBuildArea = false; + @Getter + @Setter + private boolean inTestblockArea = false; + @Getter private boolean hasMicroMotion = false; - public TNTRecord(Record record, long offset, Region region) { + public TNTRecord(Record record, Region region) { this.record = record; - this.offset = offset; this.region = region; } @@ -112,17 +117,17 @@ public class Record { public void explode(TNTPrimed tntPrimed) { add(tntPrimed, false, true); - record.checkMicroMotion(); + record.checkMicroMotion(tntPrimed.getLocation().toVector()); } private void add(TNTPrimed tntPrimed, boolean source, boolean exploded) { TNTPosition position; if (positions.isEmpty()) { - position = new TNTPosition(this, tntPrimed, null, tntPrimed.getVelocity(), null, source, exploded); + 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, positions.get(positions.size() - 1).getLocation(), tntPrimed.getVelocity(), lastVelocity, source, exploded); + 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); diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/show/ShowModeParameter.java b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/show/ShowModeParameter.java index 802c1eba..1da942eb 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/show/ShowModeParameter.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/show/ShowModeParameter.java @@ -28,15 +28,20 @@ public class ShowModeParameter { private boolean interpolateXZ = false; private boolean sourceOnly = false; private boolean explodeOnly = false; - private boolean ticks = false; + private boolean fuse = false; private boolean count = false; private boolean buildDestroyOnly = false; - private boolean ticksSinceStart = 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; @@ -54,8 +59,8 @@ public class ShowModeParameter { this.explodeOnly = true; } - public void enableTicks() { - this.ticks = true; + public void enableFuse() { + this.fuse = true; } public void enableCount() { @@ -66,11 +71,15 @@ public class ShowModeParameter { this.buildDestroyOnly = true; } - public void enableTicksSinceStart() { - this.ticksSinceStart = true; + public void enableTestblockDestroyOnly() { + this.testblockDestroyOnly = true; } public void enableMicroMotion() { this.microMotion = true; } + + public void enableMicroMotionLocation() { + this.microMotionLocation = true; + } } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/show/ShowModeParameterType.java b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/show/ShowModeParameterType.java index a4f83958..51e1e9a5 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/show/ShowModeParameterType.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/show/ShowModeParameterType.java @@ -36,13 +36,14 @@ public enum ShowModeParameterType { showModeParameter.enableInterpolateY(); showModeParameter.enableInterpolateXZ(); }, Arrays.asList("-advanced", "-a"), "INTERPOLATE_Y", "INTERPOLATE_XZ"), - SOURCE(ShowModeParameter::enableSourceOnly, Arrays.asList("-source", "-sourceonly", "-ignite"), "TICKS", "ADVANCED", "INTERPOLATE_Y", "INTERPOLATE_XZ", "WATER"), - EXPLODE(ShowModeParameter::enableExplodeOnly, Arrays.asList("-explode", "-explodeonly"), "TICKS", "ADVANCED", "INTERPOLATE_Y", "INTERPOLATE_XZ", "WATER"), - TICKS(ShowModeParameter::enableTicks, Arrays.asList("-ticks", "-t"), "EXPLODE", "SOURCE", "COUNT", "TICKS_SINCE_START"), - COUNT(ShowModeParameter::enableCount, Arrays.asList("-count", "-c"), "TICKS", "TICKS_SINCE_START"), - BUILD_DESTROY_ONLY(ShowModeParameter::enableBuildDestroyOnly, Arrays.asList("-builddestroy", "-builddestoryonly"), "WATER"), - TICKS_SINCE_START(ShowModeParameter::enableTicksSinceStart, Arrays.asList("-tickssincestart", "-tss"), "TICKS", "COUNT"), + 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 diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/show/StoredRecords.java b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/show/StoredRecords.java index 993e4fdd..91bc2272 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/show/StoredRecords.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/show/StoredRecords.java @@ -19,46 +19,21 @@ package de.steamwar.bausystem.features.tracer.show; -import de.steamwar.bausystem.BauSystem; 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 org.bukkit.Bukkit; -import org.bukkit.entity.Player; import java.util.*; import java.util.function.Predicate; -import java.util.function.Supplier; import java.util.stream.Collectors; @UtilityClass public class StoredRecords { - private static final Map>> isolatedTNT = new HashMap<>(); - private static final Map> replayTime = new HashMap<>(); - private static final Map>> replayLoops = new HashMap<>(); private static final Map> records = new HashMap<>(); - static { - BauSystem.runTaskTimer(BauSystem.getInstance(), () -> { - replayLoops.forEach((region, playerSupplierMap) -> { - playerSupplierMap.forEach((player, integerSupplier) -> { - int tick = integerSupplier.get(); - replayTime.computeIfAbsent(region, __ -> new HashMap<>()).put(player, tick); - TraceShowManager.reshow(region, player); - }); - }); - }, 1, 1); - } - - static void cleanup(Player player) { - isolatedTNT.forEach((region, playerListMap) -> playerListMap.remove(player)); - replayTime.forEach((region, playerIntegerMap) -> playerIntegerMap.remove(player)); - replayLoops.forEach((region, playerIntegerMap) -> playerIntegerMap.remove(player)); - } - public static void add(Region region, Record record) { records.computeIfAbsent(region, k -> new ArrayList<>()).add(record); } @@ -83,117 +58,13 @@ public class StoredRecords { return records.getOrDefault(region, Collections.emptyList()); } - public Record.TNTRecord getRecord(UUID id) { - return records.values().stream() - .flatMap(Collection::stream) - .map(Record::getTnt) - .flatMap(Collection::stream) - .filter(tntRecord -> tntRecord.getId().equals(id)) - .findFirst() - .orElse(null); - } - - public static boolean isIsolated(Player p, Record.TNTRecord tntRecord) { - return isolatedTNT.values() - .stream() - .filter(map -> map.containsKey(p)) - .anyMatch(map -> map.get(p).contains(tntRecord)); - } - - public static void toggleIsolate(Player p, Record.TNTRecord tntRecord) { - List tntRecords = isolatedTNT.computeIfAbsent(tntRecord.getRegion(), k -> new HashMap<>()) - .computeIfAbsent(p, k -> new ArrayList<>()); - if (tntRecords.contains(tntRecord)) { - tntRecords.remove(tntRecord); - if (tntRecords.isEmpty()) { - isolatedTNT.get(tntRecord.getRegion()).remove(p); - if (isolatedTNT.get(tntRecord.getRegion()).isEmpty()) { - isolatedTNT.remove(tntRecord.getRegion()); - } - } - } else { - tntRecords.add(tntRecord); - } - TraceShowManager.reshow(tntRecord.getRegion(), p); - } - - public static void hideIsolated(Region region) { - isolatedTNT.remove(region); - } - - public static void hideIsolated(Region region, Player player) { - Map> regionalIsolatedTNT = isolatedTNT.get(region); - if (regionalIsolatedTNT == null) { - return; - } - regionalIsolatedTNT.remove(player); - } - - public static int getReplayTime(Region region, Player player) { - return replayTime.computeIfAbsent(region, k -> new HashMap<>()).getOrDefault(player, -1); - } - - public static void removeReplayTime(Region region) { - replayTime.remove(region); - replayLoops.remove(region); - } - - public static void removeReplayTime(Region region, Player player) { - Map regionalReplayTime = replayTime.get(region); - if (regionalReplayTime != null) { - regionalReplayTime.remove(player); - } - Map> regionalReplayLoops = replayLoops.get(region); - if (regionalReplayLoops != null) { - regionalReplayLoops.remove(player); - } - } - - public static void setReplayTime(Region region, Player player, int time) { - if (time < 0) { - removeReplayTime(region, player); - return; - } - replayTime.computeIfAbsent(region, k -> new HashMap<>()).put(player, time); - TraceShowManager.reshow(region, player); - - Map> regionalReplayLoops = replayLoops.get(region); - if (regionalReplayLoops != null) { - regionalReplayLoops.remove(player); - } - } - - public static void setReplayLoop(Region region, Player player, Supplier loop) { - replayLoops.computeIfAbsent(region, k -> new HashMap<>()).put(player, loop); - } - - static Predicate replayTimeFilter(Region region, Player player) { - Predicate replayTimeFilter = tntPosition -> true; - if (replayTime.containsKey(region) && replayTime.get(region).containsKey(player)) { - int time = replayTime.get(region).get(player); - replayTimeFilter = tntPosition -> (80 - tntPosition.getFuseTicks()) + tntPosition.getRecord().getOffset() == time; - } - return replayTimeFilter; - } - - static void show(Region region, Player player, ShowMode traceShowMode) { - Predicate replayTimeFilter = replayTimeFilter(region, player); - if (isolatedTNT.containsKey(region) && isolatedTNT.get(region).containsKey(player)) { - isolatedTNT.get(region).get(player).forEach(record -> { - record.getPositions() - .stream() - .filter(replayTimeFilter) + static void show(Region region, Predicate traceShowFilter, ShowMode traceShowMode) { + records.getOrDefault(region, new ArrayList<>()).forEach(record -> { + record.getTnt().forEach(tntRecord -> { + tntRecord.getPositions().stream() + .filter(traceShowFilter) .forEach(traceShowMode::show); }); - } else { - records.getOrDefault(region, new ArrayList<>()).forEach(record -> { - record.getTnt().forEach(tntRecord -> { - tntRecord.getPositions() - .stream() - .filter(replayTimeFilter) - .forEach(traceShowMode::show); - }); - }); - } + }); } } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/show/TraceShowManager.java b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/show/TraceShowManager.java index 5cebaa1c..e3745391 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/show/TraceShowManager.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/show/TraceShowManager.java @@ -23,17 +23,13 @@ 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.entity.REntity; import org.bukkit.Bukkit; -import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerQuitEvent; -import java.util.Collections; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.function.Predicate; @@ -42,40 +38,36 @@ public class TraceShowManager implements Listener { } private static final Map>> showModes = new HashMap<>(); + private static final Map>> showFilters = new HashMap<>(); public static void show(Player player, ShowMode traceShowMode) { - hide(player); - Region region = Region.getRegion(player.getLocation()); + _hide(region, player, true); + Map> regionalShowModes = showModes.computeIfAbsent(region, __ -> new HashMap<>()); regionalShowModes.put(player, traceShowMode); - StoredRecords.show(region, player, traceShowMode); + StoredRecords.show(region, getShowFilter(player, region), traceShowMode); } public static void hide(Player player) { Region region = Region.getRegion(player.getLocation()); - Map> regionalShowModes = showModes.get(region); - if (regionalShowModes == null) { - return; - } - ShowMode showMode = regionalShowModes.remove(player); - if (showMode == null) { - return; - } - showMode.hide(); + _hide(region, player, true); + + showFilters.getOrDefault(region, new HashMap<>()).remove(player); } - public static void reshow(Region region, Player p) { - Map> regionalShowModes = showModes.get(region); - if (regionalShowModes == null) { - return; + public static void setShowFilter(Player player, Predicate showFilter) { + Region region = Region.getRegion(player.getLocation()); + Map> regionShowFilters = showFilters.computeIfAbsent(region, __ -> new HashMap<>()); + if (showFilter == null) { + regionShowFilters.remove(player); + } else { + regionShowFilters.put(player, showFilter); } - ShowMode showMode = regionalShowModes.get(p); - if (showMode == null) { - return; - } - showMode.hide(); - StoredRecords.show(region, p, showMode); + + _hide(region, player, false); + ShowMode showMode = showModes.computeIfAbsent(region, __ -> new HashMap<>()).computeIfAbsent(player, __ -> new EntityShowMode(player, new ShowModeParameter(), 10)); + StoredRecords.show(region, getShowFilter(player, region), showMode); } public static void reshow(Region region) { @@ -85,10 +77,31 @@ public class TraceShowManager implements Listener { } for (Map.Entry> entry : regionalShowModes.entrySet()) { entry.getValue().hide(); - StoredRecords.show(region, entry.getKey(), entry.getValue()); + StoredRecords.show(region, getShowFilter(entry.getKey(), region), entry.getValue()); } } + private static void _hide(Region region, Player player, boolean remove) { + Map> regionalShowModes = showModes.get(region); + if (regionalShowModes == null) { + return; + } + ShowMode showMode; + if (remove) { + showMode = regionalShowModes.remove(player); + } else { + showMode = regionalShowModes.get(player); + } + if (showMode == null) { + return; + } + showMode.hide(); + } + + private static Predicate 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> regionalShowModes = showModes.get(region); @@ -96,8 +109,9 @@ public class TraceShowManager implements Listener { return; } regionalShowModes.forEach((player, tntPositionShowMode) -> { - Predicate replayTimeFilter = StoredRecords.replayTimeFilter(region, player); - if (replayTimeFilter.test(tnt)) tntPositionShowMode.show(tnt); + if (getShowFilter(player, region).test(tnt)) { + tntPositionShowMode.show(tnt); + } }); } @@ -121,6 +135,8 @@ public class TraceShowManager implements Listener { ShowMode showMode = playerShowModeMap.remove(event.getPlayer()); if (showMode != null) showMode.hide(); }); - StoredRecords.cleanup(event.getPlayer()); + showFilters.forEach((region, playerPredicateMap) -> { + playerPredicateMap.remove(event.getPlayer()); + }); } } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/util/BindCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/util/BindCommand.java new file mode 100644 index 00000000..ab213c83 --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/util/BindCommand.java @@ -0,0 +1,147 @@ +package de.steamwar.bausystem.features.util; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.SWUtils; +import de.steamwar.bausystem.features.script.ScriptCommand; +import de.steamwar.bausystem.features.script.ScriptRunner; +import de.steamwar.command.PreviousArguments; +import de.steamwar.command.SWCommand; +import de.steamwar.command.TypeMapper; +import de.steamwar.linkage.Linked; +import org.bukkit.Bukkit; +import org.bukkit.NamespacedKey; +import org.bukkit.command.CommandMap; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerCommandPreprocessEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.persistence.PersistentDataType; + +import java.lang.reflect.Field; +import java.util.*; +import java.util.stream.Collectors; + +@Linked +public class BindCommand extends SWCommand implements Listener { + + @Linked + public static class UnBindCommand extends SWCommand { + + public UnBindCommand() { + super("unbind"); + } + + @Register + public void generic(Player player) { + bindInternal(player); + } + } + + private static final CommandMap commandMap; + + static { + Field knownCommandsField; + try { + knownCommandsField = Bukkit.getServer().getClass().getDeclaredField("commandMap"); + knownCommandsField.setAccessible(true); + commandMap = (CommandMap)knownCommandsField.get(Bukkit.getServer()); + } catch (IllegalAccessException | NoSuchFieldException var2) { + Bukkit.shutdown(); + throw new SecurityException("Oh shit. Commands cannot be registered.", var2); + } + } + + private static final NamespacedKey KEY = SWUtils.getNamespaceKey("command"); + + public BindCommand() { + super("bind"); + } + + @Register(description = "OTHER_BIND_HELP") + public void bind(Player player, @Mapper("command") @ErrorMessage("OTHER_BIND_ERROR") String... command) { + bindInternal(player, command); + } + + private static void bindInternal(Player player, String... command) { + ItemStack item = player.getInventory().getItemInMainHand(); + ItemMeta meta = item.getItemMeta(); + if (meta == null) { + BauSystem.MESSAGE.send("OTHER_BIND_UNBINDABLE", player); + return; + } + + if (command.length != 0) { + String commandText = String.join(" ", command); + meta.getPersistentDataContainer().set(KEY, PersistentDataType.STRING, commandText); + meta.setDisplayName(BauSystem.MESSAGE.parse("OTHER_BIND_LORE", player, commandText)); + BauSystem.MESSAGE.send("OTHER_BIND_MESSAGE_BIND", player, commandText); + } else { + meta.getPersistentDataContainer().remove(KEY); + meta.setDisplayName(null); + BauSystem.MESSAGE.send("OTHER_BIND_MESSAGE_UNBIND", player); + } + item.setItemMeta(meta); + player.getInventory().setItemInMainHand(item); + } + + @EventHandler + public void onPlayerInteract(PlayerInteractEvent event) { + if (!event.hasItem()) return; + ItemStack itemStack = event.getItem(); + ItemMeta meta = itemStack.getItemMeta(); + if (meta == null) { + return; + } + + String command = meta.getPersistentDataContainer().get(KEY, PersistentDataType.STRING); + if (command == null) { + return; + } + + event.setCancelled(true); + Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> { + PlayerCommandPreprocessEvent playerCommandPreprocessEvent = new PlayerCommandPreprocessEvent(event.getPlayer(), "/" + command); + Bukkit.getPluginManager().callEvent(playerCommandPreprocessEvent); + if (playerCommandPreprocessEvent.isCancelled()) return; + Bukkit.getServer().dispatchCommand(event.getPlayer(), command); + }, 1); + } + + @Mapper(value = "command", local = true) + public TypeMapper getCommandMapper() { + return new TypeMapper() { + @Override + public String map(CommandSender sender, PreviousArguments previousArguments, String s) { + return s; + } + + @Override + public Collection tabCompletes(CommandSender sender, PreviousArguments previousArguments, String s) { + if (previousArguments.mappedArgs.length == 0) return null; + Object[] args = (Object[]) previousArguments.mappedArgs[previousArguments.mappedArgs.length - 1]; + List tabCompletes; + if (args.length == 0) { + tabCompletes = commandMap.tabComplete(sender, ""); + } else { + tabCompletes = commandMap.tabComplete(sender, Arrays.stream(args).map(Objects::toString).collect(Collectors.joining(" ")) + " "); + } + if (tabCompletes == null) return null; + if (args.length == 0) { + tabCompletes = tabCompletes.stream() + .map(t -> t.substring(1)) + .filter(t -> !t.equals("bind")) + .collect(Collectors.toList()); + tabCompletes.addAll(ScriptRunner.getCommandsOfPlayer((Player) sender)); + return tabCompletes.stream() + .filter(t -> !t.contains(":")) + .collect(Collectors.toList()); + } + return tabCompletes; + } + }; + } +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/util/MaterialCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/util/MaterialCommand.java index e7efd6dd..6f7a92c7 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/util/MaterialCommand.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/util/MaterialCommand.java @@ -20,6 +20,7 @@ package de.steamwar.bausystem.features.util; import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.SWUtils; import de.steamwar.bausystem.shared.EnumDisplay; import de.steamwar.command.PreviousArguments; import de.steamwar.command.SWCommand; @@ -39,6 +40,7 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.inventory.ItemStack; import java.util.*; import java.util.function.BiConsumer; @@ -185,6 +187,9 @@ public class MaterialCommand extends SWCommand implements Listener { } }); SWListInv materialSWListInv = new SWListInv<>(p, BauSystem.MESSAGE.parse("MATERIAL_INV_NAME", p, swListEntries.size(), MaterialLazyInit.materialData.size()), false, swListEntries, (clickType, material) -> { + if (material.isItem()) { + SWUtils.giveItemToPlayer(p, new ItemStack(material, 1)); + } }); materialSWListInv.setItem(49, new SWItem(Material.NAME_TAG, BauSystem.MESSAGE.parse("MATERIAL_SEARCH", p), clickType -> { searchGUI(p); diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/util/PistonCalculator.java b/BauSystem_Main/src/de/steamwar/bausystem/features/util/PistonCalculator.java index 281b159f..15f0a005 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/util/PistonCalculator.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/util/PistonCalculator.java @@ -20,11 +20,15 @@ package de.steamwar.bausystem.features.util; import de.steamwar.bausystem.BauSystem; +import de.steamwar.entity.REntityServer; +import de.steamwar.entity.RFallingBlockEntity; import de.steamwar.linkage.Linked; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.ToString; import net.md_5.bungee.api.ChatMessageType; +import org.bukkit.Bukkit; +import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; @@ -37,10 +41,7 @@ import org.bukkit.event.Listener; import org.bukkit.event.block.Action; import org.bukkit.event.player.PlayerInteractEvent; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; +import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; @Linked @@ -59,6 +60,7 @@ public class PistonCalculator implements Listener { boolean pulling = blockType == Material.STICKY_PISTON && (clickedBlock.getRelative(piston.getFacing()).getType() == Material.AIR || piston.isExtended()); CalculationResult result = calc(clickedBlock, piston.getFacing(), (pulling ? piston.getFacing().getOppositeFace() : piston.getFacing())); + result.entityServer.addPlayer(event.getPlayer()); BauSystem.MESSAGE.sendPrefixless("PISTON_INFO", event.getPlayer(), ChatMessageType.ACTION_BAR, result.unmovable ? "§c" : (result.tooMany ? "§e" : "§a"), result.amount); } @@ -66,7 +68,7 @@ public class PistonCalculator implements Listener { private CalculationResult calc(Block origin, BlockFace facing, BlockFace direction) { Set blockSet = new HashSet<>(); - AtomicBoolean unmovable = new AtomicBoolean(); + Set unmovable = new HashSet<>(); Block calcOrigin = origin; if (facing != direction) calcOrigin = origin.getRelative(facing, 3); @@ -95,21 +97,30 @@ public class PistonCalculator implements Listener { blockSet.remove(origin); if (facing != direction) blockSet.remove(origin.getRelative(facing, 1)); - return new CalculationResult(blockSet.size(), blockSet.size() > 12, unmovable.get()); + + REntityServer entityServer = new REntityServer(); + for (Location loc : unmovable) { + RFallingBlockEntity rFallingBlockEntity = new RFallingBlockEntity(entityServer, loc.clone().add(0.5, 0, 0.5), Material.RED_STAINED_GLASS); + rFallingBlockEntity.setGlowing(true); + rFallingBlockEntity.setNoGravity(true); + rFallingBlockEntity.setInvisible(true); + } + Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), entityServer::close, 20); + return new CalculationResult(blockSet.size(), blockSet.size() > 12, !unmovable.isEmpty(), entityServer); } - private void calcDirection(Block origin, Block blockOrigin, Block calcOrigin, Block ignore, BlockFace facing, BlockFace direction, Set blockSet, List toCalc, AtomicBoolean unmovable) { - for (int i = 1; i < 13; i++) { + private void calcDirection(Block origin, Block blockOrigin, Block calcOrigin, Block ignore, BlockFace facing, BlockFace direction, Set blockSet, List toCalc, Set unmovable) { + for (int i = 1; i < 24; i++) { Block block = calcOrigin.getRelative(direction, i); if (block.equals(ignore)) return; if (block.getPistonMoveReaction() == PistonMoveReaction.BREAK) return; if (!isPiston(block) && (block.getPistonMoveReaction() == PistonMoveReaction.BLOCK || block.getPistonMoveReaction() == PistonMoveReaction.IGNORE || block.getState() instanceof TileState)) { - unmovable.set(true); + unmovable.add(block.getLocation()); return; } if (block.getType().isAir()) return; if (facing == direction && block.equals(blockOrigin)) { - unmovable.set(true); + unmovable.add(block.getLocation()); return; } if (facing != direction && (block.equals(origin) || block.getRelative(facing.getOppositeFace()).equals(origin))) return; @@ -127,10 +138,10 @@ public class PistonCalculator implements Listener { @AllArgsConstructor @Getter - @ToString private static class CalculationResult { private int amount; private boolean tooMany; private boolean unmovable; + private REntityServer entityServer; } } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/world/SignEditFrom20.java b/BauSystem_Main/src/de/steamwar/bausystem/features/world/SignEditFrom20.java new file mode 100644 index 00000000..7956a3ef --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/world/SignEditFrom20.java @@ -0,0 +1,136 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2023 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.features.world; + +import com.comphenix.tinyprotocol.Reflection; +import com.comphenix.tinyprotocol.TinyProtocol; +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.utils.PlaceItemUtils; +import de.steamwar.linkage.Linked; +import de.steamwar.linkage.MinVersion; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.Sign; +import org.bukkit.block.data.BlockData; +import org.bukkit.block.data.Directional; +import org.bukkit.block.data.Rotatable; +import org.bukkit.block.sign.Side; +import org.bukkit.block.sign.SignSide; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.util.Vector; + +@Linked +@MinVersion(20) +public class SignEditFrom20 implements Listener { + + private static final Class blockPosition = Reflection.getClass("{nms.core}.BlockPosition"); + private static final Class craftBlock = Reflection.getClass("{obc}.block.CraftBlock"); + private static final Class craftWorld = Reflection.getClass("{obc}.CraftWorld"); + private static final Class generatorAccess = Reflection.getClass("{nms.world.level}.GeneratorAccess"); + private static final Reflection.MethodInvoker getPosition = Reflection.getTypedMethod(craftBlock, "getPosition", blockPosition); + private static final Reflection.MethodInvoker getWorldHandle = Reflection.getTypedMethod(craftWorld, "getHandle", null); + private static final Reflection.MethodInvoker at = Reflection.getTypedMethod(craftBlock, "at", craftBlock, generatorAccess, blockPosition); + + private static final Class openSign = Reflection.getClass("{nms.network.protocol.game}.PacketPlayOutOpenSignEditor"); + private static final Reflection.FieldAccessor blockPositionFieldAccessor = Reflection.getField(openSign, blockPosition, 0); + private static final Reflection.FieldAccessor sideFieldAccessor = Reflection.getField(openSign, boolean.class, 0); + + private static final Class updateSign = Reflection.getClass("{nms.network.protocol.game}.PacketPlayInUpdateSign"); + private static final Reflection.FieldAccessor getBlockPositionFieldAccessor = Reflection.getField(updateSign, blockPosition, 0); + private static final Reflection.FieldAccessor stringFieldAccessor = Reflection.getField(updateSign, String[].class, 0); + + @EventHandler + public void editSign(PlayerInteractEvent event) { + if (event.getClickedBlock() == null || !event.getClickedBlock().getType().name().contains("SIGN")) return; + if (event.getAction() == Action.RIGHT_CLICK_BLOCK && !event.getPlayer().isSneaking()) { + PlaceItemUtils.placeItem(event.getPlayer(), event.getItem(), event.getClickedBlock(), event.getBlockFace(), event.getHand(), false, true, false, true); + event.setCancelled(true); + } + if (!event.getPlayer().isSneaking()) return; + + if (event.getAction() == Action.RIGHT_CLICK_BLOCK && (event.getItem() == null || event.getItem().getType() == Material.AIR) || event.getAction() == Action.LEFT_CLICK_BLOCK) { + event.setCancelled(true); + Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> { + edit(event.getPlayer(), event.getClickedBlock()); + }, 1); + } + } + + private void edit(Player player, Block block) { + Sign sign = (Sign) block.getState(); + Side side = signSide(player, block); + SignSide signSide = sign.getSide(side); + String[] lines = signSide.getLines(); + for (int i = 0; i < lines.length; i++) { + signSide.setLine(i, lines[i].replace('§', '&')); + } + sign.update(true); + + Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> { + Object openSignObject = Reflection.newInstance(openSign); + blockPositionFieldAccessor.set(openSignObject, getPosition.invoke(block)); + sideFieldAccessor.set(openSignObject, side == Side.FRONT); + TinyProtocol.instance.sendPacket(player, openSignObject); + }, 1); + + } + + private Side signSide(Player entity, Block sign) { + Vector vector = entity.getEyeLocation().toVector().subtract(sign.getLocation().add(0.5, 0.5, 0.5).toVector()); + BlockData blockData = sign.getBlockData(); + + BlockFace blockFace = BlockFace.NORTH; + if (blockData instanceof Directional) { + blockFace = ((Directional) blockData).getFacing(); + } else if (blockData instanceof Rotatable) { + blockFace = ((Rotatable) blockData).getRotation(); + } + + Vector signDirection = new Vector(blockFace.getModX(), blockFace.getModY(), blockFace.getModZ()); + return vector.dot(signDirection) > 0 ? Side.FRONT : Side.BACK; + } + + { + TinyProtocol.instance.addFilter(updateSign, (player, o) -> { + Bukkit.getScheduler().runTask(BauSystem.getInstance(), () -> { + String[] lines = stringFieldAccessor.get(o); + + Block signLoc = (Block) at.invoke(null, getWorldHandle.invoke(player.getWorld()), getBlockPositionFieldAccessor.get(o)); + if (!signLoc.getType().name().contains("SIGN")) + return; + + Sign sign = ((Sign) signLoc.getState()); + SignSide signSide = sign.getSide(signSide(player, signLoc)); + for (int i = 0; i < lines.length; i++) { + signSide.setLine(i, ChatColor.translateAlternateColorCodes('&', lines[i])); + } + sign.update(true); + }); + return o; + }); + } +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/world/SignEdit.java b/BauSystem_Main/src/de/steamwar/bausystem/features/world/SignEditUntil19.java similarity index 97% rename from BauSystem_Main/src/de/steamwar/bausystem/features/world/SignEdit.java rename to BauSystem_Main/src/de/steamwar/bausystem/features/world/SignEditUntil19.java index 2f8e154e..19184032 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/world/SignEdit.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/world/SignEditUntil19.java @@ -23,6 +23,7 @@ import com.comphenix.tinyprotocol.Reflection; import com.comphenix.tinyprotocol.TinyProtocol; import de.steamwar.bausystem.BauSystem; import de.steamwar.linkage.Linked; +import de.steamwar.linkage.MaxVersion; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Material; @@ -35,7 +36,8 @@ import org.bukkit.event.block.Action; import org.bukkit.event.player.PlayerInteractEvent; @Linked -public class SignEdit implements Listener { +@MaxVersion(19) +public class SignEditUntil19 implements Listener { private static final Class blockPosition = Reflection.getClass("{nms.core}.BlockPosition"); private static final Class craftBlock = Reflection.getClass("{obc}.block.CraftBlock"); diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/xray/XrayCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/xray/XrayCommand.java index 1a9387c6..ff466080 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/xray/XrayCommand.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/xray/XrayCommand.java @@ -131,6 +131,7 @@ public class XrayCommand extends SWCommand implements Listener, ScoreboardElemen @EventHandler public void onPlayerInteract(PlayerInteractEvent event) { if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return; + if (!event.hasItem() || event.getItem().getType().isAir()) return; Region region = Region.getRegion(event.getPlayer().getLocation()); if (!(hidden.containsKey(region) && hidden.get(region).contains(event.getPlayer()))) { return; diff --git a/BauSystem_Main/src/de/steamwar/bausystem/region/Region.java b/BauSystem_Main/src/de/steamwar/bausystem/region/Region.java index dd234713..c6f8b5c7 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/region/Region.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/region/Region.java @@ -445,22 +445,18 @@ public class Region { pasteBuilder.pastePoint(minPointBuild.add(prototype.getBuild().getSizeX() / 2, 0, prototype.getBuild().getSizeZ() / 2)); break; case TESTBLOCK: - Point pastePoint = minPointTestblock.add(prototype.getTestblock().getSizeX() / 2, 0, 0); - if (!pasteBuilder.getClipboardProvider().is(PasteBuilder.SchematicProvider.class)) { - pastePoint = pastePoint.add(0, 0, prototype.getTestblock().getSizeZ() / 2); - } else { - int dz = Math.abs(pasteBuilder.getClipboard().getOrigin().getZ() - pasteBuilder.getClipboard().getMinimumPoint().getZ()); - if (dz < 2 || dz > prototype.getTestblock().getSizeZ()) { - pastePoint = pastePoint.add(0, 0, prototype.getTestblock().getSizeZ() / 2); - } else if (pasteBuilder.getClipboard().getDimensions().getZ() != prototype.getTestblock().getSizeZ()) { - pastePoint = pastePoint.add(0, 0, pasteBuilder.getClipboard().getDimensions().getZ() / 2 - (pasteBuilder.getClipboard().getOrigin().getZ() - pasteBuilder.getClipboard().getMinimumPoint().getZ()) - 1); - } else { - pastePoint = pastePoint.add(0, 0, prototype.getTestblock().getSizeZ() / 2); - } + Point pastePoint = minPointTestblock.add(prototype.getTestblock().getSizeX() / 2, 0, prototype.getTestblock().getSizeZ() / 2); + if (pasteBuilder.getClipboardProvider().is(PasteBuilder.SchematicProvider.class)) { SchematicType schematicType = pasteBuilder.getClipboardProvider().as(PasteBuilder.SchematicProvider.class).getSchematic().getSchemtype(); if (schematicType.getKuerzel().equalsIgnoreCase("wg")) { pastePoint = pastePoint.add(0, 0, 1); } + if (schematicType.getKuerzel().equalsIgnoreCase("ws")) { + pastePoint = pastePoint.add(-1, 0, 1); + } + if (schematicType.getKuerzel().equalsIgnoreCase("as")) { + pastePoint = pastePoint.add(-1, 0, 1); + } } pasteBuilder.pastePoint(pastePoint); break; diff --git a/BauSystem_Main/src/de/steamwar/bausystem/region/flags/flagvalues/TNTMode.java b/BauSystem_Main/src/de/steamwar/bausystem/region/flags/flagvalues/TNTMode.java index f6f2706d..9b05d6b5 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/region/flags/flagvalues/TNTMode.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/region/flags/flagvalues/TNTMode.java @@ -29,7 +29,8 @@ public enum TNTMode implements Flag.Value { ALLOW("FLAG_TNT_ALLOW"), DENY("FLAG_TNT_DENY"), - ONLY_TB("FLAG_TNT_ONLY_TB"); + ONLY_TB("FLAG_TNT_ONLY_TB"), + ONLY_BUILD("FLAG_TNT_ONLY_BUILD"); private static TNTMode[] values; private final String chatValue; diff --git a/BauSystem_Main/src/de/steamwar/bausystem/utils/PasteBuilder.java b/BauSystem_Main/src/de/steamwar/bausystem/utils/PasteBuilder.java index 3dddc008..b0479f90 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/utils/PasteBuilder.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/utils/PasteBuilder.java @@ -183,7 +183,10 @@ public class PasteBuilder { clipboard.setBlock(blockVector3, air); return; } - clipboard.setBlock(blockVector3, waterloggedRemover.applyBlock(blockVector3)); + baseBlock = waterloggedRemover.applyBlock(blockVector3); + if (baseBlock != air) { + clipboard.setBlock(blockVector3, baseBlock); + } }); } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/utils/PlaceItemUtils.java b/BauSystem_Main/src/de/steamwar/bausystem/utils/PlaceItemUtils.java new file mode 100644 index 00000000..2f83c416 --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/utils/PlaceItemUtils.java @@ -0,0 +1,552 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2023 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.utils; + +import com.comphenix.tinyprotocol.Reflection; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.experimental.UtilityClass; +import org.bukkit.*; +import org.bukkit.block.*; +import org.bukkit.block.data.*; +import org.bukkit.block.data.type.Hopper; +import org.bukkit.block.data.type.Observer; +import org.bukkit.block.data.type.*; +import org.bukkit.entity.Player; +import org.bukkit.event.block.BlockCanBuildEvent; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.inventory.EquipmentSlot; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.*; +import org.bukkit.util.RayTraceResult; +import org.bukkit.util.Vector; + +import java.util.*; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Collectors; + +@UtilityClass +public class PlaceItemUtils { + + // https://github.com/Articdive/ArticData/blob/1.20.1/1_20_1_tags/1_20_1_block_tags.json + // #minecraft:replaceable + private static final Set replaceables; + + static { + replaceables = new HashSet<>(Arrays.asList( + "minecraft:air", + "minecraft:water", + "minecraft:lava", + "minecraft:grass", + "minecraft:fern", + "minecraft:dead_bush", + "minecraft:seagrass", + "minecraft:tall_seagrass", + "minecraft:fire", + "minecraft:soul_fire", + "minecraft:snow", + "minecraft:vine", + "minecraft:glow_lichen", + "minecraft:light", + "minecraft:tall_grass", + "minecraft:large_fern", + "minecraft:structure_void", + "minecraft:void_air", + "minecraft:cave_air", + "minecraft:bubble_column", + "minecraft:warped_roots", + "minecraft:nether_sprouts", + "minecraft:crimson_roots", + "minecraft:hanging_roots")) + .stream() + .map(s -> s.substring(10)) + .map(String::toUpperCase) + .collect(Collectors.toSet()); + } + + private static final Map ITEM_MATERIAL_TO_BLOCK_MATERIAL = new HashMap<>(); + private static final Map BLOCK_MATERIAL_TO_WALL_BLOCK_MATERIAL = new HashMap<>(); + + static { + for (Material material : Material.values()) { + if (!material.isBlock()) continue; + if (material.isLegacy()) continue; + BlockData blockData = material.createBlockData(); + Material placementMaterial = blockData.getPlacementMaterial(); + if (material == placementMaterial) continue; + if (placementMaterial == Material.AIR) continue; + if (placementMaterial.isItem() && !placementMaterial.isBlock()) { + ITEM_MATERIAL_TO_BLOCK_MATERIAL.put(placementMaterial, material); + } + if (material.name().contains("WALL")) { + BLOCK_MATERIAL_TO_WALL_BLOCK_MATERIAL.put(placementMaterial, material); + } + } + } + + private static final Class blockPosition = Reflection.getClass("{nms.core}.BlockPosition"); + private static final Reflection.ConstructorInvoker blockPositionConstructor = Reflection.getConstructor(blockPosition, int.class, int.class, int.class); + private static final Class craftBlock = Reflection.getClass("{obc}.block.CraftBlockState"); + private static final Class craftWorld = Reflection.getClass("{obc}.CraftWorld"); + private static final Reflection.FieldAccessor positionAccessor = Reflection.getField(craftBlock, blockPosition, 0); + private static final Reflection.FieldAccessor worldAccessor = Reflection.getField(craftBlock, craftWorld, 0); + + /** + * Attempt to place an {@link ItemStack} the {@link Player} is holding against a {@link Block} inside the World. + * This can be easily used inside the {@link org.bukkit.event.player.PlayerInteractEvent} to mimik placing a + * block without any minecraft related GUI's etc. executing. + * + * @param player the Player placing the block + * @param itemStack the ItemStack to be placed + * @param against the Block at which the player aims (does not need to be in range of the player) + * @param againstSide the BlockFace the player aims + * @param hand the Hand the player is using + * @param force allow illegal states to be created by placing the block + * @param applyPhysics apply physics while placing the block + * @param rotateAway rotate everything in the opposite direction, so a block facing the Player will face away, and the other way round + * @param playSound enables sound of placing + */ + public PlaceItemResult placeItem(Player player, ItemStack itemStack, Block against, BlockFace againstSide, EquipmentSlot hand, boolean force, boolean applyPhysics, boolean rotateAway, boolean playSound) { + // If the ItemStack is null or air we cannot place it + if (itemStack == null) return PlaceItemResult.NO_ITEM_HELD; + if (itemStack.getType().isAir()) return PlaceItemResult.NO_ITEM_HELD; + + // This Block should be replaced by the new Block + Block block = against.getRelative(againstSide); + + // We cannot place any Item that is not also a Block, this is checked by testing for the ItemMeta + ItemMeta itemMeta = itemStack.getItemMeta(); + if (!(itemMeta instanceof BlockDataMeta)) { + return PlaceItemResult.NO_BLOCK_ITEM_HELD; + } + + BlockDataMeta blockDataMeta = (BlockDataMeta) itemMeta; + + // Converting the Item Material to a Block Material + // e.g. Material.REDSTONE -> Material.REDSTONE_WIRE + Material typeToPlace = ITEM_MATERIAL_TO_BLOCK_MATERIAL.getOrDefault(itemStack.getType(), itemStack.getType()); + + BlockData blockData = null; + AtomicBoolean usedForcePlace = new AtomicBoolean(); + if (againstSide == BlockFace.NORTH || againstSide == BlockFace.SOUTH || againstSide == BlockFace.EAST || againstSide == BlockFace.WEST) { + // Try Wall Placement first + blockData = toBlockData(player, blockDataMeta, BLOCK_MATERIAL_TO_WALL_BLOCK_MATERIAL.getOrDefault(typeToPlace, typeToPlace)); + if (blockData != null && !canPlace(block, blockData, force, usedForcePlace)) { + // Check if default Rotation from input could be valid + BlockFace rotation = getRotation(blockData); + setRotation(blockData, againstSide); + if (!canPlace(block, blockData, force, usedForcePlace)) { + setRotation(blockData, rotation); + } + } + } + + // Try default Placement + if (blockData == null || !canPlace(block, blockData, force, usedForcePlace)) { + blockData = toBlockData(player, blockDataMeta, typeToPlace); + } + + if (blockData != null && !canPlace(block, blockData, force, usedForcePlace)) { + if (blockData instanceof FaceAttachable) { + // FaceAttachable Blocks should be placed on the Ceiling/Floor if possible + // This applies mainly to Lever and Buttons + FaceAttachable faceAttachable = (FaceAttachable) blockData; + boolean topFirst = isHitHalfTop(player); + faceAttachable.setAttachedFace(topFirst ? FaceAttachable.AttachedFace.CEILING : FaceAttachable.AttachedFace.FLOOR); + if (!canPlace(block, blockData, force, usedForcePlace)) { + faceAttachable.setAttachedFace(topFirst ? FaceAttachable.AttachedFace.FLOOR : FaceAttachable.AttachedFace.CEILING); + } + if (!canPlace(block, blockData, force, usedForcePlace)) { + return PlaceItemResult.NO_VALID_PLACEMENT; + } + } + } + + if (blockData == null) return PlaceItemResult.NO_BLOCK_ITEM_HELD; + + // Placing a Block inside of Water should set it to Waterlogged + if (blockData instanceof Waterlogged) { + ((Waterlogged) blockData).setWaterlogged(block.getType() == Material.WATER); + } + + if (blockData instanceof Slab) { + // Slabs can be set at Top or Bottom + ((Slab) blockData).setType(isHitHalfTop(player) ? Slab.Type.TOP : Slab.Type.BOTTOM); + } else if (blockData instanceof Stairs) { + // Stairs can be set at Top or Bottom + ((Stairs) blockData).setHalf(isHitHalfTop(player) ? Bisected.Half.TOP : Bisected.Half.BOTTOM); + } else if (blockData instanceof TrapDoor) { + // TrapDoors can be set at Top or Bottom + ((TrapDoor) blockData).setHalf(isHitHalfTop(player) ? Bisected.Half.TOP : Bisected.Half.BOTTOM); + } else if (blockData instanceof Chain) { + // Chains are always rotated against the block you place against + Orientable orientable = (Orientable) blockData; + switch (againstSide) { + case EAST: + case WEST: + orientable.setAxis(Axis.X); + break; + case UP: + case DOWN: + orientable.setAxis(Axis.Y); + break; + case NORTH: + case SOUTH: + orientable.setAxis(Axis.Z); + break; + } + } else if (blockData instanceof Hopper && (againstSide == BlockFace.UP || againstSide == BlockFace.DOWN)) { + // Placing at the Top or Bottom of a Block result in a downwards facing Hopper + ((Hopper) blockData).setFacing(BlockFace.DOWN); + } else if (blockData instanceof Directional && (blockData.getMaterial().name().endsWith("_HEAD") || blockData.getMaterial().name().endsWith("_SKULL")) && againstSide != BlockFace.DOWN && againstSide != BlockFace.UP) { + // Skulls and Heads are always rotated towards you if not in Wall variant + ((Directional) blockData).setFacing(againstSide); + } else if (blockData instanceof LightningRod) { + // Lightning Rod is always rotated against the block you place against + ((Directional) blockData).setFacing(againstSide); + } + if (force && blockData instanceof FaceAttachable) { + // Forcing to Place a FaceAttachable against the Block you specified. Needs the force flag to be set + FaceAttachable faceAttachable = (FaceAttachable) blockData; + if (blockData instanceof Switch && againstSide == BlockFace.DOWN) { + faceAttachable.setAttachedFace(FaceAttachable.AttachedFace.CEILING); + } else if (againstSide == BlockFace.UP) { + faceAttachable.setAttachedFace(FaceAttachable.AttachedFace.FLOOR); + } else if (blockData instanceof Directional) { + ((Directional) blockData).setFacing(againstSide); + } + if (blockData instanceof Switch) { + // Levers and Buttons are always Rotated the other way + Switch switchType = (Switch) blockData; + switch (switchType.getAttachedFace()) { + case FLOOR: + case CEILING: + switchType.setFacing(switchType.getFacing().getOppositeFace()); + break; + } + } + } + if (force && blockData instanceof Directional && !(blockData instanceof FaceAttachable) && BLOCK_MATERIAL_TO_WALL_BLOCK_MATERIAL.containsValue(blockData.getMaterial())) { + Directional directional = (Directional) blockData; + if (directional.getFaces().contains(againstSide)) { + directional.setFacing(againstSide); + } + } + if (force && blockData instanceof Rotatable && !(blockData instanceof FaceAttachable)) { + Rotatable rotatable = (Rotatable) blockData; + if (againstSide != BlockFace.UP && againstSide != BlockFace.DOWN) { + rotatable.setRotation(againstSide); + } + } + + if (blockData instanceof RedstoneWire) { + // Redstone Wire is connected to every Side by default + RedstoneWire redstoneWire = (RedstoneWire) blockData; + redstoneWire.setFace(BlockFace.NORTH, RedstoneWire.Connection.SIDE); + redstoneWire.setFace(BlockFace.SOUTH, RedstoneWire.Connection.SIDE); + redstoneWire.setFace(BlockFace.EAST, RedstoneWire.Connection.SIDE); + redstoneWire.setFace(BlockFace.WEST, RedstoneWire.Connection.SIDE); + } + + if (rotateAway) { + // Rotate the other way if rotateAway is set to true + BlockFace blockFace = getRotation(blockData); + if (blockFace != null) { + blockFace = blockFace.getOppositeFace(); + if (blockData instanceof Hopper && (blockFace == BlockFace.UP || blockFace == BlockFace.DOWN)) { + ((Hopper) blockData).setFacing(BlockFace.DOWN); + } else { + setRotation(blockData, blockFace); + } + } + } + + // Check if the Block can be build + BlockCanBuildEvent blockCanBuildEvent = new BlockCanBuildEvent(against, player, blockData, canPlace(block, blockData, force, usedForcePlace)); + Bukkit.getPluginManager().callEvent(blockCanBuildEvent); + if (!blockCanBuildEvent.isBuildable()) return PlaceItemResult.NO_BUILD; + + BlockState oldState = block.getState(); + + // Retrieve the BlockState of the ItemStack if present + BlockState blockState = null; + if (itemMeta instanceof BlockStateMeta) { + blockState = ((BlockStateMeta) itemMeta).getBlockState(); + } + + if (blockState == null) { + // If no BlockState is present use the BlockState of the Block you want to edit + blockState = block.getState(); + } else { + // If a BlockState is present set the Position and World to the Block you want to place + Location blockLocation = block.getLocation(); + positionAccessor.set(blockState, blockPositionConstructor.invoke(blockLocation.getBlockX(), blockLocation.getBlockY(), blockLocation.getBlockZ())); + worldAccessor.set(blockState, blockLocation.getWorld()); + } + + if (blockData.getMaterial().isSolid()) { + for (Player p : Bukkit.getOnlinePlayers()) { + Location min = p.getLocation().add(-0.3, 0, -0.3); + Location max = p.getLocation().add(0.3, p.isSneaking() ? 1.5 : 1.8, 0.3); + + Location blockmin = block.getLocation(); + Location blockmax = block.getLocation().add(1.0, 1.0, 1.0); + if ( + !(max.getX() <= blockmin.getX() || min.getX() >= blockmax.getX() || + max.getY() <= blockmin.getY() || min.getY() >= blockmax.getY() || + max.getZ() <= blockmin.getZ() || min.getZ() >= blockmax.getZ()) + ) { + return PlaceItemResult.NO_PLACE_INSIDE_PLAYER; + } + } + } + + // Set the generated BlockData to the BlockState and update the world without physics + blockState.setBlockData(blockData); + blockState.update(true, false); + + // Check if the Block is allowed to be placed + BlockPlaceEvent blockPlaceEvent = new BlockPlaceEvent(block, oldState, against, itemStack, player, true, hand); + Bukkit.getPluginManager().callEvent(blockCanBuildEvent); + if (blockPlaceEvent.isCancelled() || !blockPlaceEvent.canBuild()) { + // Reset world + oldState.update(true, false); + return PlaceItemResult.NO_PLACE; + } + + if (hasSecondBlock(blockData)) { + // Place tht second block of a Door or Tallgrass. + Bisected bisected = (Bisected) blockData; + Block blockAbove = block.getRelative(0, 1, 0); + bisected.setHalf(Bisected.Half.TOP); + if (canPlace(blockAbove, blockData, force, usedForcePlace)) { + if (blockData instanceof Waterlogged) { + ((Waterlogged) blockData).setWaterlogged(blockAbove.getType() == Material.WATER); + } + blockAbove.setBlockData(blockData, applyPhysics); + } else { + // If the second Block couldn't be placed remove the first Block as well + oldState.update(true, false); + return PlaceItemResult.NO_DOUBLE_HIGH_BLOCK_SPACE; + } + } + if (applyPhysics) { + // Apply Physics by placing the old State without Physics and setting the new with physics + oldState.update(true, false); + blockState.update(true, true); + } + + if (itemMeta instanceof BannerMeta) { + // Apply Banner Patterns to now placed Block in World + BannerMeta bannerMeta = (BannerMeta) itemMeta; + Banner banner = (Banner) block.getState(); + banner.setPatterns(bannerMeta.getPatterns()); + banner.update(true, false); + } else if (itemMeta instanceof SkullMeta) { + // Apply Skull Data to now placed Block in World + SkullMeta skullMeta = (SkullMeta) itemMeta; + Skull skull = (Skull) block.getState(); + skull.setOwnerProfile(skullMeta.getOwnerProfile()); + skull.setOwningPlayer(skullMeta.getOwningPlayer()); + skull.update(true, false); + } + + if (playSound) { + // Play the corresponding sound of placing the now placed Block + SoundGroup soundGroup = blockData.getSoundGroup(); + block.getWorld().playSound(block.getLocation(), soundGroup.getPlaceSound(), soundGroup.getVolume() * 0.8F, soundGroup.getPitch() * 0.8F); + } + return usedForcePlace.get() ? PlaceItemResult.SUCCESS_FORCE : PlaceItemResult.SUCCESS; + } + + public BlockFace[] axis = { BlockFace.NORTH, BlockFace.EAST, BlockFace.SOUTH, BlockFace.WEST }; + public BlockFace[] radial = { BlockFace.NORTH, BlockFace.NORTH_EAST, BlockFace.EAST, BlockFace.SOUTH_EAST, BlockFace.SOUTH, BlockFace.SOUTH_WEST, BlockFace.WEST, BlockFace.NORTH_WEST }; + + public BlockFace yawToFace(float yaw) { + return radial[Math.round(yaw / 45f) & 0x7]; + } + + public BlockFace yawToFaceAxis(float yaw) { + return axis[Math.round(yaw / 90f) & 0x3]; + } + + public BlockFace toFace(Set faces, float pitch, float yaw) { + if (faces.contains(BlockFace.UP) && pitch >= 45.0) { + return BlockFace.UP; + } + if (faces.contains(BlockFace.DOWN) && pitch <= -45.0) { + return BlockFace.DOWN; + } + return yawToFaceAxis(yaw); + } + + public BlockData toBlockData(Player player, BlockDataMeta blockDataMeta, Material material) { + BlockData blockData; + try { + blockData = blockDataMeta.getBlockData(material); + } catch (NullPointerException e) { + // Some items have a BlockDataMeta but they cannot be converted to one like ItemFrame, those will be ignored + return null; + } + + if (blockData instanceof Stairs || blockData instanceof Observer || blockData instanceof Hopper || blockData instanceof Door) { + // Stairs, Observer, Hopper and Doors are placed the opposite way + Directional directional = (Directional) blockData; + BlockFace face = toFace(directional.getFaces(), player.getLocation().getPitch(), player.getLocation().getYaw()); + directional.setFacing(face.getOppositeFace()); + } else if (blockData instanceof Orientable) { + // Orientable only have 3 Axis: X, Y, Z + Orientable orientable = (Orientable) blockData; + Set faces = new HashSet<>(); + Set axisSet = orientable.getAxes(); + if (axisSet.contains(Axis.X)) { + faces.add(BlockFace.EAST); + faces.add(BlockFace.WEST); + } + if (axisSet.contains(Axis.Y)) { + faces.add(BlockFace.UP); + faces.add(BlockFace.DOWN); + } + if (axisSet.contains(Axis.Z)) { + faces.add(BlockFace.NORTH); + faces.add(BlockFace.SOUTH); + } + BlockFace face = toFace(faces, player.getLocation().getPitch(), player.getLocation().getYaw()); + switch (face) { + case EAST: + case WEST: + orientable.setAxis(Axis.X); + break; + case UP: + case DOWN: + orientable.setAxis(Axis.Y); + break; + case NORTH: + case SOUTH: + orientable.setAxis(Axis.Z); + break; + } + } else if (blockData instanceof Rotatable) { + Rotatable rotatable = (Rotatable) blockData; + BlockFace blockeFace = yawToFace(player.getLocation().getYaw()); + if (blockData.getMaterial().name().endsWith("_HEAD") || blockData.getMaterial().name().endsWith("_SKULL")) { + // Wall Heads and Wall Skulls are placed the opposite way + rotatable.setRotation(blockeFace.getOppositeFace()); + } else { + rotatable.setRotation(blockeFace); + } + } else if (blockData instanceof Directional) { + Directional directional = (Directional) blockData; + directional.setFacing(toFace(directional.getFaces(), player.getLocation().getPitch(), player.getLocation().getYaw())); + } else if (blockData instanceof Rail) { + Rail rail = (Rail) blockData; + BlockFace face = yawToFaceAxis(player.getLocation().getYaw()); + // Rails are only represented by 2 States, North_South or East_West the remaining States will be ignored here + rail.setShape(face == BlockFace.NORTH || face == BlockFace.SOUTH ? Rail.Shape.NORTH_SOUTH : Rail.Shape.EAST_WEST); + } + + return blockData; + } + + private BlockFace getRotation(BlockData blockData) { + if (blockData instanceof Rotatable) { + return ((Rotatable) blockData).getRotation(); + } else if (blockData instanceof Directional) { + return ((Directional) blockData).getFacing(); + } else if (blockData instanceof Rail) { + Rail rail = (Rail) blockData; + switch (rail.getShape()) { + case NORTH_SOUTH: + return BlockFace.NORTH; + case EAST_WEST: + return BlockFace.EAST; + } + } + return null; + } + + private void setRotation(BlockData blockData, BlockFace rotation) { + if (blockData instanceof Rotatable) { + ((Rotatable) blockData).setRotation(rotation); + } else if (blockData instanceof Directional) { + ((Directional) blockData).setFacing(rotation); + } else if (blockData instanceof Rail) { + Rail rail = (Rail) blockData; + switch (rotation) { + case NORTH: + case SOUTH: + rail.setShape(Rail.Shape.NORTH_SOUTH); + break; + case EAST: + case WEST: + rail.setShape(Rail.Shape.EAST_WEST); + break; + } + } + } + + private boolean isHitHalfTop(Player player) { + RayTraceResult rayTraceResult = player.rayTraceBlocks(6, FluidCollisionMode.NEVER); + if (rayTraceResult != null) { + Vector vector = rayTraceResult.getHitPosition(); + return (vector.getY() - vector.getBlockY()) > 0.5; + } + return false; + } + + private boolean hasSecondBlock(BlockData blockData) { + if (!(blockData instanceof Bisected)) { + return false; + } + if (blockData instanceof Door) { + return true; + } + return blockData.getClass().getName().contains("Tall"); + } + + private boolean canPlace(Block block, BlockData blockData, boolean force, AtomicBoolean usedForcePlace) { + if (!block.canPlace(blockData)) { + if (force) usedForcePlace.set(true); + return force; + } + return replaceables.contains(block.getType().name()); + } + + @AllArgsConstructor + @Getter + public enum PlaceItemResult { + NO_ITEM_HELD(false), + NO_BLOCK_ITEM_HELD(false), + NO_VALID_PLACEMENT(false), + NO_BUILD(false), + NO_PLACE(false), + NO_DOUBLE_HIGH_BLOCK_SPACE(false), + NO_PLACE_INSIDE_PLAYER(false), + SUCCESS(true), + SUCCESS_FORCE(true), + ; + + private final boolean success; + + public boolean wasForced() { + return this == SUCCESS_FORCE; + } + } +} diff --git a/SCRIPT.md b/SCRIPT.md index bd4edd7c..ae9cb181 100644 --- a/SCRIPT.md +++ b/SCRIPT.md @@ -144,11 +144,12 @@ Es gibt folgende weitere Module: Das `tnt`-Modul stellt Funktionen zur Verfügung, die den TNT-Modus in der Region des Spielers betreffen. Es gibt folgende Funktionen: -| Name | Signature | Beschreibung | -|-----------|--------------------|-------------------------------------------------------------------------------------| -| `mode` | mode(): String | Gibt den Aktuellen TNT-Modus zurück, die werte sind: `ALLOW`, `DENY` oder `ONLY_TB` | -| `enabled` | enabled(): Boolean | Gibt zurück, ob der TNT-Modus in der Region des Spielers aktiviert ist oder nicht | -| `onlyTb` | onlyTb(): Boolean | Gibt zurück, ob der TNT-Modus auf Only-Tb ist | +| Name | Signature | Beschreibung | +|-------------|----------------------|-------------------------------------------------------------------------------------| +| `mode` | mode(): String | Gibt den Aktuellen TNT-Modus zurück, die werte sind: `ALLOW`, `DENY` oder `ONLY_TB` | +| `enabled` | enabled(): Boolean | Gibt zurück, ob der TNT-Modus in der Region des Spielers aktiviert ist oder nicht | +| `onlyTb` | onlyTb(): Boolean | Gibt zurück, ob der TNT-Modus auf Only-Tb ist | +| `onlyBuild` | onlyBuild(): Boolean | Gibt zurück, ob der TNT-Modus auf Only-Build ist | #### trace diff --git a/sw.def.lua b/sw.def.lua index d1570fd8..d56a134e 100644 --- a/sw.def.lua +++ b/sw.def.lua @@ -167,6 +167,9 @@ function tnt.enabled() return nil end ---@return boolean function tnt.onlyTb() return nil end +---@return boolean +function tnt.onlyBuild() return nil end + ---@class trace local trace = {} @@ -341,3 +344,54 @@ function command(command, handler) end ---@param handler fun(pressed: boolean): void ---@return void function hotkey(trigger, handler) end + +---@class bossbar +bossbar = {} + +---@alias BossBarColor 'PINK' | 'BLUE' | 'RED' | 'GREEN' | 'YELLOW' | 'PURPLE' | 'WHITE' +---@alias BossBarStyle 'SEGMENTED_6' | 'SEGMENTED_10' | 'SEGMENTED_12' | 'SEGMENTED_20' | 'SOLID' +---@alias BossBarFlag 'DARKEN_SKY' | 'PLAY_BOSS_MUSIC' | 'CREATE_FOG' + +---@class BossBar +local BossBar = {} + +---@param title string +---@param color BossBarColor +---@param style BossBarStyle +---@return BossBar +function bossbar.create(title, color, style) return nil end + +---@return string +---@overload fun(title: string): void +function BossBar.title() end + +---@return BossBarColor +---@overload fun(color: BossBarColor): void +function BossBar.color() end + +---@return BossBarStyle +---@overload fun(style: BossBarStyle): void +function BossBar.style() end + +---@return number +---@overload fun(progress: number): void +function BossBar.progress() end + +---@return boolean +---@overload fun(visible: boolean): void +function BossBar.visible() end + +---@return boolean +---@param flag BossBarFlag +function BossBar.hasFlag(flag) return nil end + +---@return void +---@param flag BossBarFlag +function BossBar.addFlag(flag) end + +---@return boolean +---@param flag BossBarFlag +function BossBar.removeFlag(flag) return nil end + +---@return void +function BossBar.destroy() end