Compare commits

..
Author SHA1 Message Date
YoyoNow 0ae094abe4 With EndsWithHandler 2025-12-21 09:45:37 +01:00
YoyoNow 3d6c50938c Improve error messages 2025-11-24 10:00:45 +01:00
YoyoNow e9d814bc95 Fix AssertionUtils.SimpleAssertion.assertNoInitialize 2025-11-23 21:20:08 +01:00
YoyoNow ef61cf455d Fix MapperHandler, SupplierHandler, ValidatorHandler
Improve HandlerForVariableElement.getAnnotations()
Improve HandlerForTypeMirror.isEnum
Add HandlerForTypeMirror.getTypeName
2025-11-23 21:14:09 +01:00
YoyoNow b6bad4e78e Fix HandlerForVariableElement.getAnnotations 2025-11-23 20:54:08 +01:00
YoyoNow 18659385d2 Add Annotation Processor for compile time checks 2025-11-23 20:27:44 +01:00
YoyoNow f6fc65a370 Fix SupplierHandler checking for AbstractTypeMapper instead of AbstractTypeSupplier 2025-11-23 16:36:48 +01:00
YoyoNow fbc14d0503 Fix AbstractCommand with empty args for execute 2025-11-23 16:18:14 +01:00
YoyoNow 9fe38bcf61 Fix java version for Velocity CommandFramework 2025-11-23 15:11:06 +01:00
YoyoNow fd22c1cccc Fix registering of commands 2025-11-23 08:32:44 +01:00
YoyoNow b627b3b4a6 Fix build errors of CommandFramework 2025-11-23 08:27:11 +01:00
YoyoNow f9faa9b296 Initial copy from other repository (nothing is fixed here) 2025-11-22 23:08:48 +01:00
Chaoscaot e343d044ff Refactor Discord authentication endpoint for improved error handling and structure
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-14 23:56:04 +01:00
Chaoscaot f923a007a7 Revert "Add EventCache for efficient retrieval of event groups and teams"
This reverts commit 8b4f864f99.

Revert "Refactor EventFights and Fight classes to improve player initialization and retrieval"

This reverts commit 8d705e7a84.

Revert "Refactor EventFights and Fight classes to improve player initialization and retrieval"

This reverts commit 78352a3e67.
2025-11-14 23:25:05 +01:00
Chaoscaot 78352a3e67 Refactor EventFights and Fight classes to improve player initialization and retrieval
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-14 23:18:38 +01:00
Chaoscaot 8d705e7a84 Refactor EventFights and Fight classes to improve player initialization and retrieval
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-14 23:14:13 +01:00
Chaoscaot 8b4f864f99 Add EventCache for efficient retrieval of event groups and teams
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-14 22:47:27 +01:00
Chaoscaot f9cb712b07 Merge pull request 'Simplify Tokens and add Discord OAuth' (#220) from authv3 into main
Reviewed-on: SteamWar/SteamWar#220
Reviewed-by: YoyoNow <yoyonow@noreply.localhost>
2025-11-14 22:43:04 +01:00
Chaoscaot b3b13d2950 Move Chatter.disconnect call to ensure proper execution after IP ban check.
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-13 23:01:37 +01:00
Chaoscaot 08ad5edf76 Simplify Tokens and add Discord OAuth
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-13 14:31:05 +01:00
Chaoscaot afcf3a1906 Fix Schematic Move
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-12 22:52:51 +01:00
YoyoNow 33efd26d48 Fix build.gradle.kts 2025-11-12 07:43:36 +01:00
YoyoNow 2a96b3c26a Hotfix AutoCheckerItems for 1.19 2025-11-11 22:06:44 +01:00
YoyoNow 3de4b3871d Hotfix ModifyPart 2025-11-11 21:42:38 +01:00
YoyoNow 67223be80e Trigger rebuild 2025-11-11 21:28:13 +01:00
Chaoscaot 81715736ae Refactor TeamTable to introduce default values for color and deleted, and make address column nullable.
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-11 18:44:46 +01:00
Chaoscaot 36691c6fea Refactor TeamTable to introduce default values for color and deleted, and make address column nullable.
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-11 18:44:25 +01:00
YoyoNow 58618a3991 Fix FightTeam.removeLeader
Fix FightTeam.setLeader
2025-11-11 17:36:19 +01:00
Chaoscaot e6848b27a0 Refactor FightTable to use WinningTeam enum for win column and adjust related logic.
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-11 17:25:38 +01:00
Chaoscaot 93d0011b46 Update openMaterialSelector to exclude non-item materials in UtilGui.
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-11 17:20:33 +01:00
YoyoNow f56fedefe4 Fix Obsidian and Bedrock 2025-11-11 17:07:56 +01:00
YoyoNow 167bb4e266 Fix YMLWrapper 2025-11-11 17:05:46 +01:00
YoyoNow f6a9ce184b Closes: #214
Closes: #215
2025-11-11 16:40:26 +01:00
Chaoscaot d5708c110c Refactor NodeDataTable to use default current timestamp for createdAt and ensure schemData reads blob as bytes.
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-11 00:18:16 +01:00
Chaoscaot f23c1215b7 Refactor NodeDataTable to use insert instead of insertIgnore and add blobParam import.
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-11 00:15:19 +01:00
YoyoNow cfcaf1569c Add GameModeConfig.Schematic.MaxBlastResistance 2025-11-10 21:39:35 +01:00
Chaoscaot dc56b67ff6 Sort fights by start time in descending order and refactor saveFromStream method to use useDb block.
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-10 14:18:13 +01:00
Chaoscaot 13c4a3ff8b Sort fights by start time in descending order and refactor saveFromStream method to use useDb block.
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-10 12:27:02 +01:00
Chaoscaot 7e5a13989b Sort fights by start time in descending order and refactor saveFromStream method to use useDb block.
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-10 12:24:51 +01:00
Chaoscaot 990a03ca6c Add Exposed library dependencies to WebsiteBackend build script.
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-10 11:57:12 +01:00
YoyoNow 4a608fe5b5 Fix SchematicType.fromDB 2025-11-10 11:55:17 +01:00
Chaoscaot 5ca15aa117 Refactor PersonalKitTable to use explicit ID column initialization and update create method to utilize insert operation.
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-10 11:50:39 +01:00
Chaoscaot 9b459bd12c Refactor PersonalKitTable to use explicit ID column initialization and update create method to utilize insert operation.
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-10 11:40:34 +01:00
Chaoscaot b20d37e252 Refactor PersonalKitTable to use explicit ID column initialization and update create method to utilize insert operation.
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-10 11:40:20 +01:00
YoyoNow a8c98594a9 Fix GameModeConfig.Schematic.SubTypes 2025-11-10 11:32:03 +01:00
Chaoscaot 1c076b5bbf Fix incorrect field references in BauweltMember methods.
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-10 11:19:56 +01:00
Chaoscaot 133ddb39cc Add ID column initialization for BauweltMember
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-10 11:09:57 +01:00
YoyoNow ebb375d8d6 Improve messages 2025-11-10 11:04:29 +01:00
YoyoNow 8ada9a6335 Fix UserElo.getEloFromDb 2025-11-10 11:01:31 +01:00
Chaoscaot 0760a5a08a Update build scripts: migrate to Spigot API, adjust JVM toolchains and Java version.
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-10 09:42:24 +01:00
Chaoscaot 852ff95757 Update build scripts: migrate to Spigot API, adjust JVM toolchains and Java version.
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-10 09:40:36 +01:00
Chaoscaot 5c7d388876 Remove unused SLF4J exclusion from shadowJar task.
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-10 09:34:44 +01:00
Chaoscaot 4f92f8132d Remove unused SLF4J exclusion from shadowJar task.
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-10 09:27:58 +01:00
Chaoscaot 56fb63f781 Add MySQL dependency to KotlinCore build script.
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-10 09:17:37 +01:00
Chaoscaot 273efff87d Remove unused api-version field from plugin.yml.
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-10 09:16:14 +01:00
Chaoscaot 0cac6f36c1 Remove unused api-version field from plugin.yml.
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-10 09:09:44 +01:00
Chaoscaot 8680b9e6cf Change api dependencies to compileOnlyApi in build.gradle.kts and rename KitName column to Name in PersonalKitTable.
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-10 09:02:23 +01:00
YoyoNow 6c94efaf90 Improve TeamCommand.info 2025-11-10 09:00:18 +01:00
YoyoNow f6261ad989 Improve output for DevCommand reloadmodes 2025-11-10 09:00:18 +01:00
Chaoscaot 614e989892 Rename IgnoreTable to IgnoredPlayers in IgnoreSystemTable for improved clarity.
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-10 08:47:32 +01:00
Chaoscaot 84e1f605bd Merge pull request 'Exposed!' (#179) from exposed into main
Reviewed-on: SteamWar/SteamWar#179
Reviewed-by: YoyoNow <yoyonow@noreply.localhost>
2025-11-10 08:42:59 +01:00
Chaoscaot 0ea5a62dbe Merge branch 'main' into exposed 2025-11-10 08:40:42 +01:00
Chaoscaot 0eb6047139 Merge remote-tracking branch 'origin/exposed' into exposed 2025-11-09 17:48:12 +01:00
Chaoscaot fcebecf745 Add placement column to TeamTeilnahme table and corresponding property.
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-09 17:48:02 +01:00
YoyoNow dd14e9f518 Cleanup Session 2025-11-09 17:30:21 +01:00
Chaoscaot 6c5239c8fc Optimize imports across SQL module: replace explicit class imports with wildcard imports, remove unused imports for cleaner structure.
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-09 17:28:40 +01:00
Chaoscaot fc71f47add Remove needsAdmin property from PunishmentType enum and refactor related declarations for cleaner structure.
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-09 17:25:19 +01:00
Chaoscaot 5d36393643 Refactor EventRelation, EventGroup, and EventFight classes: ensure database operations are enclosed in useDb, add default values for group points, and override delete methods. Update Gradle build script to include lombok dependencies.
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-08 22:44:22 +01:00
Chaoscaot ebc6f50261 Refactor Gradle build scripts: update source set exclusions, add java-library plugin, and remove redundant configurations in SQL module.
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-08 13:52:27 +01:00
YoyoNow 69cf219e39 Fix FlatteningWrapper21 2025-11-07 22:47:05 +01:00
YoyoNow fb4e53165f Hotfix FixedFlagStorage.clear and FixedGlobalFlagStorage.clear 2025-11-07 22:42:48 +01:00
YoyoNow 415d783365 Hotfix SEND_COMMAND_FEEDBACK in 1.20+ 2025-11-07 22:17:30 +01:00
YoyoNow ee99708340 Hotfix (FA)WE Selection 1.20+ 2025-11-07 22:13:31 +01:00
Chaoscaot c9d74fb656 Remove redundant SQL logger in useDb and extra newlines in SQLConfig.
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-07 18:59:01 +01:00
Chaoscaot e50e52950b Refactor Token and SteamwarUser classes: enhance owner property with memoized transformation, increase hash generation key size, and ensure database usage in useDb block.
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-07 18:57:34 +01:00
YoyoNow cac0ae3e13 Hotfix MaterialLazyInit for 1.21 2025-11-07 15:41:48 +01:00
YoyoNow f9b3dd34cf Trigger rebuild 2025-11-07 15:25:20 +01:00
Chaoscaot e5a61226ca Add newline at end of build.gradle.kts file for consistency.
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-07 15:06:37 +01:00
Chaoscaot 0c35ace5e2 Remove redundant Java installation paths in Gradle configuration.
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-07 14:54:30 +01:00
Chaoscaot 23bcf14ca5 Update Gradle configuration to specify multiple Java installation paths for compatibility.
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-07 14:53:07 +01:00
Chaoscaot 63a5fcff97 Add Kotlin plugin and configure build scripts for Kotlin compatibility, integrate exposed library dependencies, and enhance JVM settings.
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-07 14:40:10 +01:00
Chaoscaot 39b3cdb897 Introduce GDPRQuery command for GDPR data generation, refactor SQL statements, and improve null safety across modules.
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-07 12:42:15 +01:00
YoyoNow 3ccfe92afb Remove DC prefix for discord send messages to cleanup the chat 2025-11-07 08:46:26 +01:00
YoyoNow c17b76851d Improve chat from discord 2025-11-07 08:44:07 +01:00
YoyoNow f0e18bfc72 Improve CouncilChannel and StaticMessageChannel 2025-11-07 08:39:42 +01:00
YoyoNow 160f982955 Improve ChatListener for STC Chat
Add debug output for DiscordChannel
Fix CouncilChannel
2025-11-07 08:34:19 +01:00
Chaoscaot 6ac0143459 Remove outdated SQL-related Java classes (GDPRQuery, Field, SelectStatement, SqlTypeMapper, Statement) and update references across modules.
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-06 11:30:01 +01:00
Chaoscaot 98ca9e852c Merge pull request 'Add version dependant impl of tps warp to fight system' (#187) from FightSystem/Add-version-dependent-impl-of-tps-warp into main
Reviewed-on: SteamWar/SteamWar#187
Reviewed-by: Chaoscaot <max@chaoscaot.de>
2025-11-06 09:50:24 +01:00
D4rkr34lm 17910ec8a4 Add version dependant impl 2025-11-06 02:07:20 +01:00
Chaoscaot 56bc75763b Migrate Token class to Kotlin, remove outdated Java implementation, and refactor references across modules. Update timestamp fields to use CurrentTimestamp where applicable.
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-05 21:44:52 +01:00
Chaoscaot 8272c73b48 Migrate SQL-related classes (Referee, SchemElo, Script, Session, SWException, TeamTeilnahme) to Kotlin and remove outdated Java implementations. Update references across modules.
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-05 17:47:30 +01:00
Chaoscaot 9acfb32ae0 Refactor SQL classes: update GameModeConfig functions, improve null safety in SchematicNode and SchematicType, and adjust NodeMemberTable structure.
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-05 17:04:01 +01:00
Chaoscaot b2a4b05545 Merge branch 'main' into exposed
# Conflicts:
#	CommonCore/SQL/src/de/steamwar/sql/GameModeConfig.java
#	CommonCore/SQL/src/de/steamwar/sql/Punishment.java
2025-11-05 16:18:30 +01:00
Chaoscaot 89e2df0eb2 Migrate Punishment and PollAnswer classes to Kotlin and remove outdated Java implementations. Update references across modules.
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-04 21:17:53 +01:00
Chaoscaot 73da9179bf Migrate SQL-related classes (IgnoreSystem, Mod, NodeDownload, NodeMember) to Kotlin and remove old Java implementations. Update references across modules.
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-02 19:28:14 +01:00
Chaoscaot 0fbbcdacea Migrate Fight, FightPlayer, and SchematicType classes to Kotlin and remove old Java implementations. Update references across modules.
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-01 13:52:26 +01:00
Chaoscaot 4e6933f2fd Remove Event-related SQL classes and update relevant references across modules
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-10-30 23:14:25 +01:00
Chaoscaot eea1073892 Migrate Event class to Kotlin and update references across modules
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-10-29 23:17:17 +01:00
Chaoscaot 702aa1cfa6 Refactor CheckedSchematic and migrate to Kotlin
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-10-29 17:42:29 +01:00
Chaoscaot 6ea73f4890 Refactor NodeData
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-10-28 22:25:31 +01:00
Chaoscaot 14e82f36a5 Rename .java to .kt
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-10-28 22:25:31 +01:00
Chaoscaot a8eaf3daa7 Fixes
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-10-28 21:31:57 +01:00
Chaoscaot b51ea484e4 Refactor UserConfig
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-10-28 20:38:02 +01:00
Chaoscaot 8bef19ed8b Rename .java to .kt
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-10-28 20:38:02 +01:00
Chaoscaot 1aff7b30a6 Refactor SchematicNode 2025-10-28 19:03:30 +01:00
Chaoscaot c8ac984ad3 Rename .java to .kt 2025-10-28 19:03:30 +01:00
Chaoscaot a462231bab Starting... 2025-10-27 18:34:31 +01:00
Chaoscaot e6bbb76a0b Rename .java to .kt 2025-10-27 18:34:30 +01:00
479 changed files with 23040 additions and 6679 deletions
@@ -1,18 +1,20 @@
/*
* This file is a part of the SteamWar software.
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
* Copyright (C) 2025 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 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.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License along with this program.
* If not, see <https://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem;
@@ -44,6 +46,7 @@ import de.steamwar.linkage.SpigotLinker;
import de.steamwar.message.Message;
import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.GameRule;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@@ -69,7 +72,6 @@ public class BauSystem extends JavaPlugin implements Listener {
@Getter
private static BauSystem instance;
@Getter
private SpigotLinker linker;
@Override
@@ -127,6 +129,8 @@ public class BauSystem extends JavaPlugin implements Listener {
TraceRecorder.instance.init();
new WorldEditRendererCUIEditor();
Bukkit.getWorlds().get(0).setGameRule(GameRule.SEND_COMMAND_FEEDBACK, false);
}
@EventHandler
@@ -182,8 +186,7 @@ public class BauSystem extends JavaPlugin implements Listener {
@Override
public void run() {
if (TickManager.impl.isFrozen())
return;
if (TickManager.impl.isFrozen()) return;
if (counter >= delay) {
runnable.run();
cancel();
@@ -201,8 +204,7 @@ public class BauSystem extends JavaPlugin implements Listener {
@Override
public void run() {
if (TickManager.impl.isFrozen())
return;
if (TickManager.impl.isFrozen()) return;
if (counter >= (first ? delay : period)) {
first = false;
runnable.run();
@@ -218,4 +220,4 @@ public class BauSystem extends JavaPlugin implements Listener {
AtomicReference<BukkitTask> task = new AtomicReference<>();
task.set(runTaskTimer(plugin, () -> consumer.accept(task.get()), delay, period));
}
}
}
@@ -36,7 +36,7 @@ public class BauServer {
private Integer owner;
public UUID getOwner() {
return SteamwarUser.get(getOwnerID()).getUUID();
return SteamwarUser.byId(getOwnerID()).getUUID();
}
public int getOwnerID() {
@@ -47,7 +47,7 @@ public class InfoCommand extends SWCommand {
@Register(description = "BAU_INFO_COMMAND_HELP")
public void genericCommand(Player p) {
BauSystem.MESSAGE.send("BAU_INFO_COMMAND_OWNER", p, SteamwarUser.get(bauServer.getOwnerID()).getUserName());
BauSystem.MESSAGE.send("BAU_INFO_COMMAND_OWNER", p, SteamwarUser.byId(bauServer.getOwnerID()).getUserName());
Region region = Region.getRegion(p.getLocation());
for (Flag flag : Flag.getFlags()) {
if (!region.getFlags().has(flag).isApplicable()) continue;
@@ -97,7 +97,7 @@ public class InfoCommand extends SWCommand {
st.append("§8, ");
}
st.append("§7");
st.append(SteamwarUser.get(bauweltMembers.get(i).getMemberID()).getUserName());
st.append(SteamwarUser.byId(bauweltMembers.get(i).getMemberID()).getUserName());
}
return st.toString();
}
@@ -31,7 +31,6 @@ import de.steamwar.command.SWCommand;
import de.steamwar.command.TypeMapper;
import de.steamwar.linkage.Linked;
import de.steamwar.linkage.LinkedInstance;
import de.steamwar.sql.BauweltMember;
import de.steamwar.sql.Punishment;
import de.steamwar.sql.SchematicNode;
import de.steamwar.sql.SteamwarUser;
@@ -198,7 +197,7 @@ public class TestblockCommand extends SWCommand {
@Override
public List<String> tabCompletes(CommandSender commandSender, PreviousArguments previousArguments, String s) {
List<String> stringList = new ArrayList<>(SchematicNode.getNodeTabcomplete(SteamwarUser.get(((Player) commandSender).getUniqueId()), s));
stringList.addAll(SchematicNode.getNodeTabcomplete(SteamwarUser.get(0), s));
stringList.addAll(SchematicNode.getNodeTabcomplete(SteamwarUser.byId(0), s));
return stringList;
}
@@ -206,7 +205,7 @@ public class TestblockCommand extends SWCommand {
public SchematicNode map(CommandSender commandSender, PreviousArguments previousArguments, String s) {
SchematicNode node = SchematicNode.getNodeFromPath(SteamwarUser.get(((Player) commandSender).getUniqueId()), s);
if (node == null) {
node = SchematicNode.getNodeFromPath(SteamwarUser.get(0), s);
node = SchematicNode.getNodeFromPath(SteamwarUser.byId(0), s);
}
return node;
}
@@ -38,7 +38,7 @@ public class ScriptHelper {
BookMeta meta = (BookMeta) itemStack.getItemMeta();
if(!writeable) {
meta.setTitle(script.getName());
meta.setAuthor(SteamwarUser.get(script.getUserId()).getUserName());
meta.setAuthor(SteamwarUser.byId(script.getUserId()).getUserName());
}
meta.setPages(getScriptPages(script));
itemStack.setItemMeta(meta);
@@ -89,7 +89,7 @@ public class StorageLib implements LuaLib, Enable, Disable {
jsonObject.keySet().forEach(key -> {
map.put(key, fromJson(jsonObject.get(key)));
});
SteamwarUser steamwarUser = SteamwarUser.get(Integer.parseInt(playerStorage.getName().substring(0, playerStorage.getName().length() - ".json".length())));
SteamwarUser steamwarUser = SteamwarUser.byId(Integer.parseInt(playerStorage.getName().substring(0, playerStorage.getName().length() - ".json".length())));
PLAYER_STORAGE.put(steamwarUser.getUUID(), map);
} catch (Exception e) {}
}
@@ -1,18 +1,20 @@
/*
* This file is a part of the SteamWar software.
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
* Copyright (C) 2025 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 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.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License along with this program.
* If not, see <https://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.simulator;
@@ -20,9 +22,7 @@ package de.steamwar.bausystem.features.simulator;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.SWUtils;
import de.steamwar.bausystem.features.simulator.data.Simulator;
import de.steamwar.bausystem.features.simulator.display.SimulatorCursor;
import de.steamwar.bausystem.features.simulator.execute.SimulatorExecutor;
import de.steamwar.bausystem.features.simulator.SimulatorCursorManager;
import de.steamwar.command.PreviousArguments;
import de.steamwar.command.SWCommand;
import de.steamwar.command.TypeMapper;
@@ -40,7 +40,7 @@ import java.util.Collection;
public class SimulatorCommand extends SWCommand {
@LinkedInstance
public SimulatorCursorManager cursorManager;
public SimulatorCursor simulatorCursor;
public SimulatorCommand() {
super("sim", "simulator");
@@ -49,12 +49,12 @@ public class SimulatorCommand extends SWCommand {
@Register(description = "SIMULATOR_HELP")
public void genericCommand(@Validator Player p) {
SWUtils.giveItemToPlayer(p, SimulatorStorage.getWand(p));
cursorManager.showCursor(p, null);
simulatorCursor.calcCursor(p);
}
@Register(value = "change", description = "SIMULATOR_CHANGE_HELP")
public void change(@Validator Player p) {
if (!SimulatorUtils.isSimulatorItem(p.getInventory().getItemInMainHand()) && !SimulatorUtils.isSimulatorItem(p.getInventory().getItemInOffHand())) {
if (!SimulatorCursor.isSimulatorItem(p.getInventory().getItemInMainHand()) && !SimulatorCursor.isSimulatorItem(p.getInventory().getItemInOffHand())) {
BauSystem.MESSAGE.send("SIMULATOR_NO_SIM_IN_HAND", p);
return;
}
@@ -0,0 +1,472 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.simulator;
import com.comphenix.tinyprotocol.TinyProtocol;
import de.steamwar.Reflection;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.Permission;
import de.steamwar.bausystem.SWUtils;
import de.steamwar.bausystem.features.simulator.data.Simulator;
import de.steamwar.bausystem.features.simulator.data.SimulatorElement;
import de.steamwar.bausystem.features.simulator.data.SimulatorGroup;
import de.steamwar.bausystem.features.simulator.data.observer.ObserverElement;
import de.steamwar.bausystem.features.simulator.data.observer.ObserverPhase;
import de.steamwar.bausystem.features.simulator.data.redstone.RedstoneElement;
import de.steamwar.bausystem.features.simulator.data.redstone.RedstonePhase;
import de.steamwar.bausystem.features.simulator.data.tnt.TNTElement;
import de.steamwar.bausystem.features.simulator.data.tnt.TNTPhase;
import de.steamwar.bausystem.features.simulator.execute.SimulatorExecutor;
import de.steamwar.bausystem.features.simulator.gui.SimulatorGroupGui;
import de.steamwar.bausystem.features.simulator.gui.SimulatorGui;
import de.steamwar.bausystem.features.simulator.gui.base.SimulatorBaseGui;
import de.steamwar.bausystem.utils.BauMemberUpdateEvent;
import de.steamwar.bausystem.utils.ItemUtils;
import de.steamwar.bausystem.utils.RayTraceUtils;
import de.steamwar.entity.REntity;
import de.steamwar.entity.REntityServer;
import de.steamwar.entity.RFallingBlockEntity;
import de.steamwar.inventory.SWAnvilInv;
import de.steamwar.linkage.Linked;
import de.steamwar.linkage.MinVersion;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Player;
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.player.*;
import org.bukkit.inventory.ItemStack;
import org.bukkit.util.Vector;
import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collectors;
@Linked
@MinVersion(19)
public class SimulatorCursor implements Listener {
private static final World WORLD = Bukkit.getWorlds().get(0);
private Class<?> position = Reflection.getClass("net.minecraft.network.protocol.game.ServerboundMovePlayerPacket$Pos");
private Class<?> look = Reflection.getClass("net.minecraft.network.protocol.game.ServerboundMovePlayerPacket$Rot");
private Class<?> positionLook = Reflection.getClass("net.minecraft.network.protocol.game.ServerboundMovePlayerPacket$PosRot");
private static Map<Player, CursorType> cursorType = Collections.synchronizedMap(new HashMap<>());
private static Map<Player, REntityServer> cursors = Collections.synchronizedMap(new HashMap<>());
private static final Set<Player> calculating = new HashSet<>();
public static boolean isSimulatorItem(ItemStack itemStack) {
return ItemUtils.isItem(itemStack, "simulator");
}
public SimulatorCursor() {
BiFunction<Player, Object, Object> function = (player, object) -> {
calcCursor(player);
return object;
};
TinyProtocol.instance.addFilter(position, function);
TinyProtocol.instance.addFilter(look, function);
TinyProtocol.instance.addFilter(positionLook, function);
}
@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
if (!Permission.BUILD.hasPermission(event.getPlayer())) return;
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> {
calcCursor(event.getPlayer());
}, 0);
}
@EventHandler
public void onPlayerDropItem(PlayerDropItemEvent event) {
if (!Permission.BUILD.hasPermission(event.getPlayer())) return;
calcCursor(event.getPlayer());
}
@EventHandler
public void onPlayerItemHeld(PlayerItemHeldEvent event) {
if (!Permission.BUILD.hasPermission(event.getPlayer())) return;
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> {
calcCursor(event.getPlayer());
}, 1);
}
@EventHandler
public void onBauMemberUpdate(BauMemberUpdateEvent event) {
event.getChanged().forEach(SimulatorCursor::calcCursor);
}
@EventHandler
public void onPlayerQuit(PlayerQuitEvent event) {
cursorType.remove(event.getPlayer());
cursors.remove(event.getPlayer());
synchronized (calculating) {
calculating.remove(event.getPlayer());
}
}
private static final Map<Player, Long> LAST_SNEAKS = new HashMap<>();
static {
Bukkit.getScheduler().runTaskTimer(BauSystem.getInstance(), () -> {
long millis = System.currentTimeMillis();
LAST_SNEAKS.entrySet().removeIf(entry -> millis - entry.getValue() > 200);
}, 1, 1);
}
@EventHandler(priority = EventPriority.HIGH)
public void onPlayerToggleSneak(PlayerToggleSneakEvent event) {
if (!event.isSneaking()) return;
Player player = event.getPlayer();
if (!isSimulatorItem(player.getInventory().getItemInMainHand()) && !isSimulatorItem(player.getInventory().getItemInOffHand())) {
return;
}
if (LAST_SNEAKS.containsKey(player)) {
CursorType currentType = cursorType.getOrDefault(player, CursorType.TNT);
if (currentType == CursorType.TNT) {
cursorType.put(player, CursorType.REDSTONE_BLOCK);
} else {
cursorType.put(player, CursorType.TNT);
}
calcCursor(player);
} else {
LAST_SNEAKS.put(player, System.currentTimeMillis());
}
}
public static CursorType getCursorType(Player player) {
return cursorType.getOrDefault(player, CursorType.TNT);
}
public static void setCursorType(Player player, CursorType cursorType) {
SimulatorCursor.cursorType.put(player, cursorType);
calcCursor(player);
}
public static void calcCursor(Player player) {
synchronized (calculating) {
if (calculating.contains(player)) return;
calculating.add(player);
}
if (!Permission.BUILD.hasPermission(player) || (!isSimulatorItem(player.getInventory().getItemInMainHand()) && !isSimulatorItem(player.getInventory().getItemInOffHand()))) {
if (removeCursor(player) || SimulatorWatcher.show(null, player)) {
SWUtils.sendToActionbar(player, "");
}
synchronized (calculating) {
calculating.remove(player);
}
return;
}
Simulator simulator = SimulatorStorage.getSimulator(player);
if (simulator != null && simulator.getStabGenerator() != null) {
removeCursor(player);
SimulatorWatcher.show(null, player);
SWUtils.sendToActionbar(player, "§cGenerating Stab");
synchronized (calculating) {
calculating.remove(player);
}
return;
}
SimulatorWatcher.show(simulator, player);
List<REntity> entities = SimulatorWatcher.getEntitiesOfSimulator(simulator);
RayTraceUtils.RRayTraceResult rayTraceResult = RayTraceUtils.traceREntity(player, player.getLocation(), entities);
if (rayTraceResult == null) {
removeCursor(player);
if (simulator == null) {
SWUtils.sendToActionbar(player, "§eSelect Simulator");
} else {
SWUtils.sendToActionbar(player, "§eOpen Simulator");
}
synchronized (calculating) {
calculating.remove(player);
}
return;
}
showCursor(player, rayTraceResult, simulator != null);
synchronized (calculating) {
calculating.remove(player);
}
}
private static synchronized boolean removeCursor(Player player) {
REntityServer entityServer = cursors.get(player);
boolean hadCursor = entityServer != null && !entityServer.getEntities().isEmpty();
if (entityServer != null) {
entityServer.getEntities().forEach(REntity::die);
}
return hadCursor;
}
private static synchronized void showCursor(Player player, RayTraceUtils.RRayTraceResult rayTraceResult, boolean hasSimulatorSelected) {
REntityServer entityServer = cursors.computeIfAbsent(player, __ -> {
REntityServer rEntityServer = new REntityServer();
rEntityServer.addPlayer(player);
return rEntityServer;
});
CursorType type = cursorType.getOrDefault(player, CursorType.TNT);
REntity hitEntity = rayTraceResult.getHitEntity();
Location location = hitEntity != null ? new Vector(hitEntity.getX(), hitEntity.getY(), hitEntity.getZ()).toLocation(WORLD) :
type.position.apply(player, rayTraceResult).toLocation(WORLD);
Material material = hitEntity != null ? Material.GLASS : type.getMaterial();
List<RFallingBlockEntity> entities = entityServer.getEntitiesByType(RFallingBlockEntity.class);
entities.removeIf(rFallingBlockEntity -> {
if (rFallingBlockEntity.getMaterial() != material) {
rFallingBlockEntity.die();
return true;
}
rFallingBlockEntity.move(location);
return false;
});
if (entities.isEmpty()) {
RFallingBlockEntity rFallingBlockEntity = new RFallingBlockEntity(entityServer, location, material);
rFallingBlockEntity.setNoGravity(true);
if (material == Material.GLASS) {
rFallingBlockEntity.setGlowing(true);
}
}
if (hasSimulatorSelected) {
if (hitEntity != null) {
SWUtils.sendToActionbar(player, "§eEdit Position");
} else {
SWUtils.sendToActionbar(player, "§eAdd new " + type.name);
}
} else {
SWUtils.sendToActionbar(player, "§eCreate new Simulator");
}
}
public static Vector getPosFree(Player player, RayTraceUtils.RRayTraceResult result) {
Vector pos = result.getHitPosition();
BlockFace face = result.getHitBlockFace();
if (face != null) {
switch (face) {
case DOWN:
pos.setY(pos.getY() - 0.98);
break;
case EAST:
pos.setX(pos.getX() + 0.49);
break;
case WEST:
pos.setX(pos.getX() - 0.49);
break;
case NORTH:
pos.setZ(pos.getZ() - 0.49);
break;
case SOUTH:
pos.setZ(pos.getZ() + 0.49);
break;
default:
break;
}
if (face.getModY() == 0 && player.isSneaking()) {
pos.setY(pos.getY() - 0.49);
}
}
if (!player.isSneaking()) {
pos.setX(pos.getBlockX() + 0.5);
if (face == null || face.getModY() == 0)
pos.setY(pos.getBlockY() + 0.0);
pos.setZ(pos.getBlockZ() + 0.5);
}
return pos;
}
private static Vector getPosBlockAligned(Player player, RayTraceUtils.RRayTraceResult result) {
Vector pos = result.getHitPosition();
BlockFace face = result.getHitBlockFace();
if (face != null) {
switch (face) {
case DOWN:
pos.setY(pos.getY() - 0.98);
break;
case EAST:
pos.setX(pos.getX() + 0.49);
break;
case WEST:
pos.setX(pos.getX() - 0.49);
break;
case NORTH:
pos.setZ(pos.getZ() - 0.49);
break;
case SOUTH:
pos.setZ(pos.getZ() + 0.49);
break;
default:
break;
}
}
pos.setX(pos.getBlockX() + 0.5);
if (pos.getY() - pos.getBlockY() != 0 && face == BlockFace.UP) {
pos.setY(pos.getBlockY() + 1.0);
} else {
pos.setY(pos.getBlockY());
}
pos.setZ(pos.getBlockZ() + 0.5);
return pos;
}
@Getter
@AllArgsConstructor
public enum CursorType {
TNT(Material.TNT, Material.GUNPOWDER, SimulatorCursor::getPosFree, "TNT", vector -> new TNTElement(vector).add(new TNTPhase())),
REDSTONE_BLOCK(Material.REDSTONE_BLOCK, Material.REDSTONE, SimulatorCursor::getPosBlockAligned, "Redstone Block", vector -> new RedstoneElement(vector).add(new RedstonePhase())),
OBSERVER(Material.OBSERVER, Material.QUARTZ, SimulatorCursor::getPosBlockAligned, "Observer", vector -> new ObserverElement(vector).add(new ObserverPhase())),
;
public final Material material;
public final Material nonSelectedMaterial;
public final BiFunction<Player, RayTraceUtils.RRayTraceResult, Vector> position;
public final String name;
public final Function<Vector, SimulatorElement<?>> elementFunction;
}
@EventHandler
public void onPlayerInteract(PlayerInteractEvent event) {
if (!Permission.BUILD.hasPermission(event.getPlayer())) return;
if (!ItemUtils.isItem(event.getItem(), "simulator")) {
return;
}
event.setCancelled(true);
Player player = event.getPlayer();
Simulator simulator = SimulatorStorage.getSimulator(player);
if (event.getAction() == Action.LEFT_CLICK_BLOCK || event.getAction() == Action.LEFT_CLICK_AIR) {
if (simulator == null) {
return;
}
SimulatorExecutor.run(event.getPlayer(), simulator, null);
return;
}
if (event.getAction() != Action.RIGHT_CLICK_BLOCK && event.getAction() != Action.RIGHT_CLICK_AIR) {
return;
}
RayTraceUtils.RRayTraceResult rayTraceResult = RayTraceUtils.traceREntity(player, player.getLocation(), SimulatorWatcher.getEntitiesOfSimulator(simulator));
if (simulator == null) {
if (rayTraceResult == null) {
SimulatorStorage.openSimulatorSelector(player);
} else {
SWAnvilInv anvilInv = new SWAnvilInv(player, "Name");
anvilInv.setCallback(s -> {
Simulator sim = SimulatorStorage.getSimulator(s);
if (sim != null) {
BauSystem.MESSAGE.send("SIMULATOR_NAME_ALREADY_EXISTS", player);
return;
}
if (!s.matches("[a-zA-Z_0-9-]+")) {
BauSystem.MESSAGE.send("SIMULATOR_NAME_INVALID", player);
return;
}
sim = new Simulator(s);
SimulatorStorage.addSimulator(s, sim);
createElement(player, rayTraceResult, sim);
SimulatorStorage.setSimulator(player, sim);
});
anvilInv.open();
}
return;
}
if (rayTraceResult == null) {
new SimulatorGui(player, simulator).open();
return;
}
if (rayTraceResult.getHitEntity() != null) {
REntity hitEntity = rayTraceResult.getHitEntity();
Vector vector = new Vector(hitEntity.getX(), hitEntity.getY(), hitEntity.getZ());
List<SimulatorElement<?>> elements = simulator.getGroups().stream().map(SimulatorGroup::getElements).flatMap(List::stream).filter(element -> {
return element.getWorldPos().distanceSquared(vector) < (1 / 16.0) * (1 / 16.0);
}).collect(Collectors.toList());
switch (elements.size()) {
case 0:
return;
case 1:
// Open single element present in Simulator
SimulatorElement<?> element = elements.get(0);
SimulatorGroup group1 = element.getGroup(simulator);
SimulatorBaseGui back = new SimulatorGui(player, simulator);
if (group1.getElements().size() > 1) {
back = new SimulatorGroupGui(player, simulator, group1, back);
}
element.open(player, simulator, group1, back);
break;
default:
List<SimulatorGroup> parents = elements.stream().map(e -> e.getGroup(simulator)).distinct().collect(Collectors.toList());
if (parents.size() == 1) {
// Open multi element present in Simulator in existing group
SimulatorGui simulatorGui = new SimulatorGui(player, simulator);
new SimulatorGroupGui(player, simulator, parents.get(0), simulatorGui).open();
} else {
// Open multi element present in Simulator in implicit group
SimulatorGroup group2 = new SimulatorGroup();
group2.setMaterial(null);
group2.getElements().addAll(elements);
SimulatorGui simulatorGui = new SimulatorGui(player, simulator);
new SimulatorGroupGui(player, simulator, group2, simulatorGui).open();
}
break;
}
return;
}
// Add new Element to current simulator
createElement(player, rayTraceResult, simulator);
}
private void createElement(Player player, RayTraceUtils.RRayTraceResult rayTraceResult, Simulator simulator) {
CursorType type = cursorType.getOrDefault(player, CursorType.TNT);
Vector vector = type.position.apply(player, rayTraceResult);
if (type == CursorType.REDSTONE_BLOCK) {
vector.subtract(new Vector(0.5, 0, 0.5));
}
SimulatorElement<?> element = type.elementFunction.apply(vector);
SimulatorGroup group = new SimulatorGroup().add(element);
simulator.getGroups().add(group);
SimulatorGui simulatorGui = new SimulatorGui(player, simulator);
element.open(player, simulator, group, simulatorGui);
SimulatorWatcher.update(simulator);
calcCursor(player);
}
}
@@ -1,103 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify it under the terms of the
* GNU Affero General Public License as published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License along with this program.
* If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.simulator;
import de.steamwar.bausystem.features.simulator.data.Simulator;
import de.steamwar.bausystem.features.simulator.display.ASimulatorCursor;
import de.steamwar.bausystem.features.simulator.display.EmptySimulatorCursor;
import de.steamwar.bausystem.features.simulator.display.SimulatorCursor;
import de.steamwar.bausystem.features.simulator.display.SimulatorCursorMode;
import de.steamwar.linkage.Linked;
import de.steamwar.linkage.MinVersion;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.*;
import org.bukkit.inventory.ItemStack;
import java.util.*;
// TODO fix memory leak when players leave the server
// TODO fix cursor not being hidden when player deequips simulator item
@Linked
@MinVersion(19)
public class SimulatorCursorManager implements Listener {
public static final SimulatorCursorManager INSTANCE = new SimulatorCursorManager();
private final Map<Player, Map<Simulator, ASimulatorCursor>> openCursorsByPlayerBySimulator = new HashMap<>();
private final Map<Player, ASimulatorCursor> activeCursorByPlayer = new HashMap<>();
@EventHandler
public void onPlayerItemEquip(PlayerItemHeldEvent event) {
ItemStack newItem = event.getPlayer().getInventory().getItem(event.getNewSlot());
if (SimulatorUtils.isSimulatorItem(newItem)) {
Simulator simulator = SimulatorStorage.getSimulator(newItem);
showCursor(event.getPlayer(), simulator);
}
}
/**
* Shows the cursor for the given simulator to the given player. Shows an empty cursor if the
* simulator is null.
*/
public void showCursor(Player player, Simulator simulator) {
var currentActiveCursor = activeCursorByPlayer.get(player);
if (currentActiveCursor != null) {
currentActiveCursor.hide();
}
var cursorMode = currentActiveCursor != null ? currentActiveCursor.getCursorMode() : SimulatorCursorMode.TNT;
var cursorsBySimulator = openCursorsByPlayerBySimulator.computeIfAbsent(player, __ -> new HashMap<>());
var cursor = cursorsBySimulator.get(simulator);
if (cursor == null) {
if (simulator == null) {
ASimulatorCursor emptyCursor = new EmptySimulatorCursor(player, cursorMode);
cursorsBySimulator.put(simulator, emptyCursor);
cursor = emptyCursor;
} else {
ASimulatorCursor newCursor = new SimulatorCursor(simulator, player, cursorMode);
cursorsBySimulator.put(simulator, newCursor);
cursor = newCursor;
}
}
cursor.show();
}
public Optional<SimulatorCursorMode> getActiveCursorMode(Player player) {
var currentActiveCursor = activeCursorByPlayer.get(player);
if (currentActiveCursor != null) {
return Optional.of(currentActiveCursor.getCursorMode());
} else {
return Optional.empty();
}
}
public void setActiveCursorMode(Player player, SimulatorCursorMode mode) {
var currentActiveCursor = activeCursorByPlayer.get(player);
if (currentActiveCursor != null) {
currentActiveCursor.setCursorMode(mode);
}
}
}
@@ -1,18 +1,20 @@
/*
* This file is a part of the SteamWar software.
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
* Copyright (C) 2025 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 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.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License along with this program.
* If not, see <https://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.simulator;
@@ -54,13 +56,12 @@ public class SimulatorStorage implements Enable {
public static Simulator getSimulator(Player player) {
Simulator simulator = getSimulator(player.getInventory().getItemInMainHand());
if (simulator != null)
return simulator;
if (simulator != null) return simulator;
return getSimulator(player.getInventory().getItemInOffHand());
}
public static Simulator getSimulator(ItemStack itemStack) {
if (!SimulatorUtils.isSimulatorItem(itemStack)) {
if (!SimulatorCursor.isSimulatorItem(itemStack)) {
return null;
}
String selection = ItemUtils.getTag(itemStack, simulatorSelection);
@@ -85,11 +86,11 @@ public class SimulatorStorage implements Enable {
YAPIONFormatSimulatorLoader yapionFormatSimulatorLoader = new YAPIONFormatSimulatorLoader();
File[] files = simulatorsDir.listFiles();
if (files == null)
return;
if (files == null) return;
for (File file : files) {
try {
List<Simulator> simulators = simFormatSimulatorLoader.load(file).orElse(null);
List<Simulator> simulators = simFormatSimulatorLoader.load(file)
.orElse(null);
if (simulators != null) {
simulators.forEach(simulator -> {
simulatorMap.put(simulator.getName(), simulator);
@@ -101,7 +102,8 @@ public class SimulatorStorage implements Enable {
}
try {
List<Simulator> simulators = simulatorFormatSimulatorLoader.load(file).orElse(null);
List<Simulator> simulators = simulatorFormatSimulatorLoader.load(file)
.orElse(null);
if (simulators != null) {
simulators.forEach(simulator -> {
simulatorMap.put(simulator.getName(), simulator);
@@ -114,7 +116,8 @@ public class SimulatorStorage implements Enable {
}
try {
List<Simulator> simulators = yapionFormatSimulatorLoader.load(file).orElse(null);
List<Simulator> simulators = yapionFormatSimulatorLoader.load(file)
.orElse(null);
if (simulators != null) {
simulators.forEach(simulator -> {
simulatorMap.put(simulator.getName(), simulator);
@@ -128,8 +131,7 @@ public class SimulatorStorage implements Enable {
}
public static void openSimulatorSelector(Player player) {
SimulatorPageGui<Simulator> simulatorPageGui = new SimulatorPageGui<Simulator>(player, null, 6 * 9,
simulatorMap.values().stream().sorted(Comparator.comparing(Simulator::getName)).collect(Collectors.toList())) {
SimulatorPageGui<Simulator> simulatorPageGui = new SimulatorPageGui<Simulator>(player, null, 6 * 9, simulatorMap.values().stream().sorted(Comparator.comparing(Simulator::getName)).collect(Collectors.toList())) {
@Override
public String baseTitle() {
return "Simulators";
@@ -169,11 +171,7 @@ public class SimulatorStorage implements Enable {
}
public static ItemStack getWand(Player p) {
ItemStack itemStack = new SWItem(Material.BLAZE_ROD, BauSystem.MESSAGE.parse("SIMULATOR_WAND_NAME", p),
Arrays.asList(BauSystem.MESSAGE.parse("SIMULATOR_WAND_LORE_1", p), BauSystem.MESSAGE.parse("SIMULATOR_WAND_LORE_2", p),
BauSystem.MESSAGE.parse("SIMULATOR_WAND_LORE_3", p), BauSystem.MESSAGE.parse("SIMULATOR_WAND_LORE_4", p),
BauSystem.MESSAGE.parse("SIMULATOR_WAND_LORE_5", p)),
false, null).getItemStack();
ItemStack itemStack = new SWItem(Material.BLAZE_ROD, BauSystem.MESSAGE.parse("SIMULATOR_WAND_NAME", p), Arrays.asList(BauSystem.MESSAGE.parse("SIMULATOR_WAND_LORE_1", p), BauSystem.MESSAGE.parse("SIMULATOR_WAND_LORE_2", p), BauSystem.MESSAGE.parse("SIMULATOR_WAND_LORE_3", p), BauSystem.MESSAGE.parse("SIMULATOR_WAND_LORE_4", p), BauSystem.MESSAGE.parse("SIMULATOR_WAND_LORE_5", p)), false, null).getItemStack();
ItemMeta itemMeta = itemStack.getItemMeta();
itemMeta.setCustomModelData(1);
itemStack.setItemMeta(itemMeta);
@@ -185,9 +183,9 @@ public class SimulatorStorage implements Enable {
ItemStack mainHand = player.getInventory().getItemInMainHand();
ItemStack offHand = player.getInventory().getItemInOffHand();
ItemStack itemStack;
if (SimulatorUtils.isSimulatorItem(mainHand)) {
if (SimulatorCursor.isSimulatorItem(mainHand)) {
itemStack = mainHand;
} else if (SimulatorUtils.isSimulatorItem(offHand)) {
} else if (SimulatorCursor.isSimulatorItem(offHand)) {
itemStack = offHand;
} else {
itemStack = null;
@@ -1,12 +0,0 @@
package de.steamwar.bausystem.features.simulator;
import org.bukkit.inventory.ItemStack;
import de.steamwar.bausystem.utils.ItemUtils;
import lombok.experimental.UtilityClass;
@UtilityClass
public class SimulatorUtils {
public static boolean isSimulatorItem(ItemStack itemStack) {
return ItemUtils.isItem(itemStack, "simulator");
}
}
@@ -0,0 +1,129 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.simulator;
import de.steamwar.bausystem.features.simulator.data.Simulator;
import de.steamwar.bausystem.features.simulator.data.SimulatorElement;
import de.steamwar.bausystem.features.simulator.data.SimulatorGroup;
import de.steamwar.bausystem.features.simulator.storage.SimulatorSaver;
import de.steamwar.bausystem.shared.Pair;
import de.steamwar.entity.REntity;
import de.steamwar.entity.REntityServer;
import de.steamwar.entity.RFallingBlockEntity;
import de.steamwar.linkage.Linked;
import de.steamwar.linkage.MinVersion;
import lombok.experimental.UtilityClass;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.util.Vector;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
@UtilityClass
public class SimulatorWatcher {
private final World WORLD = Bukkit.getWorlds().get(0);
private Map<Simulator, REntityServer> entityServers = new HashMap<>();
private Map<Player, Pair<Simulator, Runnable>> watchers = new HashMap<>();
public void watch(Player player, Simulator simulator, Runnable watcher) {
if (simulator == null || watcher == null) {
watchers.remove(player);
} else {
watchers.put(player, new Pair<>(simulator, watcher));
}
}
public synchronized void update(Simulator simulator) {
REntityServer rEntityServer = entityServers.get(simulator);
if (rEntityServer != null) {
rEntityServer.getEntities().forEach(REntity::die);
createSim(rEntityServer, simulator);
}
new ArrayList<>(watchers.values()).forEach(simulatorRunnablePair -> {
if (simulatorRunnablePair.getKey() == simulator) {
simulatorRunnablePair.getValue().run();
}
});
SimulatorSaver.saveSimulator(SimulatorStorage.simulatorsDir, simulator);
}
@Linked
@MinVersion(19)
public static class QuitListener implements Listener {
@EventHandler
public void onPlayerQuit(PlayerQuitEvent event) {
watchers.remove(event.getPlayer());
show(null, event.getPlayer());
}
}
private REntityServer createSim(REntityServer server, Simulator simulator) {
if (simulator == null) {
return null;
}
Map<Vector, Set<Class<?>>> positionCache = new HashMap<>();
simulator.getGroups().stream().map(group -> group.getElements().stream().map(element -> new Pair<>(group, element)).collect(Collectors.toList())).flatMap(List::stream).forEach(pair -> {
SimulatorGroup group = pair.getKey();
SimulatorElement<?> element = pair.getValue();
boolean wasNotPresent = positionCache.computeIfAbsent(element.getPosition(), __ -> new HashSet<>())
.add(element.getClass());
if (!wasNotPresent) return;
Material material = group.isDisabled() || element.isDisabled() ? element.getWorldDisabledMaterial() : element.getWorldMaterial();
Location location = element.getWorldPos().toLocation(WORLD);
RFallingBlockEntity rFallingBlockEntity = new RFallingBlockEntity(server, location, material);
rFallingBlockEntity.setNoGravity(true);
});
return server;
}
public synchronized boolean show(Simulator sim, Player player) {
AtomicBoolean removed = new AtomicBoolean();
entityServers.forEach((simulator, rEntityServer) -> {
if (rEntityServer == null) return;
if (rEntityServer.getPlayers().contains(player) && sim != simulator) {
rEntityServer.removePlayer(player);
removed.set(true);
}
});
if (sim == null) return removed.get();
entityServers.computeIfAbsent(sim, __ -> createSim(new REntityServer(), sim)).addPlayer(player);
return removed.get();
}
synchronized List<REntity> getEntitiesOfSimulator(Simulator simulator) {
REntityServer entityServer = entityServers.get(simulator);
if (entityServer == null) {
return Collections.emptyList();
}
return entityServer.getEntities();
}
}
@@ -1,54 +0,0 @@
package de.steamwar.bausystem.features.simulator.display;
import java.util.List;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerToggleSneakEvent;
import de.steamwar.bausystem.utils.cursor.Cursor;
import de.steamwar.entity.REntityServer;
import lombok.Getter;
public abstract class ASimulatorCursor extends Cursor implements Listener {
protected final Player owner;
@Getter
protected SimulatorCursorMode cursorMode;
protected ASimulatorCursor(Player owner, REntityServer targetServer, SimulatorCursorMode cursorMode) {
super(targetServer, owner, Material.GLASS, Material.TNT, List.of(Cursor.CursorMode.FREE, Cursor.CursorMode.BLOCK_ALIGNED));
this.cursorMode = cursorMode;
this.owner = owner;
}
public void swapCursorMode() {
cursorMode = cursorMode.switchType();
setCursorMaterial(cursorMode.getMaterial());
setAllowedCursorModes(cursorMode.getAllowedCursorModes());
}
public void setCursorMode(SimulatorCursorMode mode) {
this.cursorMode = mode;
setCursorMaterial(cursorMode.getMaterial());
setAllowedCursorModes(cursorMode.getAllowedCursorModes());
}
public void hide() {
super.hide();
super.getTargetServer().removePlayer(owner);
}
public void show() {
super.show();
super.getTargetServer().addPlayer(owner);
}
@EventHandler
public void onPlayerShift(PlayerToggleSneakEvent event) {
if (event.getPlayer() != owner) {
return;
}
swapCursorMode();
}
}
@@ -1,47 +0,0 @@
package de.steamwar.bausystem.features.simulator.display;
import java.util.Optional;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.block.Action;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.features.simulator.SimulatorStorage;
import de.steamwar.bausystem.features.simulator.data.Simulator;
import de.steamwar.bausystem.features.simulator.data.SimulatorElement;
import de.steamwar.bausystem.features.simulator.data.SimulatorGroup;
import de.steamwar.entity.REntityServer;
import de.steamwar.inventory.SWAnvilInv;
public class EmptySimulatorCursor extends ASimulatorCursor {
public EmptySimulatorCursor(Player owner, SimulatorCursorMode cursorMode) {
super(owner, new REntityServer(), cursorMode);
}
@Override
public void onClick(Optional<Location> clickedLocation, boolean clickedOnEntity, Action clickAction) {
if (clickAction == Action.RIGHT_CLICK_AIR) {
SimulatorStorage.openSimulatorSelector(owner);
} else if (clickAction == Action.RIGHT_CLICK_BLOCK) {
SWAnvilInv anvilInv = new SWAnvilInv(owner, "Name");
anvilInv.setCallback(name -> {
Simulator sim = SimulatorStorage.getSimulator(name);
if (sim != null) {
BauSystem.MESSAGE.send("SIMULATOR_NAME_ALREADY_EXISTS", owner);
return;
}
if (!name.matches("[a-zA-Z_0-9-]+")) {
BauSystem.MESSAGE.send("SIMULATOR_NAME_INVALID", owner);
return;
}
sim = new Simulator(name);
SimulatorStorage.addSimulator(name, sim);
SimulatorElement<?> element = cursorMode.getElementFunction().apply(clickedLocation.get().toVector());
SimulatorGroup group = new SimulatorGroup();
group.add(element);
sim.add(group);
SimulatorStorage.setSimulator(owner, sim);
});
anvilInv.open();
}
}
}
@@ -1,69 +0,0 @@
package de.steamwar.bausystem.features.simulator.display;
import java.util.List;
import java.util.Optional;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.block.Action;
import org.bukkit.util.Vector;
import de.steamwar.bausystem.features.simulator.data.Simulator;
import de.steamwar.bausystem.features.simulator.data.SimulatorElement;
import de.steamwar.bausystem.features.simulator.data.SimulatorGroup;
import de.steamwar.bausystem.features.simulator.execute.SimulatorExecutor;
import de.steamwar.bausystem.features.simulator.gui.SimulatorGroupGui;
import de.steamwar.bausystem.features.simulator.gui.SimulatorGui;
import de.steamwar.bausystem.features.simulator.gui.base.SimulatorBaseGui;
public class SimulatorCursor extends ASimulatorCursor {
private final Simulator simulator;
public SimulatorCursor(Simulator simulator, Player owner, SimulatorCursorMode cursorMode) {
super(owner, SimulatorRenderer.renderSimulator(simulator), cursorMode);
this.simulator = simulator;
}
@Override
public void onClick(Optional<Location> clickedLocation, boolean clickedOnEntity, Action clickAction) {
if (clickAction == Action.LEFT_CLICK_AIR || clickAction == Action.LEFT_CLICK_BLOCK) {
SimulatorExecutor.run(owner, simulator, null);
} else if (!clickedOnEntity || clickedLocation.isEmpty()) {
new SimulatorGui(owner, simulator);
} else {
Vector vector = clickedLocation.get().toVector();
List<SimulatorElement<?>> elements = simulator.getGroups().stream().map(SimulatorGroup::getElements).flatMap(List::stream)
.filter(element -> element.getWorldPos().distanceSquared(vector) < (1 / 16.0) * (1 / 16.0)).toList();
switch (elements.size()) {
case 0:
return;
case 1:
// Open single element present in Simulator
SimulatorElement<?> element = elements.get(0);
SimulatorGroup group1 = element.getGroup(simulator);
SimulatorBaseGui back = new SimulatorGui(owner, simulator);
if (group1.getElements().size() > 1) {
back = new SimulatorGroupGui(owner, simulator, group1, back);
}
element.open(owner, simulator, group1, back);
break;
default:
List<SimulatorGroup> parents = elements.stream().map(e -> e.getGroup(simulator)).distinct().toList();
if (parents.size() == 1) {
// Open multi element present in Simulator in existing group
SimulatorGui simulatorGui = new SimulatorGui(owner, simulator);
new SimulatorGroupGui(owner, simulator, parents.get(0), simulatorGui).open();
} else {
// Open multi element present in Simulator in implicit group
SimulatorGroup group2 = new SimulatorGroup();
group2.setMaterial(null);
group2.getElements().addAll(elements);
SimulatorGui simulatorGui = new SimulatorGui(owner, simulator);
new SimulatorGroupGui(owner, simulator, group2, simulatorGui).open();
}
break;
}
}
}
}
@@ -1,41 +0,0 @@
package de.steamwar.bausystem.features.simulator.display;
import java.util.List;
import java.util.function.Function;
import org.bukkit.Material;
import org.bukkit.util.Vector;
import de.steamwar.bausystem.features.simulator.data.SimulatorElement;
import de.steamwar.bausystem.features.simulator.data.observer.ObserverElement;
import de.steamwar.bausystem.features.simulator.data.observer.ObserverPhase;
import de.steamwar.bausystem.features.simulator.data.redstone.RedstoneElement;
import de.steamwar.bausystem.features.simulator.data.redstone.RedstonePhase;
import de.steamwar.bausystem.features.simulator.data.tnt.TNTElement;
import de.steamwar.bausystem.features.simulator.data.tnt.TNTPhase;
import de.steamwar.bausystem.utils.cursor.Cursor.CursorMode;
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
@Getter
public enum SimulatorCursorMode {
TNT(Material.TNT, Material.GUNPOWDER, "TNT", vector -> new TNTElement(vector).add(new TNTPhase()),
List.of(CursorMode.FREE, CursorMode.BLOCK_ALIGNED)), REDSTONE_BLOCK(Material.REDSTONE_BLOCK, Material.REDSTONE_WIRE, "Redstone Block",
vector -> new RedstoneElement(vector).add(new RedstonePhase()), List.of(CursorMode.BLOCK_ALIGNED)), OBSERVER(Material.OBSERVER, Material.QUARTZ,
"Observer", vector -> new ObserverElement(vector).add(new ObserverPhase()), List.of(CursorMode.BLOCK_ALIGNED)),;
public final Material material;
public final Material nonSelectedMaterial;
public final String name;
public final Function<Vector, SimulatorElement<?>> elementFunction;
public final List<CursorMode> allowedCursorModes;
public SimulatorCursorMode switchType() {
if (this == TNT) {
return REDSTONE_BLOCK;
}
if (this == REDSTONE_BLOCK) {
return OBSERVER;
}
return TNT;
}
}
@@ -1,78 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify it under the terms of the
* GNU Affero General Public License as published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License along with this program.
* If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.simulator.display;
import de.steamwar.bausystem.features.simulator.SimulatorStorage;
import de.steamwar.bausystem.features.simulator.data.Simulator;
import de.steamwar.bausystem.features.simulator.data.SimulatorElement;
import de.steamwar.bausystem.features.simulator.data.SimulatorGroup;
import de.steamwar.bausystem.features.simulator.storage.SimulatorSaver;
import de.steamwar.bausystem.shared.Pair;
import de.steamwar.entity.REntity;
import de.steamwar.entity.REntityServer;
import de.steamwar.entity.RFallingBlockEntity;
import lombok.experimental.UtilityClass;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.event.Listener;
import org.bukkit.util.Vector;
import java.util.*;
import java.util.stream.Collectors;
@UtilityClass
public class SimulatorRenderer implements Listener {
private final World WORLD = Bukkit.getWorlds().get(0);
private Map<Simulator, REntityServer> entityServers = new HashMap<>();
public synchronized void update(Simulator simulator) {
renderSimulator(simulator);
SimulatorSaver.saveSimulator(SimulatorStorage.simulatorsDir, simulator);
}
public REntityServer renderSimulator(Simulator simulator) {
if (simulator == null) {
return null;
}
REntityServer server = entityServers.computeIfAbsent(simulator, __ -> new REntityServer());
server.getEntities().forEach(REntity::die);
Map<Vector, Set<Class<?>>> positionCache = new HashMap<>();
simulator.getGroups().stream().map(group -> group.getElements().stream().map(element -> new Pair<>(group, element)).toList()).flatMap(List::stream)
.forEach(pair -> {
SimulatorGroup group = pair.getKey();
SimulatorElement<?> element = pair.getValue();
boolean wasNotPresent = positionCache.computeIfAbsent(element.getPosition(), __ -> new HashSet<>()).add(element.getClass());
if (!wasNotPresent)
return;
Material material = group.isDisabled() || element.isDisabled() ? element.getWorldDisabledMaterial() : element.getWorldMaterial();
Location location = element.getWorldPos().toLocation(WORLD);
RFallingBlockEntity rFallingBlockEntity = new RFallingBlockEntity(server, location, material);
rFallingBlockEntity.setNoGravity(true);
});
return server;
}
}
@@ -20,7 +20,7 @@
package de.steamwar.bausystem.features.simulator.execute;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.features.simulator.display.SimulatorRenderer;
import de.steamwar.bausystem.features.simulator.SimulatorWatcher;
import de.steamwar.bausystem.utils.bossbar.BauSystemBossbar;
import de.steamwar.bausystem.utils.bossbar.BossBarService;
import org.bukkit.Bukkit;
@@ -72,7 +72,7 @@ public abstract class StabStep {
protected final void stop() {
data.simulator.setStabGenerator(null);
SimulatorRenderer.update(data.simulator);
SimulatorWatcher.update(data.simulator);
for (Player player : Bukkit.getOnlinePlayers()) {
BauSystemBossbar bossbar = BossBarService.instance.get(player, data.region, "simulator_stab_generator");
@@ -1,35 +1,35 @@
/*
* This file is a part of the SteamWar software.
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
* Copyright (C) 2025 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 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.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License along with this program.
* If not, see <https://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.simulator.gui;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.features.simulator.SimulatorCursorManager;
import de.steamwar.bausystem.features.simulator.SimulatorCursor;
import de.steamwar.bausystem.features.simulator.data.Simulator;
import de.steamwar.bausystem.features.simulator.display.SimulatorCursorMode;
import de.steamwar.bausystem.features.simulator.gui.base.SimulatorBaseGui;
import de.steamwar.data.CMDs;
import de.steamwar.inventory.SWItem;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import java.util.Collections;
public class SimulatorCursorSwitcherGui extends SimulatorBaseGui {
private final SimulatorCursorManager cursorManager = BauSystem.getInstance().getLinker().get(SimulatorCursorManager.class).orElseThrow();
private SimulatorBaseGui back;
@@ -50,12 +50,14 @@ public class SimulatorCursorSwitcherGui extends SimulatorBaseGui {
}).setCustomModelData(CMDs.BACK));
int slot = 2;
SimulatorCursorMode currentType = cursorManager.getActiveCursorMode(player).orElse(SimulatorCursorMode.TNT);
for (SimulatorCursorMode type : SimulatorCursorMode.values()) {
SimulatorCursor.CursorType currentType = SimulatorCursor.getCursorType(player);
for (SimulatorCursor.CursorType type : SimulatorCursor.CursorType.values()) {
boolean selected = type == currentType;
SWItem swItem = new SWItem(selected ? type.material : type.nonSelectedMaterial, "§e" + type.name)
.setCustomModelData(selected ? 0 : CMDs.Simulator.NEW_PHASE).setLore(Collections.singletonList("§eClick to select")).setCallback(click -> {
cursorManager.setActiveCursorMode(player, type);
.setCustomModelData(selected ? 0 : CMDs.Simulator.NEW_PHASE)
.setLore(Collections.singletonList("§eClick to select"))
.setCallback(click -> {
SimulatorCursor.setCursorType(player, type);
player.closeInventory();
});
inventory.setItem(slot, swItem);
@@ -1,26 +1,28 @@
/*
* This file is a part of the SteamWar software.
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 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 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.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License along with this program.
* If not, see <https://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.simulator.gui;
import de.steamwar.bausystem.features.simulator.SimulatorWatcher;
import de.steamwar.bausystem.features.simulator.data.Simulator;
import de.steamwar.bausystem.features.simulator.data.SimulatorElement;
import de.steamwar.bausystem.features.simulator.data.SimulatorGroup;
import de.steamwar.bausystem.features.simulator.display.SimulatorRenderer;
import de.steamwar.bausystem.features.simulator.gui.base.SimulatorBaseGui;
import de.steamwar.bausystem.features.simulator.gui.base.SimulatorPageGui;
import de.steamwar.inventory.InvCallback;
@@ -36,11 +38,8 @@ public class SimulatorGroupChooserGui extends SimulatorPageGui<SimulatorGroup> {
private final SimulatorGroup parent;
private final SimulatorBaseGui back;
public SimulatorGroupChooserGui(Player player, Simulator simulator, SimulatorElement<?> subject,
SimulatorGroup parent, SimulatorBaseGui back) {
super(player, simulator, 6 * 9,
simulator.getGroups().stream().filter(e -> e != parent).filter(e -> subject.canBeInGroup(e))
.collect(Collectors.toList()));
public SimulatorGroupChooserGui(Player player, Simulator simulator, SimulatorElement<?> subject, SimulatorGroup parent, SimulatorBaseGui back) {
super(player, simulator, 6 * 9, simulator.getGroups().stream().filter(e -> e != parent).filter(e -> subject.canBeInGroup(e)).collect(Collectors.toList()));
this.subject = subject;
this.parent = parent;
this.back = back;
@@ -57,7 +56,7 @@ public class SimulatorGroupChooserGui extends SimulatorPageGui<SimulatorGroup> {
simulator.getGroups().add(newParent);
parent.getElements().remove(subject);
back.open();
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
if (parent.getElements().size() == 1) {
parent.setDisabled(false);
parent.setMaterial(Material.BARREL);
@@ -84,7 +83,7 @@ public class SimulatorGroupChooserGui extends SimulatorPageGui<SimulatorGroup> {
parent.setMaterial(Material.BARREL);
}
back.open();
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
};
return simulatorGroup.toItem(player, invCallback, invCallback);
}
@@ -1,26 +1,28 @@
/*
* This file is a part of the SteamWar software.
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
* Copyright (C) 2025 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 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.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License along with this program.
* If not, see <https://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.simulator.gui;
import de.steamwar.bausystem.features.simulator.SimulatorWatcher;
import de.steamwar.bausystem.features.simulator.data.Simulator;
import de.steamwar.bausystem.features.simulator.data.SimulatorElement;
import de.steamwar.bausystem.features.simulator.data.SimulatorGroup;
import de.steamwar.bausystem.features.simulator.display.SimulatorRenderer;
import de.steamwar.bausystem.features.simulator.gui.base.SimulatorBaseGui;
import de.steamwar.bausystem.features.simulator.gui.base.SimulatorPageGui;
import de.steamwar.data.CMDs;
@@ -58,7 +60,7 @@ public class SimulatorGroupGui extends SimulatorPageGui<SimulatorElement<?>> {
}
if (simulatorGroup.getElements().removeIf(element -> element.getPhases().isEmpty())) {
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}
if (simulatorGroup.getElements().size() < 2) {
back.open();
@@ -73,12 +75,11 @@ public class SimulatorGroupGui extends SimulatorPageGui<SimulatorElement<?>> {
inventory.setItem(8, new SWItem(Material.BARRIER, "§eDelete", clickType -> {
simulatorGroup.getElements().clear();
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DELETE));
inventory.setItem(4, simulatorGroup.toItem(player, clickType -> {
if (simulatorGroup.getMaterial() == null)
return;
if (simulatorGroup.getMaterial() == null) return;
new SimulatorMaterialGui(player, simulator, simulatorGroup::getMaterial, simulatorGroup::setMaterial, this).open();
}, clickType -> {
}));
@@ -86,19 +87,17 @@ public class SimulatorGroupGui extends SimulatorPageGui<SimulatorElement<?>> {
inventory.setItem(48, new SWItem(Material.REPEATER, "§eSettings", clickType -> {
new SimulatorGroupSettingsGui(player, simulator, simulatorGroup, this).open();
}).setCustomModelData(CMDs.Simulator.SETTINGS));
boolean disabled = simulatorGroup.getMaterial() == null ? simulatorGroup.getElements().stream().allMatch(SimulatorElement::isDisabled)
: simulatorGroup.isDisabled();
inventory.setItem(50,
new SWItem(disabled ? Material.ENDER_PEARL : Material.ENDER_EYE, simulatorGroup.isDisabled() ? "§cDisabled" : "§aEnabled", clickType -> {
if (simulatorGroup.getMaterial() == null) {
simulatorGroup.getElements().forEach(simulatorElement -> {
simulatorElement.setDisabled(!disabled);
});
} else {
simulatorGroup.setDisabled(!disabled);
}
SimulatorRenderer.update(simulator);
}).setCustomModelData(CMDs.Simulator.ENABLED_OR_DISABLED));
boolean disabled = simulatorGroup.getMaterial() == null ? simulatorGroup.getElements().stream().allMatch(SimulatorElement::isDisabled) : simulatorGroup.isDisabled();
inventory.setItem(50, new SWItem(disabled ? Material.ENDER_PEARL : Material.ENDER_EYE, simulatorGroup.isDisabled() ? "§cDisabled" : "§aEnabled", clickType -> {
if (simulatorGroup.getMaterial() == null) {
simulatorGroup.getElements().forEach(simulatorElement -> {
simulatorElement.setDisabled(!disabled);
});
} else {
simulatorGroup.setDisabled(!disabled);
}
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.ENABLED_OR_DISABLED));
}
@Override
@@ -1,26 +1,28 @@
/*
* This file is a part of the SteamWar software.
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 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 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.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License along with this program.
* If not, see <https://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.simulator.gui;
import de.steamwar.bausystem.features.simulator.SimulatorWatcher;
import de.steamwar.bausystem.features.simulator.data.Simulator;
import de.steamwar.bausystem.features.simulator.data.SimulatorGroup;
import de.steamwar.bausystem.features.simulator.data.tnt.TNTElement;
import de.steamwar.bausystem.features.simulator.display.SimulatorRenderer;
import de.steamwar.bausystem.features.simulator.gui.base.SimulatorAnvilGui;
import de.steamwar.bausystem.features.simulator.gui.base.SimulatorBaseGui;
import de.steamwar.data.CMDs;
@@ -35,8 +37,7 @@ public class SimulatorGroupSettingsGui extends SimulatorBaseGui {
private final SimulatorGroup simulatorGroup;
private final SimulatorBaseGui back;
public SimulatorGroupSettingsGui(Player player, Simulator simulator, SimulatorGroup simulatorGroup,
SimulatorBaseGui back) {
public SimulatorGroupSettingsGui(Player player, Simulator simulator, SimulatorGroup simulatorGroup, SimulatorBaseGui back) {
super(player, simulator, 5 * 9);
this.simulatorGroup = simulatorGroup;
this.back = back;
@@ -61,169 +62,164 @@ public class SimulatorGroupSettingsGui extends SimulatorBaseGui {
// Material Chooser
inventory.setItem(4, simulatorGroup.toItem(player, clickType -> {
if (simulatorGroup.getMaterial() == null)
return;
new SimulatorMaterialGui(player, simulator, simulatorGroup::getMaterial, simulatorGroup::setMaterial, this)
.open();
if (simulatorGroup.getMaterial() == null) return;
new SimulatorMaterialGui(player, simulator, simulatorGroup::getMaterial, simulatorGroup::setMaterial, this).open();
}, clickType -> {
}));
// Base Tick
int baseTicks = simulatorGroup.getBaseTick();
inventory.setItem(9,
new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
simulatorGroup.changeBaseTicks(clickType.isShiftClick() ? 5 : 1);
SimulatorRenderer.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
inventory.setItem(9, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
simulatorGroup.changeBaseTicks(clickType.isShiftClick() ? 5 : 1);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
SWItem baseTick = new SWItem(Material.REPEATER, "§eTicks§8:§7 " + baseTicks, clickType -> {
new SimulatorAnvilGui<>(player, "Ticks", baseTicks + "", Integer::parseInt, integer -> {
if (integer < 0)
return false;
if (integer < 0) return false;
simulatorGroup.changeBaseTicks(integer - baseTicks);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
return true;
}, this).setItem(Material.REPEATER).open();
});
baseTick.getItemStack().setAmount(Math.max(1, Math.min(baseTicks, 64)));
inventory.setItem(18, baseTick);
inventory.setItem(27, new SWItem(SWItem.getDye(baseTicks > 0 ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8: §e-5"),
false, clickType -> {
if (baseTicks - (clickType.isShiftClick() ? 5 : 1) < 0) {
simulatorGroup.changeBaseTicks(-baseTicks);
} else {
simulatorGroup.changeBaseTicks(clickType.isShiftClick() ? -5 : -1);
}
SimulatorRenderer.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
inventory.setItem(27, new SWItem(SWItem.getDye(baseTicks > 0 ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
if (baseTicks - (clickType.isShiftClick() ? 5 : 1) < 0) {
simulatorGroup.changeBaseTicks(-baseTicks);
} else {
simulatorGroup.changeBaseTicks(clickType.isShiftClick() ? -5 : -1);
}
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
boolean allTNT = simulatorGroup.getElements().stream().allMatch(TNTElement.class::isInstance);
if (allTNT) {
// Subpixel Alignment
inventory.setItem(21, new SWItem(Material.SUNFLOWER, "§7Align§8: §eCenter", clickType -> {
simulatorGroup.getElements().stream().map(TNTElement.class::cast).forEach(tntElement -> {
tntElement.alignX(0);
tntElement.alignZ(0);
});
SimulatorRenderer.update(simulator);
simulatorGroup.getElements().stream()
.map(TNTElement.class::cast)
.forEach(tntElement -> {
tntElement.alignX(0);
tntElement.alignZ(0);
});
SimulatorWatcher.update(simulator);
}));
// Z
SWItem negativZItem = new SWItem(Material.OAK_BUTTON, "§7Align§8: §eNegativ Z", clickType -> {
simulatorGroup.getElements().stream().map(TNTElement.class::cast).forEach(tntElement -> {
if (tntElement.getAlignment().getZ() != -1)
tntElement.alignZ(-1);
});
SimulatorRenderer.update(simulator);
simulatorGroup.getElements().stream()
.map(TNTElement.class::cast)
.forEach(tntElement -> {
if (tntElement.getAlignment().getZ() != -1) tntElement.alignZ(-1);
});
SimulatorWatcher.update(simulator);
});
negativZItem.setEnchanted(
simulatorGroup.getElements().stream().map(TNTElement.class::cast)
.allMatch(tntElement -> tntElement.getAlignment().getZ() == -1));
negativZItem.setEnchanted(simulatorGroup.getElements().stream()
.map(TNTElement.class::cast)
.allMatch(tntElement -> tntElement.getAlignment().getZ() == -1));
inventory.setItem(20, negativZItem);
SWItem positivZItem = new SWItem(Material.OAK_BUTTON, "§7Align§8: §ePositiv Z", clickType -> {
simulatorGroup.getElements().stream().map(TNTElement.class::cast).forEach(tntElement -> {
if (tntElement.getAlignment().getZ() != 1)
tntElement.alignZ(1);
});
SimulatorRenderer.update(simulator);
simulatorGroup.getElements().stream()
.map(TNTElement.class::cast)
.forEach(tntElement -> {
if (tntElement.getAlignment().getZ() != 1) tntElement.alignZ(1);
});
SimulatorWatcher.update(simulator);
});
positivZItem.setEnchanted(
simulatorGroup.getElements().stream().map(TNTElement.class::cast)
.allMatch(tntElement -> tntElement.getAlignment().getZ() == 1));
positivZItem.setEnchanted(simulatorGroup.getElements().stream()
.map(TNTElement.class::cast)
.allMatch(tntElement -> tntElement.getAlignment().getZ() == 1));
inventory.setItem(22, positivZItem);
// X
SWItem negativXItem = new SWItem(Material.STONE_BUTTON, "§7Align§8: §eNegativ X", clickType -> {
simulatorGroup.getElements().stream().map(TNTElement.class::cast).forEach(tntElement -> {
if (tntElement.getAlignment().getX() != -1)
tntElement.alignX(-1);
});
simulatorGroup.getElements().stream()
.map(TNTElement.class::cast)
.forEach(tntElement -> {
if (tntElement.getAlignment().getX() != -1) tntElement.alignX(-1);
});
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
});
negativXItem.setEnchanted(
simulatorGroup.getElements().stream().map(TNTElement.class::cast)
.allMatch(tntElement -> tntElement.getAlignment().getX() == -1));
negativXItem.setEnchanted(simulatorGroup.getElements().stream()
.map(TNTElement.class::cast)
.allMatch(tntElement -> tntElement.getAlignment().getX() == -1));
inventory.setItem(12, negativXItem);
SWItem positivXItem = new SWItem(Material.STONE_BUTTON, "§7Align§8: §ePositiv X", clickType -> {
simulatorGroup.getElements().stream().map(TNTElement.class::cast).forEach(tntElement -> {
if (tntElement.getAlignment().getX() != 1)
tntElement.alignX(1);
});
SimulatorRenderer.update(simulator);
SWItem positivXItem = new SWItem(Material.STONE_BUTTON, "§7Align§8: §ePositiv X", clickType -> {
simulatorGroup.getElements().stream()
.map(TNTElement.class::cast)
.forEach(tntElement -> {
if (tntElement.getAlignment().getX() != 1) tntElement.alignX(1);
});
SimulatorWatcher.update(simulator);
});
positivXItem.setEnchanted(
simulatorGroup.getElements().stream().map(TNTElement.class::cast)
.allMatch(tntElement -> tntElement.getAlignment().getX() == -1));
positivXItem.setEnchanted(simulatorGroup.getElements().stream()
.map(TNTElement.class::cast)
.allMatch(tntElement -> tntElement.getAlignment().getX() == -1));
inventory.setItem(30, positivXItem);
}
// Pos X
inventory.setItem(15, new SWItem(SWItem.getDye(10), "§e+1",
Arrays.asList(allTNT ? "§7Shift§8: §e+0.0625" : "§7Shift§8: §e+5"), false, clickType -> {
simulatorGroup.move(clickType.isShiftClick() ? (allTNT ? 0.0625 : 5) : 1, 0, 0);
SimulatorRenderer.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
//Pos X
inventory.setItem(15, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList(allTNT ? "§7Shift§8: §e+0.0625" : "§7Shift§8: §e+5"), false, clickType -> {
simulatorGroup.move(clickType.isShiftClick() ? (allTNT ? 0.0625 : 5) : 1, 0, 0);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
inventory.setItem(24, new SWItem(Material.PAPER, "§eX", clickType -> {
new SimulatorAnvilGui<>(player, "Relative X", "", Double::parseDouble, number -> {
if (!allTNT) {
if(!allTNT){
number = (double) Math.round(number);
}
simulatorGroup.move(number, 0, 0);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
return true;
}, this).setItem(Material.PAPER).open();
}));
inventory.setItem(33, new SWItem(SWItem.getDye(1), "§e-1",
Arrays.asList(allTNT ? "§7Shift§8: §e-0.0625" : "§7Shift§8: §e-5"), false, clickType -> {
simulatorGroup.move(clickType.isShiftClick() ? (allTNT ? -0.0625 : -5) : -1, 0, 0);
SimulatorRenderer.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
inventory.setItem(33, new SWItem(SWItem.getDye(1), "§e-1", Arrays.asList(allTNT ? "§7Shift§8: §e-0.0625" : "§7Shift§8: §e-5"), false, clickType -> {
simulatorGroup.move(clickType.isShiftClick() ? (allTNT ? -0.0625 : -5) : -1, 0, 0);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
// Pos Y
inventory.setItem(16, new SWItem(SWItem.getDye(10), "§e+1",
Arrays.asList(allTNT ? "§7Shift§8: §e+0.0625" : "§7Shift§8: §e+5"), false, clickType -> {
simulatorGroup.move(0, clickType.isShiftClick() ? (allTNT ? 0.0625 : 5) : 1, 0);
SimulatorRenderer.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
//Pos Y
inventory.setItem(16, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList(allTNT ? "§7Shift§8: §e+0.0625" : "§7Shift§8: §e+5"), false, clickType -> {
simulatorGroup.move(0, clickType.isShiftClick() ? (allTNT ? 0.0625 : 5) : 1, 0);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
inventory.setItem(25, new SWItem(Material.PAPER, "§eY", clickType -> {
new SimulatorAnvilGui<>(player, "Relative Y", "", Double::parseDouble, number -> {
if (!allTNT) {
if(!allTNT){
number = (double) Math.round(number);
}
simulatorGroup.move(0, number, 0);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
return true;
}, this).setItem(Material.PAPER).open();
}));
inventory.setItem(34, new SWItem(SWItem.getDye(1), "§e-1",
Arrays.asList(allTNT ? "§7Shift§8: §e-0.0625" : "§7Shift§8: §e-5"), false, clickType -> {
simulatorGroup.move(0, clickType.isShiftClick() ? (allTNT ? -0.0625 : -5) : -1, 0);
SimulatorRenderer.update(simulator);
}).setCustomModelData(CMDs.Simulator.ENABLED_OR_DISABLED));
inventory.setItem(34, new SWItem(SWItem.getDye(1), "§e-1", Arrays.asList(allTNT ? "§7Shift§8: §e-0.0625" : "§7Shift§8: §e-5"), false, clickType -> {
simulatorGroup.move(0, clickType.isShiftClick() ? (allTNT ? -0.0625 : -5) : -1, 0);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.ENABLED_OR_DISABLED));
// Pos Z
inventory.setItem(17, new SWItem(SWItem.getDye(10), "§e+1",
Arrays.asList(allTNT ? "§7Shift§8: §e+0.0625" : "§7Shift§8: §e+5"), false, clickType -> {
simulatorGroup.move(0, 0, clickType.isShiftClick() ? (allTNT ? 0.0625 : 5) : 1);
SimulatorRenderer.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
//Pos Z
inventory.setItem(17, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList(allTNT ? "§7Shift§8: §e+0.0625" : "§7Shift§8: §e+5"), false, clickType -> {
simulatorGroup.move(0, 0, clickType.isShiftClick() ? (allTNT ? 0.0625 : 5) : 1);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
inventory.setItem(26, new SWItem(Material.PAPER, "§eZ", clickType -> {
new SimulatorAnvilGui<>(player, "Relative Z", "", Double::parseDouble, number -> {
if (!allTNT) {
if(!allTNT){
number = (double) Math.round(number);
}
simulatorGroup.move(0, 0, number);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
return true;
}, this).setItem(Material.PAPER).open();
}));
inventory.setItem(35, new SWItem(SWItem.getDye(1), "§e-1",
Arrays.asList(allTNT ? "§7Shift§8: §e-0.0625" : "§7Shift§8: §e-5"), false, clickType -> {
simulatorGroup.move(0, 0, clickType.isShiftClick() ? (allTNT ? -0.0625 : -5) : -1);
SimulatorRenderer.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
inventory.setItem(35, new SWItem(SWItem.getDye(1), "§e-1", Arrays.asList(allTNT ? "§7Shift§8: §e-0.0625" : "§7Shift§8: §e-5"), false, clickType -> {
simulatorGroup.move(0, 0, clickType.isShiftClick() ? (allTNT ? -0.0625 : -5) : -1);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
}
}
@@ -1,30 +1,29 @@
/*
* This file is a part of the SteamWar software.
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
* Copyright (C) 2025 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 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.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License along with this program.
* If not, see <https://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.simulator.gui;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.features.simulator.SimulatorCursorManager;
import de.steamwar.bausystem.features.simulator.SimulatorCursor;
import de.steamwar.bausystem.features.simulator.SimulatorWatcher;
import de.steamwar.bausystem.features.simulator.data.Simulator;
import de.steamwar.bausystem.features.simulator.data.SimulatorElement;
import de.steamwar.bausystem.features.simulator.data.SimulatorGroup;
import de.steamwar.bausystem.features.simulator.display.SimulatorCursor;
import de.steamwar.bausystem.features.simulator.display.SimulatorCursorMode;
import de.steamwar.bausystem.features.simulator.display.SimulatorRenderer;
import de.steamwar.bausystem.features.simulator.gui.base.SimulatorPageGui;
import de.steamwar.data.CMDs;
import de.steamwar.inventory.SWItem;
@@ -33,8 +32,6 @@ import org.bukkit.entity.Player;
public class SimulatorGui extends SimulatorPageGui<SimulatorGroup> {
private final SimulatorCursorManager cursorManager = BauSystem.getInstance().getLinker().get(SimulatorCursorManager.class).orElseThrow();
public SimulatorGui(Player player, Simulator simulator) {
super(player, simulator, 6 * 9, simulator.getGroups());
}
@@ -46,15 +43,14 @@ public class SimulatorGui extends SimulatorPageGui<SimulatorGroup> {
@Override
public void headerAndFooter() {
if (simulator.getGroups().removeIf(element -> element.getElements().isEmpty()
|| element.getElements().stream().allMatch(simulatorElement -> simulatorElement.getPhases().isEmpty()))) {
SimulatorRenderer.update(simulator);
if (simulator.getGroups().removeIf(element -> element.getElements().isEmpty() || element.getElements().stream().allMatch(simulatorElement -> simulatorElement.getPhases().isEmpty()))) {
SimulatorWatcher.update(simulator);
}
inventory.setItem(4, simulator.toItem(player, clickType -> {
new SimulatorMaterialGui(player, simulator, simulator::getMaterial, simulator::setMaterial, this).open();
}));
SimulatorCursorMode cursorType = cursorManager.getActiveCursorMode(player).orElse(SimulatorCursorMode.TNT);
SimulatorCursor.CursorType cursorType = SimulatorCursor.getCursorType(player);
inventory.setItem(48, new SWItem(cursorType.material, "§7Placing §8-§e " + cursorType.name, clickType -> {
new SimulatorCursorSwitcherGui(player, simulator, this).open();
}));
@@ -1,24 +1,26 @@
/*
* This file is a part of the SteamWar software.
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
* Copyright (C) 2025 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 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.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License along with this program.
* If not, see <https://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.simulator.gui;
import de.steamwar.bausystem.features.simulator.SimulatorWatcher;
import de.steamwar.bausystem.features.simulator.data.Simulator;
import de.steamwar.bausystem.features.simulator.display.SimulatorRenderer;
import de.steamwar.bausystem.features.simulator.gui.base.SimulatorBaseGui;
import de.steamwar.bausystem.features.simulator.gui.base.SimulatorPageGui;
import de.steamwar.data.CMDs;
@@ -34,8 +36,11 @@ import java.util.stream.Collectors;
public class SimulatorMaterialGui extends SimulatorPageGui<Material> {
private static final List<Material> MATERIALS = Arrays.stream(Material.values()).filter(material -> !material.isAir())
.filter(material -> !material.isLegacy()).filter(Material::isItem).collect(Collectors.toList());
private static final List<Material> MATERIALS = Arrays.stream(Material.values())
.filter(material -> !material.isAir())
.filter(material -> !material.isLegacy())
.filter(Material::isItem)
.collect(Collectors.toList());
private final Supplier<Material> currentMaterial;
private Material material;
@@ -55,7 +60,7 @@ public class SimulatorMaterialGui extends SimulatorPageGui<Material> {
return true;
}
change.accept(player.getItemOnCursor().getType());
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
return false;
}
@@ -76,10 +81,9 @@ public class SimulatorMaterialGui extends SimulatorPageGui<Material> {
@Override
public SWItem convert(Material material) {
return new SWItem(material, "§eNew Material", Arrays.asList(material == this.material ? "§eSelected" : "§eClick to select"), material == this.material,
clickType -> {
change.accept(material);
SimulatorRenderer.update(simulator);
});
return new SWItem(material, "§eNew Material", Arrays.asList(material == this.material ? "§eSelected" : "§eClick to select"), material == this.material, clickType -> {
change.accept(material);
SimulatorWatcher.update(simulator);
});
}
}
@@ -1,27 +1,29 @@
/*
* This file is a part of the SteamWar software.
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
* Copyright (C) 2025 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 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.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License along with this program.
* If not, see <https://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.simulator.gui;
import de.steamwar.bausystem.features.simulator.SimulatorWatcher;
import de.steamwar.bausystem.features.simulator.data.Simulator;
import de.steamwar.bausystem.features.simulator.data.SimulatorGroup;
import de.steamwar.bausystem.features.simulator.data.observer.ObserverElement;
import de.steamwar.bausystem.features.simulator.data.observer.ObserverPhase;
import de.steamwar.bausystem.features.simulator.display.SimulatorRenderer;
import de.steamwar.bausystem.features.simulator.gui.base.SimulatorBaseGui;
import de.steamwar.bausystem.features.simulator.gui.base.SimulatorScrollGui;
import de.steamwar.data.CMDs;
@@ -58,7 +60,7 @@ public class SimulatorObserverGui extends SimulatorScrollGui<ObserverPhase> {
public void headerAndFooter() {
if (observer.getPhases().isEmpty()) {
back.open();
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
return;
}
@@ -85,7 +87,7 @@ public class SimulatorObserverGui extends SimulatorScrollGui<ObserverPhase> {
inventory.setItem(8, new SWItem(Material.BARRIER, "§eDelete", clickType -> {
observer.getPhases().clear();
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DELETE));
// Material Chooser
@@ -99,11 +101,10 @@ public class SimulatorObserverGui extends SimulatorScrollGui<ObserverPhase> {
}).setCustomModelData(CMDs.Simulator.SETTINGS));
// Enable/Disable
inventory.setItem(48,
new SWItem(observer.isDisabled() ? Material.ENDER_PEARL : Material.ENDER_EYE, observer.isDisabled() ? "§cDisabled" : "§aEnabled", clickType -> {
observer.setDisabled(!observer.isDisabled());
SimulatorRenderer.update(simulator);
}).setCustomModelData(CMDs.Simulator.ENABLED_OR_DISABLED));
inventory.setItem(48, new SWItem(observer.isDisabled() ? Material.ENDER_PEARL : Material.ENDER_EYE, observer.isDisabled() ? "§cDisabled" : "§aEnabled", clickType -> {
observer.setDisabled(!observer.isDisabled());
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.ENABLED_OR_DISABLED));
// Group chooser
inventory.setItem(51, new SWItem(Material.LEAD, "§eJoin Group", clickType -> {
@@ -138,7 +139,7 @@ public class SimulatorObserverGui extends SimulatorScrollGui<ObserverPhase> {
SWItem observer = new SWItem(Material.OBSERVER, "§eObserver", lore, false, clickType -> {
if (clickType == ClickType.MIDDLE) {
this.observer.getPhases().remove(observerPhase);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
} else {
new SimulatorObserverPhaseSettingsGui(player, simulator, this.observer, observerPhase, this).open();
}
@@ -147,35 +148,42 @@ public class SimulatorObserverGui extends SimulatorScrollGui<ObserverPhase> {
Supplier<Integer> getter = observerPhase::getTickOffset;
Consumer<Integer> setter = observerPhase::setTickOffset;
return new SWItem[] {new SWItem(SWItem.getDye(getter.get() < max ? 10 : 8), "§e+1", Arrays.asList("§7Shift§8:§e +5"), false, clickType -> {
setter.accept(Math.min(max, getter.get() + (clickType.isShiftClick() ? 5 : 1)));
SimulatorRenderer.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED), observer,
return new SWItem[] {
new SWItem(SWItem.getDye(getter.get() < max ? 10 : 8), "§e+1", Arrays.asList("§7Shift§8:§e +5"), false, clickType -> {
setter.accept(Math.min(max, getter.get() + (clickType.isShiftClick() ? 5 : 1)));
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED),
observer,
new SWItem(SWItem.getDye(getter.get() > min ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8:§e -5"), false, clickType -> {
setter.accept(Math.max(min, getter.get() - (clickType.isShiftClick() ? 5 : 1)));
SimulatorRenderer.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED), new SWItem(Material.ANVIL, "§eEdit Activation", clickType -> {
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED),
new SWItem(Material.ANVIL, "§eEdit Activation", clickType -> {
new SimulatorObserverPhaseSettingsGui(player, simulator, this.observer, observerPhase, this).open();
}).setCustomModelData(CMDs.Simulator.EDIT_ACTIVATION),};
}).setCustomModelData(CMDs.Simulator.EDIT_ACTIVATION),
};
}
@Override
public SWItem[] lastColumn() {
return new SWItem[] {new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8:§e +5"), false, clickType -> {
addNewPhase(clickType.isShiftClick());
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED), new SWItem(Material.QUARTZ, "§eObserver§8:§a New Phase", clickType -> {
addNewPhase(false);
}).setCustomModelData(CMDs.Simulator.NEW_PHASE), new SWItem(SWItem.getDye(8), "§7", clickType -> {
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED),};
return new SWItem[]{
new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8:§e +5"), false, clickType -> {
addNewPhase(clickType.isShiftClick());
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED),
new SWItem(Material.QUARTZ, "§eObserver§8:§a New Phase", clickType -> {
addNewPhase(false);
}).setCustomModelData(CMDs.Simulator.NEW_PHASE),
new SWItem(SWItem.getDye(8), "§7", clickType -> {
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED),
};
}
private void addNewPhase(boolean shift) {
ObserverPhase lastElement = observer.getPhases().get(observer.getPhases().size() - 1);
ObserverPhase newPhase = new ObserverPhase(lastElement.getTickOffset() + 4);
if (shift)
newPhase.setTickOffset(newPhase.getTickOffset() + 5);
if (shift) newPhase.setTickOffset(newPhase.getTickOffset() + 5);
scroll += 2;
observer.add(newPhase);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}
}
@@ -1,27 +1,29 @@
/*
* This file is a part of the SteamWar software.
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
* Copyright (C) 2025 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 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.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License along with this program.
* If not, see <https://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.simulator.gui;
import de.steamwar.bausystem.features.simulator.SimulatorWatcher;
import de.steamwar.bausystem.features.simulator.data.Simulator;
import de.steamwar.bausystem.features.simulator.data.SimulatorPhase;
import de.steamwar.bausystem.features.simulator.data.observer.ObserverElement;
import de.steamwar.bausystem.features.simulator.data.observer.ObserverPhase;
import de.steamwar.bausystem.features.simulator.display.SimulatorRenderer;
import de.steamwar.bausystem.features.simulator.gui.base.SimulatorAnvilGui;
import de.steamwar.bausystem.features.simulator.gui.base.SimulatorBaseGui;
import de.steamwar.core.Core;
@@ -39,8 +41,7 @@ public class SimulatorObserverPhaseSettingsGui extends SimulatorBaseGui {
private final ObserverPhase observer;
private final SimulatorBaseGui back;
public SimulatorObserverPhaseSettingsGui(Player player, Simulator simulator, ObserverElement observerElement, ObserverPhase observer,
SimulatorBaseGui back) {
public SimulatorObserverPhaseSettingsGui(Player player, Simulator simulator, ObserverElement observerElement, ObserverPhase observer, SimulatorBaseGui back) {
super(player, simulator, 5 * 9);
this.observerElement = observerElement;
this.observer = observer;
@@ -73,7 +74,7 @@ public class SimulatorObserverPhaseSettingsGui extends SimulatorBaseGui {
inventory.setItem(8, new SWItem(Material.BARRIER, "§eDelete", clickType -> {
observerElement.getPhases().remove(observer);
back.open();
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DELETE));
int index = observerElement.getPhases().indexOf(observer);
@@ -93,19 +94,18 @@ public class SimulatorObserverPhaseSettingsGui extends SimulatorBaseGui {
max = Integer.MAX_VALUE - 4;
}
// Tick Offset
//Tick Offset
int offset = observer.getTickOffset();
inventory.setItem(10, new SWItem(SWItem.getDye(offset < max ? 10 : 8), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
observer.setTickOffset(Math.min(max, offset + (clickType.isShiftClick() ? 5 : 1)));
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
SWItem offsetItem = new SWItem(Material.REPEATER, "§eStart at§8:§7 " + offset, clickType -> {
new SimulatorAnvilGui<>(player, "Start at", offset + "", Integer::parseInt, integer -> {
if (integer < 0)
return false;
if (integer < 0) return false;
observer.setTickOffset(Math.min(Math.max(integer, min), max));
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
return true;
}, this).setItem(Material.REPEATER).open();
});
@@ -114,66 +114,60 @@ public class SimulatorObserverPhaseSettingsGui extends SimulatorBaseGui {
inventory.setItem(28, new SWItem(SWItem.getDye(offset > min ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
observer.setTickOffset(Math.max(min, offset - (clickType.isShiftClick() ? 5 : 1)));
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
// Order
//Order
int order = observer.getOrder();
inventory.setItem(13,
new SWItem(SWItem.getDye(order < SimulatorPhase.ORDER_LIMIT ? 10 : 8), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
observer.setOrder(Math.min(SimulatorPhase.ORDER_LIMIT, order + (clickType.isShiftClick() ? 5 : 1)));
SimulatorRenderer.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
inventory.setItem(13, new SWItem(SWItem.getDye(order < SimulatorPhase.ORDER_LIMIT ? 10 : 8), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
observer.setOrder(Math.min(SimulatorPhase.ORDER_LIMIT, order + (clickType.isShiftClick() ? 5 : 1)));
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
Material negativeNumbers = Material.getMaterial(Core.getVersion() >= 19 ? "RECOVERY_COMPASS" : "FIREWORK_STAR");
SWItem orderItem = new SWItem(order >= 0 ? Material.COMPASS : negativeNumbers, "§eActivation Order§8:§7 " + order, clickType -> {
new SimulatorAnvilGui<>(player, "Activation Order", order + "", Integer::parseInt, integer -> {
if (integer < -SimulatorPhase.ORDER_LIMIT)
return false;
if (integer > SimulatorPhase.ORDER_LIMIT)
return false;
if (integer < -SimulatorPhase.ORDER_LIMIT) return false;
if (integer > SimulatorPhase.ORDER_LIMIT) return false;
observer.setOrder(integer);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
return true;
}, this).setItem(order >= 0 ? Material.COMPASS : negativeNumbers).open();
});
orderItem.getItemStack().setAmount(Math.max(1, Math.min(Math.abs(order), 30)));
inventory.setItem(22, orderItem);
inventory.setItem(31,
new SWItem(SWItem.getDye(order > -SimulatorPhase.ORDER_LIMIT ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
observer.setOrder(Math.max(-SimulatorPhase.ORDER_LIMIT, order - (clickType.isShiftClick() ? 5 : 1)));
SimulatorRenderer.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
inventory.setItem(31, new SWItem(SWItem.getDye(order > -SimulatorPhase.ORDER_LIMIT ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
observer.setOrder(Math.max(-SimulatorPhase.ORDER_LIMIT, order - (clickType.isShiftClick() ? 5 : 1)));
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
// Update orientation
inventory.setItem(25, new SWItem(Material.SUNFLOWER, "§7", clickType -> {
}));
inventory.setItem(15, new SWItem(observer.getOrientation() == BlockFace.UP ? Material.LIME_CONCRETE : Material.GRAY_CONCRETE, "§eUp", clickType -> {
observer.setOrientation(BlockFace.UP);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}));
inventory.setItem(33, new SWItem(observer.getOrientation() == BlockFace.DOWN ? Material.RED_CONCRETE : Material.GRAY_CONCRETE, "§eDown", clickType -> {
observer.setOrientation(BlockFace.DOWN);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}));
inventory.setItem(16, new SWItem(observer.getOrientation() == BlockFace.NORTH ? Material.LIME_WOOL : Material.GRAY_WOOL, "§eNorth", clickType -> {
observer.setOrientation(BlockFace.NORTH);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}));
inventory.setItem(34, new SWItem(observer.getOrientation() == BlockFace.SOUTH ? Material.RED_WOOL : Material.GRAY_WOOL, "§eSouth", clickType -> {
observer.setOrientation(BlockFace.SOUTH);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}));
inventory.setItem(24, new SWItem(observer.getOrientation() == BlockFace.EAST ? Material.LIME_STAINED_GLASS : Material.GRAY_STAINED_GLASS, "§eEast", clickType -> {
observer.setOrientation(BlockFace.EAST);
SimulatorWatcher.update(simulator);
}));
inventory.setItem(26, new SWItem(observer.getOrientation() == BlockFace.WEST ? Material.RED_STAINED_GLASS : Material.GRAY_STAINED_GLASS, "§eWest", clickType -> {
observer.setOrientation(BlockFace.WEST);
SimulatorWatcher.update(simulator);
}));
inventory.setItem(24,
new SWItem(observer.getOrientation() == BlockFace.EAST ? Material.LIME_STAINED_GLASS : Material.GRAY_STAINED_GLASS, "§eEast", clickType -> {
observer.setOrientation(BlockFace.EAST);
SimulatorRenderer.update(simulator);
}));
inventory.setItem(26,
new SWItem(observer.getOrientation() == BlockFace.WEST ? Material.RED_STAINED_GLASS : Material.GRAY_STAINED_GLASS, "§eWest", clickType -> {
observer.setOrientation(BlockFace.WEST);
SimulatorRenderer.update(simulator);
}));
}
}
@@ -1,25 +1,27 @@
/*
* This file is a part of the SteamWar software.
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
* Copyright (C) 2025 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 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.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License along with this program.
* If not, see <https://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.simulator.gui;
import de.steamwar.bausystem.features.simulator.SimulatorWatcher;
import de.steamwar.bausystem.features.simulator.data.Simulator;
import de.steamwar.bausystem.features.simulator.data.observer.ObserverElement;
import de.steamwar.bausystem.features.simulator.display.SimulatorRenderer;
import de.steamwar.bausystem.features.simulator.gui.base.SimulatorAnvilGui;
import de.steamwar.bausystem.features.simulator.gui.base.SimulatorBaseGui;
import de.steamwar.data.CMDs;
@@ -66,14 +68,13 @@ public class SimulatorObserverSettingsGui extends SimulatorBaseGui {
int baseTicks = observer.getBaseTick();
inventory.setItem(9, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
observer.changeBaseTicks(clickType.isShiftClick() ? 5 : 1);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
SWItem baseTick = new SWItem(Material.REPEATER, "§eTicks§8:§7 " + baseTicks, clickType -> {
new SimulatorAnvilGui<>(player, "Ticks", baseTicks + "", Integer::parseInt, integer -> {
if (integer < 0)
return false;
if (integer < 0) return false;
observer.changeBaseTicks(integer - baseTicks);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
return true;
}, this).setItem(Material.REPEATER).open();
});
@@ -85,58 +86,58 @@ public class SimulatorObserverSettingsGui extends SimulatorBaseGui {
} else {
observer.changeBaseTicks(clickType.isShiftClick() ? -5 : -1);
}
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
// Pos X
inventory.setItem(15, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
//Pos X
inventory.setItem(15, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
observer.move(clickType.isShiftClick() ? 5 : 1, 0, 0);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
inventory.setItem(24, new SWItem(Material.PAPER, "§eX§8:§7 " + observer.getPosition().getBlockX(), clickType -> {
new SimulatorAnvilGui<>(player, "X", observer.getPosition().getBlockX() + "", Integer::parseInt, i -> {
observer.getPosition().setX(i);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
return true;
}, this).open();
}));
inventory.setItem(33, new SWItem(SWItem.getDye(1), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
observer.move(clickType.isShiftClick() ? -5 : -1, 0, 0);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
// Pos Y
//Pos Y
inventory.setItem(16, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
observer.move(0, clickType.isShiftClick() ? 5 : 1, 0);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.ENABLED_OR_DISABLED));
inventory.setItem(25, new SWItem(Material.PAPER, "§eY§8:§7 " + observer.getPosition().getBlockY(), clickType -> {
new SimulatorAnvilGui<>(player, "Y", observer.getPosition().getBlockY() + "", Integer::parseInt, i -> {
observer.getPosition().setY(i);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
return true;
}, this).open();
}));
inventory.setItem(34, new SWItem(SWItem.getDye(1), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
observer.move(0, clickType.isShiftClick() ? -5 : -1, 0);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
// Pos Z
//Pos Z
inventory.setItem(17, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
observer.move(0, 0, clickType.isShiftClick() ? 5 : 1);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.ENABLED_OR_DISABLED));
inventory.setItem(26, new SWItem(Material.PAPER, "§eZ§8:§7 " + observer.getPosition().getBlockZ(), clickType -> {
new SimulatorAnvilGui<>(player, "Z", observer.getPosition().getBlockZ() + "", Integer::parseInt, i -> {
observer.getPosition().setZ(i);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
return true;
}, this).open();
}));
inventory.setItem(35, new SWItem(SWItem.getDye(1), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
observer.move(0, 0, clickType.isShiftClick() ? -5 : -1);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
}
}
@@ -1,27 +1,29 @@
/*
* This file is a part of the SteamWar software.
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
* Copyright (C) 2025 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 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.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License along with this program.
* If not, see <https://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.simulator.gui;
import de.steamwar.bausystem.features.simulator.SimulatorWatcher;
import de.steamwar.bausystem.features.simulator.data.Simulator;
import de.steamwar.bausystem.features.simulator.data.SimulatorGroup;
import de.steamwar.bausystem.features.simulator.data.redstone.RedstoneElement;
import de.steamwar.bausystem.features.simulator.data.redstone.RedstonePhase;
import de.steamwar.bausystem.features.simulator.display.SimulatorRenderer;
import de.steamwar.bausystem.features.simulator.gui.base.SimulatorBaseGui;
import de.steamwar.bausystem.features.simulator.gui.base.SimulatorScrollGui;
import de.steamwar.data.CMDs;
@@ -59,7 +61,7 @@ public class SimulatorRedstoneGui extends SimulatorScrollGui<SimulatorRedstoneGu
public void headerAndFooter() {
if (redstone.getPhases().isEmpty()) {
back.open();
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
return;
}
@@ -91,7 +93,7 @@ public class SimulatorRedstoneGui extends SimulatorScrollGui<SimulatorRedstoneGu
inventory.setItem(8, new SWItem(Material.BARRIER, "§eDelete", clickType -> {
redstone.getPhases().clear();
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DELETE));
// Material Chooser
@@ -105,11 +107,10 @@ public class SimulatorRedstoneGui extends SimulatorScrollGui<SimulatorRedstoneGu
}).setCustomModelData(CMDs.Simulator.SETTINGS));
// Enable/Disable
inventory.setItem(48,
new SWItem(redstone.isDisabled() ? Material.ENDER_PEARL : Material.ENDER_EYE, redstone.isDisabled() ? "§cDisabled" : "§aEnabled", clickType -> {
redstone.setDisabled(!redstone.isDisabled());
SimulatorRenderer.update(simulator);
}).setCustomModelData(CMDs.Simulator.ENABLED_OR_DISABLED));
inventory.setItem(48, new SWItem(redstone.isDisabled() ? Material.ENDER_PEARL : Material.ENDER_EYE, redstone.isDisabled() ? "§cDisabled" : "§aEnabled", clickType -> {
redstone.setDisabled(!redstone.isDisabled());
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.ENABLED_OR_DISABLED));
// Group chooser
inventory.setItem(51, new SWItem(Material.LEAD, "§eJoin Group", clickType -> {
@@ -150,49 +151,55 @@ public class SimulatorRedstoneGui extends SimulatorScrollGui<SimulatorRedstoneGu
lore.add("");
lore.add("§7Click§8:§e Edit");
lore.add("§7Middle-Click§8:§e Remove");
SWItem redstone = new SWItem(redstoneSubPhase.place ? Material.REDSTONE_BLOCK : Material.STONE, redstoneSubPhase.place ? "§eActivate" : "§eDeactivate",
lore, false, clickType -> {
if (clickType == ClickType.MIDDLE) {
this.redstone.getPhases().remove(redstoneSubPhase.phase);
SimulatorRenderer.update(simulator);
} else {
new SimulatorRedstonePhaseSettingsGui(player, simulator, this.redstone, redstoneSubPhase.phase, this).open();
}
});
SWItem redstone = new SWItem(redstoneSubPhase.place ? Material.REDSTONE_BLOCK : Material.STONE, redstoneSubPhase.place ? "§eActivate" : "§eDeactivate", lore, false, clickType -> {
if (clickType == ClickType.MIDDLE) {
this.redstone.getPhases().remove(redstoneSubPhase.phase);
SimulatorWatcher.update(simulator);
} else {
new SimulatorRedstonePhaseSettingsGui(player, simulator, this.redstone, redstoneSubPhase.phase, this).open();
}
});
redstone.getItemStack().setAmount(Math.max(1, Math.min(time, 64)));
Supplier<Integer> getter = redstoneSubPhase.place ? redstoneSubPhase.phase::getTickOffset : redstoneSubPhase.phase::getLifetime;
Consumer<Integer> setter = redstoneSubPhase.place ? redstoneSubPhase.phase::setTickOffset : redstoneSubPhase.phase::setLifetime;
return new SWItem[] {new SWItem(SWItem.getDye(getter.get() < max ? 10 : 8), "§e+1", Arrays.asList("§7Shift§8:§e +5"), false, clickType -> {
setter.accept(Math.min(max, getter.get() + (clickType.isShiftClick() ? 5 : 1)));
SimulatorRenderer.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED), redstone,
return new SWItem[] {
new SWItem(SWItem.getDye(getter.get() < max ? 10 : 8), "§e+1", Arrays.asList("§7Shift§8:§e +5"), false, clickType -> {
setter.accept(Math.min(max, getter.get() + (clickType.isShiftClick() ? 5 : 1)));
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED),
redstone,
new SWItem(SWItem.getDye(getter.get() > min ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8:§e -5"), false, clickType -> {
setter.accept(Math.max(min, getter.get() - (clickType.isShiftClick() ? 5 : 1)));
SimulatorRenderer.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED), new SWItem(Material.ANVIL, "§eEdit Activation", clickType -> {
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED),
new SWItem(Material.ANVIL, "§eEdit Activation", clickType -> {
new SimulatorRedstonePhaseSettingsGui(player, simulator, this.redstone, redstoneSubPhase.phase, this).open();
}).setCustomModelData(CMDs.Simulator.EDIT_ACTIVATION),};
}).setCustomModelData(CMDs.Simulator.EDIT_ACTIVATION),
};
}
@Override
public SWItem[] lastColumn() {
return new SWItem[] {new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8:§e +5"), false, clickType -> {
addNewPhase(clickType.isShiftClick());
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED), new SWItem(Material.REDSTONE, "§eRedstone§8:§a New Phase", clickType -> {
addNewPhase(false);
}).setCustomModelData(CMDs.Simulator.NEW_PHASE), new SWItem(SWItem.getDye(8), "§7", clickType -> {
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED),};
return new SWItem[]{
new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8:§e +5"), false, clickType -> {
addNewPhase(clickType.isShiftClick());
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED),
new SWItem(Material.REDSTONE, "§eRedstone§8:§a New Phase", clickType -> {
addNewPhase(false);
}).setCustomModelData(CMDs.Simulator.NEW_PHASE),
new SWItem(SWItem.getDye(8), "§7", clickType -> {
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED),
};
}
private void addNewPhase(boolean shift) {
RedstonePhase lastElement = redstone.getPhases().get(redstone.getPhases().size() - 1);
RedstonePhase newPhase = new RedstonePhase(lastElement.getTickOffset() + lastElement.getLifetime() + 1);
if (shift)
newPhase.setTickOffset(newPhase.getTickOffset() + 5);
if (shift) newPhase.setTickOffset(newPhase.getTickOffset() + 5);
scroll += 2;
redstone.add(newPhase);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}
@AllArgsConstructor
@@ -1,27 +1,29 @@
/*
* This file is a part of the SteamWar software.
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
* Copyright (C) 2025 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 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.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License along with this program.
* If not, see <https://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.simulator.gui;
import de.steamwar.bausystem.features.simulator.SimulatorWatcher;
import de.steamwar.bausystem.features.simulator.data.Simulator;
import de.steamwar.bausystem.features.simulator.data.SimulatorPhase;
import de.steamwar.bausystem.features.simulator.data.redstone.RedstoneElement;
import de.steamwar.bausystem.features.simulator.data.redstone.RedstonePhase;
import de.steamwar.bausystem.features.simulator.display.SimulatorRenderer;
import de.steamwar.bausystem.features.simulator.gui.base.SimulatorAnvilGui;
import de.steamwar.bausystem.features.simulator.gui.base.SimulatorBaseGui;
import de.steamwar.core.Core;
@@ -37,8 +39,7 @@ public class SimulatorRedstonePhaseSettingsGui extends SimulatorBaseGui {
private final RedstonePhase redstone;
private final SimulatorBaseGui back;
public SimulatorRedstonePhaseSettingsGui(Player player, Simulator simulator, RedstoneElement redstoneElement, RedstonePhase redstone,
SimulatorBaseGui back) {
public SimulatorRedstonePhaseSettingsGui(Player player, Simulator simulator, RedstoneElement redstoneElement, RedstonePhase redstone, SimulatorBaseGui back) {
super(player, simulator, 5 * 9);
this.redstoneElement = redstoneElement;
this.redstone = redstone;
@@ -71,7 +72,7 @@ public class SimulatorRedstonePhaseSettingsGui extends SimulatorBaseGui {
inventory.setItem(8, new SWItem(Material.BARRIER, "§eDelete", clickType -> {
redstoneElement.getPhases().remove(redstone);
back.open();
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DELETE));
int index = redstoneElement.getPhases().indexOf(redstone);
@@ -94,19 +95,18 @@ public class SimulatorRedstonePhaseSettingsGui extends SimulatorBaseGui {
maxOffset = Integer.MAX_VALUE - 5;
}
// Tick Offset
//Tick Offset
int offset = redstone.getTickOffset();
inventory.setItem(10, new SWItem(SWItem.getDye(offset < maxOffset ? 10 : 8), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
redstone.setTickOffset(Math.min(maxOffset, offset + (clickType.isShiftClick() ? 5 : 1)));
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
SWItem offsetItem = new SWItem(Material.REPEATER, "§eStart at§8:§7 " + offset, clickType -> {
new SimulatorAnvilGui<>(player, "Start at", offset + "", Integer::parseInt, integer -> {
if (integer < 0)
return false;
if (integer < 0) return false;
redstone.setTickOffset(Math.min(Math.max(integer, min), maxOffset));
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
return true;
}, this).setItem(Material.REPEATER).open();
});
@@ -115,22 +115,21 @@ public class SimulatorRedstonePhaseSettingsGui extends SimulatorBaseGui {
inventory.setItem(28, new SWItem(SWItem.getDye(offset > min ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
redstone.setTickOffset(Math.max(min, offset - (clickType.isShiftClick() ? 5 : 1)));
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
// Lifetime
//Lifetime
int lifetime = redstone.getLifetime();
inventory.setItem(11, new SWItem(SWItem.getDye(lifetime < maxLifetime ? 10 : 8), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
redstone.setLifetime(Math.min(maxLifetime, lifetime + (clickType.isShiftClick() ? 5 : 1)));
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
SWItem lifetimeItem = new SWItem(Material.CLOCK, "§eActivation Time§8:§7 " + lifetime, clickType -> {
new SimulatorAnvilGui<>(player, "Activation Time", lifetime + "", Integer::parseInt, integer -> {
if (integer < 0)
return false;
if (integer < 0) return false;
redstone.setLifetime(Math.min(integer, maxLifetime));
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
return true;
}, this).setItem(Material.CLOCK).open();
});
@@ -139,36 +138,32 @@ public class SimulatorRedstonePhaseSettingsGui extends SimulatorBaseGui {
inventory.setItem(29, new SWItem(SWItem.getDye(lifetime > 0 ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
redstone.setLifetime(Math.max(0, lifetime - (clickType.isShiftClick() ? 5 : 1)));
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
// Order
//Order
int order = redstone.getOrder();
inventory.setItem(13,
new SWItem(SWItem.getDye(order < SimulatorPhase.ORDER_LIMIT ? 10 : 8), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
redstone.setOrder(Math.min(SimulatorPhase.ORDER_LIMIT, order + (clickType.isShiftClick() ? 5 : 1)));
SimulatorRenderer.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
inventory.setItem(13, new SWItem(SWItem.getDye(order < SimulatorPhase.ORDER_LIMIT ? 10 : 8), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
redstone.setOrder(Math.min(SimulatorPhase.ORDER_LIMIT, order + (clickType.isShiftClick() ? 5 : 1)));
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
Material negativeNumbers = Material.getMaterial(Core.getVersion() >= 19 ? "RECOVERY_COMPASS" : "FIREWORK_STAR");
SWItem orderItem = new SWItem(order >= 0 ? Material.COMPASS : negativeNumbers, "§eActivation Order§8:§7 " + order, clickType -> {
new SimulatorAnvilGui<>(player, "Activation Order", order + "", Integer::parseInt, integer -> {
if (integer < -SimulatorPhase.ORDER_LIMIT)
return false;
if (integer > SimulatorPhase.ORDER_LIMIT)
return false;
if (integer < -SimulatorPhase.ORDER_LIMIT) return false;
if (integer > SimulatorPhase.ORDER_LIMIT) return false;
redstone.setOrder(integer);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
return true;
}, this).setItem(order >= 0 ? Material.COMPASS : negativeNumbers).open();
});
orderItem.getItemStack().setAmount(Math.max(1, Math.min(Math.abs(order), 30)));
inventory.setItem(22, orderItem);
inventory.setItem(31,
new SWItem(SWItem.getDye(order > -SimulatorPhase.ORDER_LIMIT ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
redstone.setOrder(Math.max(-SimulatorPhase.ORDER_LIMIT, order - (clickType.isShiftClick() ? 5 : 1)));
SimulatorRenderer.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
inventory.setItem(31, new SWItem(SWItem.getDye(order > -SimulatorPhase.ORDER_LIMIT ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
redstone.setOrder(Math.max(-SimulatorPhase.ORDER_LIMIT, order - (clickType.isShiftClick() ? 5 : 1)));
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
}
}
@@ -1,25 +1,27 @@
/*
* This file is a part of the SteamWar software.
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
* Copyright (C) 2025 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 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.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License along with this program.
* If not, see <https://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.simulator.gui;
import de.steamwar.bausystem.features.simulator.SimulatorWatcher;
import de.steamwar.bausystem.features.simulator.data.Simulator;
import de.steamwar.bausystem.features.simulator.data.redstone.RedstoneElement;
import de.steamwar.bausystem.features.simulator.display.SimulatorRenderer;
import de.steamwar.bausystem.features.simulator.gui.base.SimulatorAnvilGui;
import de.steamwar.bausystem.features.simulator.gui.base.SimulatorBaseGui;
import de.steamwar.data.CMDs;
@@ -65,14 +67,13 @@ public class SimulatorRedstoneSettingsGui extends SimulatorBaseGui {
int baseTicks = redstone.getBaseTick();
inventory.setItem(9, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
redstone.changeBaseTicks(clickType.isShiftClick() ? 5 : 1);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
SWItem baseTick = new SWItem(Material.REPEATER, "§eTicks§8:§7 " + baseTicks, clickType -> {
new SimulatorAnvilGui<>(player, "Ticks", baseTicks + "", Integer::parseInt, integer -> {
if (integer < 0)
return false;
if (integer < 0) return false;
redstone.changeBaseTicks(integer - baseTicks);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
return true;
}, this).setItem(Material.REPEATER).open();
});
@@ -84,58 +85,58 @@ public class SimulatorRedstoneSettingsGui extends SimulatorBaseGui {
} else {
redstone.changeBaseTicks(clickType.isShiftClick() ? -5 : -1);
}
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
// Pos X
//Pos X
inventory.setItem(15, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
redstone.move(clickType.isShiftClick() ? 5 : 1, 0, 0);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
inventory.setItem(24, new SWItem(Material.PAPER, "§eX§8:§7 " + redstone.getPosition().getBlockX(), clickType -> {
new SimulatorAnvilGui<>(player, "X", redstone.getPosition().getBlockX() + "", Integer::parseInt, i -> {
redstone.getPosition().setX(i);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
return true;
}, this).open();
}));
inventory.setItem(33, new SWItem(SWItem.getDye(1), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
redstone.move(clickType.isShiftClick() ? -5 : -1, 0, 0);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
// Pos Y
//Pos Y
inventory.setItem(16, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
redstone.move(0, clickType.isShiftClick() ? 5 : 1, 0);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
inventory.setItem(25, new SWItem(Material.PAPER, "§eY§8:§7 " + redstone.getPosition().getBlockY(), clickType -> {
new SimulatorAnvilGui<>(player, "Y", redstone.getPosition().getBlockY() + "", Integer::parseInt, i -> {
redstone.getPosition().setY(i);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
return true;
}, this).open();
}));
inventory.setItem(34, new SWItem(SWItem.getDye(1), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
redstone.move(0, clickType.isShiftClick() ? -5 : -1, 0);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
// Pos Z
//Pos Z
inventory.setItem(17, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
redstone.move(0, 0, clickType.isShiftClick() ? 5 : 1);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
inventory.setItem(26, new SWItem(Material.PAPER, "§eZ§8:§7 " + redstone.getPosition().getBlockZ(), clickType -> {
new SimulatorAnvilGui<>(player, "Z", redstone.getPosition().getBlockZ() + "", Integer::parseInt, i -> {
redstone.getPosition().setZ(i);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
return true;
}, this).open();
}));
inventory.setItem(35, new SWItem(SWItem.getDye(1), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
redstone.move(0, 0, clickType.isShiftClick() ? -5 : -1);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
}
}
@@ -1,24 +1,26 @@
/*
* This file is a part of the SteamWar software.
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
* Copyright (C) 2025 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 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.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License along with this program.
* If not, see <https://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.simulator.gui;
import de.steamwar.bausystem.features.simulator.SimulatorWatcher;
import de.steamwar.bausystem.features.simulator.data.Simulator;
import de.steamwar.bausystem.features.simulator.display.SimulatorRenderer;
import de.steamwar.bausystem.features.simulator.gui.base.SimulatorBaseGui;
import de.steamwar.data.CMDs;
import de.steamwar.inventory.SWItem;
@@ -53,52 +55,50 @@ public class SimulatorSettingsGui extends SimulatorBaseGui {
new SimulatorMaterialGui(player, simulator, simulator::getMaterial, simulator::setMaterial, this).open();
}));
// AutoTrace
inventory.setItem(19, new SWItem(simulator.isAutoTrace() ? Material.CHAIN_COMMAND_BLOCK : Material.COMMAND_BLOCK,
"§eAutoTrace§8: " + (simulator.isAutoTrace() ? "§aOn" : "§cOff"), clickType -> {
simulator.setAutoTrace(!simulator.isAutoTrace());
SimulatorRenderer.update(simulator);
}));
inventory.setItem(20, new SWItem(simulator.isAutoTestblock() ? Material.END_STONE : Material.BARRIER,
"§eTestblock§8: " + (simulator.isAutoTestblock() ? "§aOn" : "§cOff"), clickType -> {
simulator.setAutoTestblock(!simulator.isAutoTestblock());
SimulatorRenderer.update(simulator);
}));
//AutoTrace
inventory.setItem(19, new SWItem(simulator.isAutoTrace() ? Material.CHAIN_COMMAND_BLOCK : Material.COMMAND_BLOCK, "§eAutoTrace§8: " + (simulator.isAutoTrace() ? "§aOn" : "§cOff"), clickType -> {
simulator.setAutoTrace(!simulator.isAutoTrace());
SimulatorWatcher.update(simulator);
}));
inventory.setItem(20, new SWItem(simulator.isAutoTestblock() ? Material.END_STONE : Material.BARRIER, "§eTestblock§8: " + (simulator.isAutoTestblock() ? "§aOn" : "§cOff"), clickType -> {
simulator.setAutoTestblock(!simulator.isAutoTestblock());
SimulatorWatcher.update(simulator);
}));
// Pos X
//Pos X
inventory.setItem(15, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
simulator.move(clickType.isShiftClick() ? 5 : 1, 0, 0);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
inventory.setItem(24, new SWItem(Material.PAPER, "§eX", clickType -> {
}));
inventory.setItem(33, new SWItem(SWItem.getDye(1), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
simulator.move(clickType.isShiftClick() ? -5 : -1, 0, 0);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
// Pos Y
//Pos Y
inventory.setItem(16, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
simulator.move(0, clickType.isShiftClick() ? 5 : 1, 0);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
inventory.setItem(25, new SWItem(Material.PAPER, "§eY", clickType -> {
}));
inventory.setItem(34, new SWItem(SWItem.getDye(1), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
simulator.move(0, clickType.isShiftClick() ? -5 : -1, 0);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
// Pos Z
//Pos Z
inventory.setItem(17, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
simulator.move(0, 0, clickType.isShiftClick() ? 5 : 1);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
inventory.setItem(26, new SWItem(Material.PAPER, "§eZ", clickType -> {
}));
inventory.setItem(35, new SWItem(SWItem.getDye(1), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
simulator.move(0, 0, clickType.isShiftClick() ? -5 : -1);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
}
}
@@ -1,27 +1,29 @@
/*
* This file is a part of the SteamWar software.
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
* Copyright (C) 2025 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 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.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License along with this program.
* If not, see <https://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.simulator.gui;
import de.steamwar.bausystem.features.simulator.SimulatorWatcher;
import de.steamwar.bausystem.features.simulator.data.Simulator;
import de.steamwar.bausystem.features.simulator.data.SimulatorGroup;
import de.steamwar.bausystem.features.simulator.data.tnt.TNTElement;
import de.steamwar.bausystem.features.simulator.data.tnt.TNTPhase;
import de.steamwar.bausystem.features.simulator.display.SimulatorRenderer;
import de.steamwar.bausystem.features.simulator.execute.SimulatorStabGenerator;
import de.steamwar.bausystem.features.simulator.gui.base.SimulatorAnvilGui;
import de.steamwar.bausystem.features.simulator.gui.base.SimulatorBaseGui;
@@ -58,7 +60,7 @@ public class SimulatorTNTGui extends SimulatorScrollGui<TNTPhase> {
public void headerAndFooter() {
if (tnt.getPhases().isEmpty()) {
back.open();
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
return;
}
@@ -85,7 +87,7 @@ public class SimulatorTNTGui extends SimulatorScrollGui<TNTPhase> {
inventory.setItem(8, new SWItem(Material.BARRIER, "§eDelete", clickType -> {
tnt.getPhases().clear();
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DELETE));
// Material Chooser
@@ -96,18 +98,16 @@ public class SimulatorTNTGui extends SimulatorScrollGui<TNTPhase> {
inventory.setItem(47, new SWItem(Material.REPEATER, "§eSettings", clickType -> {
new SimulatorTNTSettingsGui(player, simulator, tnt, this).open();
}).setCustomModelData(CMDs.Simulator.SETTINGS));
inventory.setItem(48,
new SWItem(tnt.isDisabled() ? Material.ENDER_PEARL : Material.ENDER_EYE, tnt.isDisabled() ? "§cDisabled" : "§aEnabled", clickType -> {
tnt.setDisabled(!tnt.isDisabled());
SimulatorRenderer.update(simulator);
}).setCustomModelData(CMDs.Simulator.ENABLED_OR_DISABLED));
inventory.setItem(48, new SWItem(tnt.isDisabled() ? Material.ENDER_PEARL : Material.ENDER_EYE, tnt.isDisabled() ? "§cDisabled" : "§aEnabled", clickType -> {
tnt.setDisabled(!tnt.isDisabled());
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.ENABLED_OR_DISABLED));
if (Core.getVersion() > 19) {
inventory.setItem(49, new SWItem(Material.CALIBRATED_SCULK_SENSOR, "§eCreate Stab", click -> {
new SimulatorAnvilGui<>(player, "Depth Limit", "", Integer::parseInt, depthLimit -> {
if (depthLimit <= 0)
return false;
if (depthLimit <= 0) return false;
simulator.setStabGenerator(new SimulatorStabGenerator(Region.getRegion(player.getLocation()), simulator, tnt, depthLimit));
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
return true;
}, null).open();
}).setCustomModelData(CMDs.Simulator.CREATE_STAB));
@@ -117,7 +117,7 @@ public class SimulatorTNTGui extends SimulatorScrollGui<TNTPhase> {
tntElement.add(new TNTPhase());
parent.add(tntElement);
new SimulatorGroupGui(player, simulator, parent, new SimulatorGui(player, simulator)).open();
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.MAKE_GROUP));
inventory.setItem(51, new SWItem(Material.LEAD, "§eJoin Group", clickType -> {
new SimulatorGroupChooserGui(player, simulator, tnt, tnt.getGroup(simulator), this).open();
@@ -126,50 +126,52 @@ public class SimulatorTNTGui extends SimulatorScrollGui<TNTPhase> {
@Override
public SWItem[] column(TNTPhase tntSetting, int index) {
SWItem tnt = new SWItem(Material.TNT, "§eTNT§8:§7 " + tntSetting.getCount(),
Arrays.asList("§7Tick§8: §e" + tntSetting.getTickOffset(), "§7Fuse§8:§e " + tntSetting.getLifetime(), "",
"§7Order§8:§e " + tntSetting.getOrder(), "", "§7X-Jump§8: " + (tntSetting.isXJump() ? "§aOn" : "§cOff"),
"§7Y-Jump§8: " + (tntSetting.isYJump() ? "§aOn" : "§cOff"), "§7Z-Jump§8: " + (tntSetting.isZJump() ? "§aOn" : "§cOff"), "",
"§7Click§8:§e Edit", "§7Middle-Click§8:§e Remove"),
false, clickType -> {
if (clickType == ClickType.MIDDLE) {
this.tnt.getPhases().remove(tntSetting);
SimulatorRenderer.update(simulator);
} else {
new SimulatorTNTPhaseSettingsGui(player, simulator, this.tnt, tntSetting, this).open();
}
});
SWItem tnt = new SWItem(Material.TNT, "§eTNT§8:§7 " + tntSetting.getCount(), Arrays.asList("§7Tick§8: §e" + tntSetting.getTickOffset(), "§7Fuse§8:§e " + tntSetting.getLifetime(), "", "§7Order§8:§e " + tntSetting.getOrder(), "", "§7X-Jump§8: " + (tntSetting.isXJump() ? "§aOn" : "§cOff"), "§7Y-Jump§8: " + (tntSetting.isYJump() ? "§aOn" : "§cOff"), "§7Z-Jump§8: " + (tntSetting.isZJump() ? "§aOn" : "§cOff"), "", "§7Click§8:§e Edit", "§7Middle-Click§8:§e Remove"), false, clickType -> {
if (clickType == ClickType.MIDDLE) {
this.tnt.getPhases().remove(tntSetting);
SimulatorWatcher.update(simulator);
} else {
new SimulatorTNTPhaseSettingsGui(player, simulator, this.tnt, tntSetting, this).open();
}
});
tnt.getItemStack().setAmount(Math.min(tntSetting.getCount(), 64));
return new SWItem[] {new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8:§e +5"), false, clickType -> {
tntSetting.setCount(tntSetting.getCount() + (clickType.isShiftClick() ? 5 : 1));
SimulatorRenderer.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED), tnt,
return new SWItem[]{
new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8:§e +5"), false, clickType -> {
tntSetting.setCount(tntSetting.getCount() + (clickType.isShiftClick() ? 5 : 1));
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED),
tnt,
new SWItem(SWItem.getDye(tntSetting.getCount() > 1 ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8:§e -5"), false, clickType -> {
tntSetting.setCount(Math.max(1, tntSetting.getCount() - (clickType.isShiftClick() ? 5 : 1)));
SimulatorRenderer.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED), new SWItem(Material.ANVIL, "§eEdit Phase", clickType -> {
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED),
new SWItem(Material.ANVIL, "§eEdit Phase", clickType -> {
new SimulatorTNTPhaseSettingsGui(player, simulator, this.tnt, tntSetting, this).open();
}).setCustomModelData(CMDs.Simulator.EDIT_ACTIVATION),};
}).setCustomModelData(CMDs.Simulator.EDIT_ACTIVATION),
};
}
@Override
public SWItem[] lastColumn() {
return new SWItem[] {new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8:§e +5"), false, clickType -> {
addNewPhase(clickType.isShiftClick());
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED), new SWItem(Material.GUNPOWDER, "§eTNT§8:§a New Phase", clickType -> {
addNewPhase(false);
}).setCustomModelData(CMDs.Simulator.NEW_PHASE), new SWItem(SWItem.getDye(8), "§7", clickType -> {
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED),};
return new SWItem[]{
new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8:§e +5"), false, clickType -> {
addNewPhase(clickType.isShiftClick());
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED),
new SWItem(Material.GUNPOWDER, "§eTNT§8:§a New Phase", clickType -> {
addNewPhase(false);
}).setCustomModelData(CMDs.Simulator.NEW_PHASE),
new SWItem(SWItem.getDye(8), "§7", clickType -> {
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED),
};
}
private void addNewPhase(boolean shift) {
TNTPhase lastElement = tnt.getPhases().get(tnt.getPhases().size() - 1);
TNTPhase newPhase = new TNTPhase(lastElement.getTickOffset() + 1);
if (shift)
newPhase.setCount(newPhase.getCount() + 5);
if (shift) newPhase.setCount(newPhase.getCount() + 5);
scroll++;
tnt.add(newPhase);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}
}
@@ -1,27 +1,29 @@
/*
* This file is a part of the SteamWar software.
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
* Copyright (C) 2025 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 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.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License along with this program.
* If not, see <https://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.simulator.gui;
import de.steamwar.bausystem.features.simulator.SimulatorWatcher;
import de.steamwar.bausystem.features.simulator.data.Simulator;
import de.steamwar.bausystem.features.simulator.data.SimulatorPhase;
import de.steamwar.bausystem.features.simulator.data.tnt.TNTElement;
import de.steamwar.bausystem.features.simulator.data.tnt.TNTPhase;
import de.steamwar.bausystem.features.simulator.display.SimulatorRenderer;
import de.steamwar.bausystem.features.simulator.gui.base.SimulatorAnvilGui;
import de.steamwar.bausystem.features.simulator.gui.base.SimulatorBaseGui;
import de.steamwar.core.Core;
@@ -66,26 +68,25 @@ public class SimulatorTNTPhaseSettingsGui extends SimulatorBaseGui {
new SimulatorMaterialGui(player, simulator, tntElement::getMaterial, tntElement::setMaterial, this).open();
}));
// Delete
//Delete
inventory.setItem(8, new SWItem(Material.BARRIER, "§eDelete", clickType -> {
tntElement.getPhases().remove(tnt);
back.open();
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DELETE));
// Count
//Count
int count = tnt.getCount();
inventory.setItem(9, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
tnt.setCount(count + (clickType.isShiftClick() ? 5 : 1));
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
SWItem countItem = new SWItem(Material.TNT, "§eCount§8:§7 " + count, clickType -> {
new SimulatorAnvilGui<>(player, "Count", count + "", Integer::parseInt, integer -> {
if (integer < 1)
return false;
if (integer < 1) return false;
tnt.setCount(integer);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
return true;
}, this).setItem(Material.TNT).open();
});
@@ -94,22 +95,21 @@ public class SimulatorTNTPhaseSettingsGui extends SimulatorBaseGui {
inventory.setItem(27, new SWItem(SWItem.getDye(count > 1 ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
tnt.setCount(Math.max(1, count - (clickType.isShiftClick() ? 5 : 1)));
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
// Tick Offset
//Tick Offset
int offset = tnt.getTickOffset();
inventory.setItem(10, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
tnt.setTickOffset(offset + (clickType.isShiftClick() ? 5 : 1));
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
SWItem offsetItem = new SWItem(Material.REPEATER, "§eStart at§8:§7 " + offset, clickType -> {
new SimulatorAnvilGui<>(player, "Start at", offset + "", Integer::parseInt, integer -> {
if (integer < 0)
return false;
if (integer < 0) return false;
tnt.setTickOffset(integer);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
return true;
}, this).setItem(Material.REPEATER).open();
});
@@ -118,22 +118,21 @@ public class SimulatorTNTPhaseSettingsGui extends SimulatorBaseGui {
inventory.setItem(28, new SWItem(SWItem.getDye(offset > 0 ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
tnt.setTickOffset(Math.max(0, offset - (clickType.isShiftClick() ? 5 : 1)));
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
// Lifetime
//Lifetime
int lifetime = tnt.getLifetime();
inventory.setItem(11, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
tnt.setLifetime(lifetime + (clickType.isShiftClick() ? 5 : 1));
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
SWItem lifetimeItem = new SWItem(Material.CLOCK, "§eLifetime§8:§7 " + lifetime, clickType -> {
new SimulatorAnvilGui<>(player, "Lifetime", lifetime + "", Integer::parseInt, integer -> {
if (integer < 1)
return false;
if (integer < 1) return false;
tnt.setLifetime(integer);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
return true;
}, this).setItem(Material.CLOCK).open();
});
@@ -142,63 +141,56 @@ public class SimulatorTNTPhaseSettingsGui extends SimulatorBaseGui {
inventory.setItem(29, new SWItem(SWItem.getDye(lifetime > 0 ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
tnt.setLifetime(Math.max(1, lifetime - (clickType.isShiftClick() ? 5 : 1)));
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
// Order
//Order
int order = tnt.getOrder();
inventory.setItem(13,
new SWItem(SWItem.getDye(order < SimulatorPhase.ORDER_LIMIT ? 10 : 8), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
tnt.setOrder(Math.min(SimulatorPhase.ORDER_LIMIT, order + (clickType.isShiftClick() ? 5 : 1)));
SimulatorRenderer.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
inventory.setItem(13, new SWItem(SWItem.getDye(order < SimulatorPhase.ORDER_LIMIT ? 10 : 8), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
tnt.setOrder(Math.min(SimulatorPhase.ORDER_LIMIT, order + (clickType.isShiftClick() ? 5 : 1)));
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
Material negativeNumbers = Material.getMaterial(Core.getVersion() >= 19 ? "RECOVERY_COMPASS" : "FIREWORK_STAR");
SWItem orderItem = new SWItem(order >= 0 ? Material.COMPASS : negativeNumbers, "§eCalculation Order§8:§7 " + order, clickType -> {
new SimulatorAnvilGui<>(player, "Calculation Order", order + "", Integer::parseInt, integer -> {
if (integer < -SimulatorPhase.ORDER_LIMIT)
return false;
if (integer > SimulatorPhase.ORDER_LIMIT)
return false;
if (integer < -SimulatorPhase.ORDER_LIMIT) return false;
if (integer > SimulatorPhase.ORDER_LIMIT) return false;
tnt.setOrder(integer);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
return true;
}, this).setItem(order >= 0 ? Material.COMPASS : negativeNumbers).open();
});
orderItem.getItemStack().setAmount(Math.max(1, Math.min(Math.abs(order), 30)));
inventory.setItem(22, orderItem);
inventory.setItem(31,
new SWItem(SWItem.getDye(order > -SimulatorPhase.ORDER_LIMIT ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
tnt.setOrder(Math.max(-SimulatorPhase.ORDER_LIMIT, order - (clickType.isShiftClick() ? 5 : 1)));
SimulatorRenderer.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
inventory.setItem(31, new SWItem(SWItem.getDye(order > -SimulatorPhase.ORDER_LIMIT ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
tnt.setOrder(Math.max(-SimulatorPhase.ORDER_LIMIT, order - (clickType.isShiftClick() ? 5 : 1)));
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
// Jump
SWItem jumpX =
new SWItem(tnt.isXJump() ? Material.LIME_WOOL : Material.RED_WOOL, "§7TNT §eJump X§8: " + (tnt.isZJump() ? "§aon" : "§coff"), clickType -> {
tnt.setXJump(!tnt.isXJump());
SimulatorRenderer.update(simulator);
});
//Jump
SWItem jumpX = new SWItem(tnt.isXJump() ? Material.LIME_WOOL : Material.RED_WOOL, "§7TNT §eJump X§8: " + (tnt.isZJump() ? "§aon" : "§coff"), clickType -> {
tnt.setXJump(!tnt.isXJump());
SimulatorWatcher.update(simulator);
});
inventory.setItem(33, jumpX);
SWItem jumpY =
new SWItem(tnt.isYJump() ? Material.LIME_WOOL : Material.RED_WOOL, "§7TNT §eJump Y§8: " + (tnt.isYJump() ? "§aon" : "§coff"), clickType -> {
tnt.setYJump(!tnt.isYJump());
SimulatorRenderer.update(simulator);
});
SWItem jumpY = new SWItem(tnt.isYJump() ? Material.LIME_WOOL : Material.RED_WOOL, "§7TNT §eJump Y§8: " + (tnt.isYJump() ? "§aon" : "§coff"), clickType -> {
tnt.setYJump(!tnt.isYJump());
SimulatorWatcher.update(simulator);
});
inventory.setItem(16, jumpY);
SWItem jumpZ =
new SWItem(tnt.isZJump() ? Material.LIME_WOOL : Material.RED_WOOL, "§7TNT §eJump Z§8: " + (tnt.isZJump() ? "§aon" : "§coff"), clickType -> {
tnt.setZJump(!tnt.isZJump());
SimulatorRenderer.update(simulator);
});
SWItem jumpZ = new SWItem(tnt.isZJump() ? Material.LIME_WOOL : Material.RED_WOOL, "§7TNT §eJump Z§8: " + (tnt.isZJump() ? "§aon" : "§coff"), clickType -> {
tnt.setZJump(!tnt.isZJump());
SimulatorWatcher.update(simulator);
});
inventory.setItem(35, jumpZ);
SWItem jumpAll = new SWItem(Material.TNT, "§7TNT §eJump §8: " + (tnt.hasJump() ? "§aon" : "§coff"), clickType -> {
tnt.setJump(!tnt.hasJump());
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
});
inventory.setItem(25, jumpAll);
}
@@ -1,25 +1,27 @@
/*
* This file is a part of the SteamWar software.
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
* Copyright (C) 2025 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 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.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License along with this program.
* If not, see <https://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.simulator.gui;
import de.steamwar.bausystem.features.simulator.SimulatorWatcher;
import de.steamwar.bausystem.features.simulator.data.Simulator;
import de.steamwar.bausystem.features.simulator.data.tnt.TNTElement;
import de.steamwar.bausystem.features.simulator.display.SimulatorRenderer;
import de.steamwar.bausystem.features.simulator.gui.base.SimulatorAnvilGui;
import de.steamwar.bausystem.features.simulator.gui.base.SimulatorBaseGui;
import de.steamwar.data.CMDs;
@@ -74,14 +76,13 @@ public class SimulatorTNTSettingsGui extends SimulatorBaseGui {
int baseTicks = tnt.getBaseTick();
inventory.setItem(9, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
tnt.changeBaseTicks(clickType.isShiftClick() ? 5 : 1);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
SWItem baseTick = new SWItem(Material.REPEATER, "§eTicks§8:§7 " + baseTicks, clickType -> {
new SimulatorAnvilGui<>(player, "Ticks", baseTicks + "", Integer::parseInt, integer -> {
if (integer < 0)
return false;
if (integer < 0) return false;
tnt.changeBaseTicks(integer - baseTicks);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
return true;
}, this).setItem(Material.REPEATER).open();
});
@@ -93,46 +94,42 @@ public class SimulatorTNTSettingsGui extends SimulatorBaseGui {
} else {
tnt.changeBaseTicks(clickType.isShiftClick() ? -5 : -1);
}
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
// Subpixel Alignment
inventory.setItem(21, new SWItem(Material.SUNFLOWER, "§7Align§8: §eCenter", clickType -> {
tnt.alignX(0);
tnt.alignZ(0);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}));
// Z
SWItem negativZItem = new SWItem(Material.OAK_BUTTON, "§7Align§8: §eNegativ Z", clickType -> {
if (tnt.getAlignment().getZ() != -1)
tnt.alignZ(-1);
SimulatorRenderer.update(simulator);
if (tnt.getAlignment().getZ() != -1) tnt.alignZ(-1);
SimulatorWatcher.update(simulator);
});
negativZItem.setEnchanted(tnt.getAlignment().getZ() == -1);
inventory.setItem(20, negativZItem);
SWItem positivZItem = new SWItem(Material.OAK_BUTTON, "§7Align§8: §ePositiv Z", clickType -> {
if (tnt.getAlignment().getZ() != 1)
tnt.alignZ(1);
SimulatorRenderer.update(simulator);
if (tnt.getAlignment().getZ() != 1) tnt.alignZ(1);
SimulatorWatcher.update(simulator);
});
positivZItem.setEnchanted(tnt.getAlignment().getZ() == 1);
inventory.setItem(22, positivZItem);
// X
SWItem negativXItem = new SWItem(Material.STONE_BUTTON, "§7Align§8: §eNegativ X", clickType -> {
if (tnt.getAlignment().getX() != -1)
tnt.alignX(-1);
SimulatorRenderer.update(simulator);
if (tnt.getAlignment().getX() != -1) tnt.alignX(-1);
SimulatorWatcher.update(simulator);
});
negativXItem.setEnchanted(tnt.getAlignment().getX() == -1);
inventory.setItem(12, negativXItem);
SWItem positivXItem = new SWItem(Material.STONE_BUTTON, "§7Align§8: §ePositiv X", clickType -> {
if (tnt.getAlignment().getX() != 1)
tnt.alignX(1);
SimulatorRenderer.update(simulator);
SWItem positivXItem = new SWItem(Material.STONE_BUTTON, "§7Align§8: §ePositiv X", clickType -> {
if(tnt.getAlignment().getX() != 1) tnt.alignX(1);
SimulatorWatcher.update(simulator);
});
positivXItem.setEnchanted(tnt.getAlignment().getX() == 1);
inventory.setItem(30, positivXItem);
@@ -140,52 +137,52 @@ public class SimulatorTNTSettingsGui extends SimulatorBaseGui {
// Pos X
inventory.setItem(15, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+0.0625"), false, clickType -> {
tnt.move(clickType.isShiftClick() ? 0.0625 : 1, 0, 0);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
inventory.setItem(24, new SWItem(Material.PAPER, "§eX§8:§7 " + tnt.getPosition().getX(), clickType -> {
new SimulatorAnvilGui<>(player, "X", tnt.getPosition().getX() + "", Double::parseDouble, d -> {
tnt.getPosition().setX(d);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
return true;
}, this).open();
}));
inventory.setItem(33, new SWItem(SWItem.getDye(1), "§e-1", Arrays.asList("§7Shift§8: §e-0.0625"), false, clickType -> {
tnt.move(clickType.isShiftClick() ? -0.0625 : -1, 0, 0);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
// Pos Y
inventory.setItem(16, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+0.0625"), false, clickType -> {
tnt.move(0, clickType.isShiftClick() ? 0.0625 : 1, 0);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
inventory.setItem(25, new SWItem(Material.PAPER, "§eY§8:§7 " + tnt.getPosition().getY(), clickType -> {
new SimulatorAnvilGui<>(player, "Y", tnt.getPosition().getY() + "", Double::parseDouble, d -> {
tnt.getPosition().setY(d);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
return true;
}, this).open();
}));
inventory.setItem(34, new SWItem(SWItem.getDye(1), "§e-1", Arrays.asList("§7Shift§8: §e-0.0625"), false, clickType -> {
tnt.move(0, clickType.isShiftClick() ? -0.0625 : -1, 0);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
// Pos Z
inventory.setItem(17, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+0.0625"), false, clickType -> {
tnt.move(0, 0, clickType.isShiftClick() ? 0.0625 : 1);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
inventory.setItem(26, new SWItem(Material.PAPER, "§eZ§8:§7 " + tnt.getPosition().getZ(), clickType -> {
new SimulatorAnvilGui<>(player, "Z", tnt.getPosition().getZ() + "", Double::parseDouble, d -> {
tnt.getPosition().setZ(d);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
return true;
}, this).open();
}));
inventory.setItem(35, new SWItem(SWItem.getDye(1), "§e-1", Arrays.asList("§7Shift§8: §e-0.0625"), false, clickType -> {
tnt.move(0, 0, clickType.isShiftClick() ? -0.0625 : -1);
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
}
}
@@ -1,24 +1,26 @@
/*
* This file is a part of the SteamWar software.
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
* Copyright (C) 2025 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 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.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License along with this program.
* If not, see <https://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.simulator.gui.base;
import de.steamwar.bausystem.features.simulator.SimulatorWatcher;
import de.steamwar.bausystem.features.simulator.data.Simulator;
import de.steamwar.bausystem.features.simulator.display.SimulatorRenderer;
import de.steamwar.core.Core;
import de.steamwar.inventory.SWInventory;
import de.steamwar.inventory.SWItem;
@@ -43,8 +45,7 @@ public abstract class SimulatorBaseGui {
}
public final void open() {
if (!shouldOpen())
return;
if (!shouldOpen()) return;
String newTitle = title();
String originalTitle = player.getOpenInventory().getTitle();
@@ -57,6 +58,7 @@ public abstract class SimulatorBaseGui {
setup();
if (player.getOpenInventory().getTopInventory() != inv) {
inventory.open();
SimulatorWatcher.watch(player, simulator, this::open);
}
if (Core.getVersion() > 19) {
player.getOpenInventory().setTitle(title());
@@ -68,6 +70,7 @@ public abstract class SimulatorBaseGui {
}
if (player.getOpenInventory().getTopInventory() == inv) {
inventory.open();
SimulatorWatcher.watch(player, simulator, this::open);
}
return;
}
@@ -79,7 +82,11 @@ public abstract class SimulatorBaseGui {
return inv;
});
setup();
inventory.addCloseCallback(clickType -> {
SimulatorWatcher.watch(player, null, null);
});
SimulatorWatcher.watch(player, simulator, this::open);
if (simulator != null && simulator.getStabGenerator() != null) {
populateStabGenerator();
} else {
@@ -91,7 +98,7 @@ public abstract class SimulatorBaseGui {
private void populateStabGenerator() {
inventory.setItem(22, new SWItem(Material.BARRIER, "§cCancel Stab Generator", click -> {
simulator.getStabGenerator().cancel();
SimulatorRenderer.update(simulator);
SimulatorWatcher.update(simulator);
}));
}
@@ -54,7 +54,7 @@ public class YAPIONFormatSimulatorLoader implements SimulatorLoader {
}
String name = file.getName().substring(0, file.getName().length() - 7);
SteamwarUser steamwarUser = SteamwarUser.get(Integer.parseInt(name));
SteamwarUser steamwarUser = SteamwarUser.byId(Integer.parseInt(name));
List<Simulator> simulators = new ArrayList<>();
for (String s : yapionObject.getKeys()) {
@@ -87,6 +87,7 @@ public class MaterialLazyInit {
Block block = Bukkit.getWorlds().get(0).getBlockAt(0, 0, 0);
block.setType(material);
unmoveable = block.getPistonMoveReaction() == PistonMoveReaction.BLOCK || block.getPistonMoveReaction() == PistonMoveReaction.IGNORE || block.getState() instanceof TileState;
block.setType(Material.AIR);
}
if (material.isItem() && material != Material.AIR) {
@@ -41,7 +41,7 @@ public class AntiBauAddMemberFix implements Listener {
}
if (BauweltMember.getBauMember(BauServer.getInstance().getOwner(), event.getPlayer().getUniqueId()) == null) {
event.getPlayer().kickPlayer("");
throw new SecurityException("The player " + event.getPlayer().getName() + " joined on the server of " + SteamwarUser.get(BauServer.getInstance().getOwnerID()).getUserName() + " without being added!");
throw new SecurityException("The player " + event.getPlayer().getName() + " joined on the server of " + SteamwarUser.byId(BauServer.getInstance().getOwnerID()).getUserName() + " without being added!");
}
}
@@ -1,203 +0,0 @@
package de.steamwar.bausystem.utils.cursor;
import de.steamwar.bausystem.utils.RayTraceUtils;
import de.steamwar.entity.REntity;
import de.steamwar.entity.REntityServer;
import de.steamwar.entity.RFallingBlockEntity;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Player;
import org.bukkit.event.block.Action;
import org.bukkit.util.Vector;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.function.BiFunction;
import java.util.function.Predicate;
@Getter
public abstract class Cursor {
private final World WORLD = Bukkit.getWorlds().get(0);
private final REntityServer targetServer;
private final REntityServer cursorServer;
private final Player owner;
private final Material highlightMaterial;
private RFallingBlockEntity cursorEntity;
private Location cursorLocation;
private boolean isHittingEntity = false;
@Setter
private Material cursorMaterial;
@Setter
private List<CursorMode> allowedCursorModes;
private boolean visible = true;
protected Cursor(REntityServer targetServer, Player owner, Material highlightMaterial, Material cursorMaterial, List<CursorMode> allowedModes) {
this.targetServer = targetServer;
this.owner = owner;
this.highlightMaterial = highlightMaterial;
this.cursorMaterial = cursorMaterial;
this.allowedCursorModes = allowedModes;
cursorServer = new REntityServer();
cursorServer.addPlayer(owner);
CursorManager.getInstance().registerCursor(this);
}
public void render() {
if (!visible)
return;
RayTraceUtils.RRayTraceResult rayTraceResult = RayTraceUtils.traceREntity(owner, owner.getLocation(), targetServer.getEntities());
if (rayTraceResult == null) {
if (cursorEntity != null)
cursorEntity.die();
cursorEntity = null;
return;
}
REntity hitEntity = rayTraceResult.getHitEntity() == cursorEntity ? null : rayTraceResult.getHitEntity();
Material activeCursorMaterial = hitEntity == null ? cursorMaterial : highlightMaterial;
CursorMode activeCursorMode = allowedCursorModes.stream().filter((mode) -> mode.isActive.test(owner)).min(Comparator.comparingInt(a -> a.priority))
.orElse(CursorMode.BLOCK_ALIGNED);
Location activeCursorLocation = hitEntity == null ? activeCursorMode.positionTransform.apply(owner, rayTraceResult).toLocation(WORLD)
: new Vector(hitEntity.getX(), hitEntity.getY(), hitEntity.getZ()).toLocation(WORLD);
cursorLocation = activeCursorLocation;
isHittingEntity = hitEntity != null;
if (cursorEntity == null) {
cursorEntity = new RFallingBlockEntity(cursorServer, activeCursorLocation, activeCursorMaterial);
cursorEntity.setNoGravity(true);
} else if (cursorEntity.getMaterial() == activeCursorMaterial) {
cursorEntity.move(activeCursorLocation);
} else {
cursorEntity.die();
cursorEntity = new RFallingBlockEntity(cursorServer, activeCursorLocation, activeCursorMaterial);
cursorEntity.setNoGravity(true);
if (activeCursorMaterial == highlightMaterial) {
cursorEntity.setGlowing(true);
}
}
}
public void hide() {
visible = false;
if (cursorEntity != null) {
cursorEntity.die();
cursorEntity = null;
}
}
public void show() {
visible = true;
}
final void handleClick(Action action) {
if (!visible)
return;
onClick(Optional.ofNullable(this.cursorLocation), isHittingEntity, action);
}
public void close() {
cursorServer.close();
CursorManager.getInstance().unregisterCursor(this);
}
@AllArgsConstructor
public enum CursorMode {
FREE(1, (player, rayTraceResult) -> {
Vector pos = rayTraceResult.getHitPosition();
BlockFace face = rayTraceResult.getHitBlockFace();
if (face != null) {
switch (face) {
case DOWN:
pos.setY(pos.getY() - 0.98);
break;
case EAST:
pos.setX(pos.getX() + 0.49);
break;
case WEST:
pos.setX(pos.getX() - 0.49);
break;
case NORTH:
pos.setZ(pos.getZ() - 0.49);
break;
case SOUTH:
pos.setZ(pos.getZ() + 0.49);
break;
default:
break;
}
if (face.getModY() == 0 && player.isSneaking()) {
pos.setY(pos.getY() - 0.49);
}
}
return pos;
}, (player) -> player.isSneaking()),
BLOCK_ALIGNED(0, (player, rayTraceResult) -> {
Vector pos = rayTraceResult.getHitPosition();
BlockFace face = rayTraceResult.getHitBlockFace();
if (face != null) {
switch (face) {
case DOWN:
pos.setY(pos.getY() - 0.98);
break;
case EAST:
pos.setX(pos.getX() + 0.49);
break;
case WEST:
pos.setX(pos.getX() - 0.49);
break;
case NORTH:
pos.setZ(pos.getZ() - 0.49);
break;
case SOUTH:
pos.setZ(pos.getZ() + 0.49);
break;
default:
break;
}
}
pos.setX(pos.getBlockX() + 0.5);
if (pos.getY() - pos.getBlockY() != 0 && face == BlockFace.UP) {
pos.setY(pos.getBlockY() + 1.0);
} else {
pos.setY(pos.getBlockY());
}
pos.setZ(pos.getBlockZ() + 0.5);
return pos;
}, (player) -> true);
private final int priority;
private final BiFunction<Player, RayTraceUtils.RRayTraceResult, Vector> positionTransform;
private final Predicate<Player> isActive;
}
public abstract void onClick(Optional<Location> cursorLocation, boolean didHitEntity, Action action);
}
@@ -1,118 +0,0 @@
package de.steamwar.bausystem.utils.cursor;
import com.comphenix.tinyprotocol.TinyProtocol;
import de.steamwar.Reflection;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.linkage.Linked;
import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.BiFunction;
@Linked
public class CursorManager implements Listener {
@Getter
private static CursorManager instance;
private final Set<Player> calculationActive = new HashSet<>();
private final Map<Player, List<Cursor>> activeCursors = new HashMap<>();
public CursorManager() {
if (instance == null) {
instance = this;
}
BiFunction<Player, Object, Object> function = (player, object) -> {
updateCursors(player);
return object;
};
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> {
Set<Player> playersWithActiveCursor = activeCursors.keySet();
playersWithActiveCursor.forEach(this::updateCursors);
}, 0);
Class<?> positionPacketClass = Reflection.getClass("net.minecraft.network.protocol.game.ServerboundMovePlayerPacket$Pos");
Class<?> lookPacketClass = Reflection.getClass("net.minecraft.network.protocol.game.ServerboundMovePlayerPacket$Rot");
Class<?> positionLookPacketClass = Reflection.getClass("net.minecraft.network.protocol.game.ServerboundMovePlayerPacket$PosRot");
TinyProtocol.instance.addFilter(positionPacketClass, function);
TinyProtocol.instance.addFilter(lookPacketClass, function);
TinyProtocol.instance.addFilter(positionLookPacketClass, function);
}
void registerCursor(Cursor cursor) {
List<Cursor> cursorsOfPlayer = activeCursors.getOrDefault(cursor.getOwner(), new ArrayList<>());
cursorsOfPlayer.add(cursor);
activeCursors.put(cursor.getOwner(), cursorsOfPlayer);
}
void unregisterCursor(Cursor cursor) {
List<Cursor> cursorsOfPlayer = activeCursors.get(cursor.getOwner());
if (cursorsOfPlayer != null) {
cursorsOfPlayer.remove(cursor);
if (cursorsOfPlayer.isEmpty()) {
activeCursors.remove(cursor.getOwner());
}
}
}
private void closeCursorsOf(Player player) {
List<Cursor> cursorsOfPlayer = activeCursors.remove(player);
if (cursorsOfPlayer != null) {
new ArrayList<>(cursorsOfPlayer).forEach(Cursor::close);
}
}
private void updateCursors(Player player) {
if (!activeCursors.containsKey(player)) {
return;
}
synchronized (calculationActive) {
if (calculationActive.contains(player)) {
return;
} else {
calculationActive.add(player);
}
}
List<Cursor> cursors = activeCursors.get(player);
if (cursors != null) {
cursors.forEach(Cursor::render);
}
synchronized (calculationActive) {
calculationActive.remove(player);
}
}
@EventHandler
private void handlePlayerInteract(PlayerInteractEvent event) {
Player player = event.getPlayer();
List<Cursor> cursorsOfPlayer = activeCursors.get(player);
if (cursorsOfPlayer != null) {
cursorsOfPlayer.forEach(cursor -> cursor.handleClick(event.getAction()));
}
}
@EventHandler
private void handlePlayerQuit(PlayerQuitEvent event) {
closeCursorsOf(event.getPlayer());
}
}
@@ -84,7 +84,12 @@ public class FixedFlagStorage implements FlagStorage {
@Override
public void clear() {
flagMap.clear();
for (Flag flag : Flag.getFlags()) {
if (flag == Flag.TESTBLOCK) continue;
if (flag == Flag.COLOR) continue;
if (flag == Flag.CHANGED) continue;
flagMap.remove(flag);
}
}
@Override
@@ -91,7 +91,12 @@ public class FixedGlobalFlagStorage implements FlagStorage {
@Override
public void clear() {
flagMap.clear();
for (Flag flag : Flag.getFlags()) {
if (flag == Flag.TESTBLOCK) continue;
if (flag == Flag.COLOR) continue;
if (flag == Flag.CHANGED) continue;
flagMap.remove(flag);
}
}
@Override
+1
View File
@@ -50,5 +50,6 @@ tasks.register<DevServer>("DevBau21") {
description = "Run a 1.21 Dev Bau"
dependsOn(":SpigotCore:shadowJar")
dependsOn(":BauSystem:shadowJar")
dependsOn(":SchematicSystem:shadowJar")
template = "Bau21"
}
+27
View File
@@ -0,0 +1,27 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2024 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
plugins {
steamwar.java
}
dependencies {
testImplementation(libs.junit)
testImplementation(libs.hamcrest)
}
@@ -0,0 +1,32 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2024 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
plugins {
steamwar.java
}
java {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
dependencies {
implementation(project(":CommandFramework:CommandFrameworkBase", "default"))
annotationProcessor(project(":CommandFramework:CommandFrameworkBase", "default"))
}
@@ -0,0 +1,5 @@
de.steamwar.command.annotationprocessor.impl.CachedAnnotationProcessor
de.steamwar.command.annotationprocessor.impl.MapperAnnotationProcessor
de.steamwar.command.annotationprocessor.impl.RegisterAnnotationProcessor
de.steamwar.command.annotationprocessor.impl.SupplierAnnotationProcessor
de.steamwar.command.annotationprocessor.impl.ValidatorAnnotationProcessor
@@ -17,29 +17,27 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.sql;
package de.steamwar.command;
import de.steamwar.sql.internal.Field;
import de.steamwar.sql.internal.Statement;
import de.steamwar.sql.internal.Table;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.sql.Timestamp;
import javax.lang.model.element.AnnotationMirror;
import java.lang.annotation.Annotation;
@AllArgsConstructor
public class Session {
public class HandlerForAnnotationMirror<A extends Annotation> implements Handler.AnnotationWrapper<A> {
private static final Table<Session> table = new Table<>(Session.class);
private static final Statement insert = table.insert(Table.PRIMARY);
private A annotation;
public static void insertSession(int userID, Timestamp startTime){
insert.update(userID, startTime);
@Getter
private AnnotationMirror annotationMirror;
public HandlerForAnnotationMirror(A annotation, AnnotationMirror annotationMirror) {
this.annotation = annotation;
this.annotationMirror = annotationMirror;
}
@Field(keys = {Table.PRIMARY})
private int userId;
@Field(keys = {Table.PRIMARY})
private Timestamp startTime;
@Field(def = "CURRENT_TIMESTAMP")
private Timestamp endTime;
@Override
public A getAnnotation() {
return annotation;
}
}
@@ -0,0 +1,68 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.command;
import lombok.Getter;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import java.util.List;
public class HandlerForExecutableElement implements Handler.MethodWrapper {
@Getter
private final ExecutableElement method;
private final Types types;
private final Elements elements;
public HandlerForExecutableElement(ExecutableElement method, Types types, Elements elements) {
this.method = method;
this.types = types;
this.elements = elements;
}
@Override
public String getName() {
return method.getSimpleName().toString();
}
@Override
public int getParameterCount() {
return method.getParameters().size();
}
@Override
public Handler.TypeWrapper getReturnType() {
return new HandlerForTypeMirror(method.getReturnType(), types, elements);
}
@Override
public Handler.ParameterWrapper[] getParameters() {
Handler.ParameterWrapper[] parameters = new Handler.ParameterWrapper[method.getParameters().size()];
List<? extends VariableElement> variableElements = method.getParameters();
for (int i = 0; i < parameters.length; i++) {
VariableElement variableElement = variableElements.get(i);
parameters[i] = new HandlerForVariableElement(variableElement, types, elements, i == parameters.length - 1 && method.isVarArgs());
}
return parameters;
}
}
@@ -0,0 +1,121 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.command;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
public class HandlerForTypeMirror implements Handler.TypeWrapper {
private final TypeMirror type;
private final Types types;
private final Elements elements;
public HandlerForTypeMirror(TypeMirror type, Types types, Elements elements) {
this.type = type;
this.types = types;
this.elements = elements;
}
@Override
public boolean isAssignableTo(Class<?> clazz) {
return types.isAssignable(types.erasure(type), types.erasure(elements.getTypeElement(clazz.getTypeName()).asType()));
}
@Override
public boolean isAssignableTo(Handler.TypeWrapper type) {
if (type instanceof ForClass) {
return isAssignableTo(((ForClass) type).getClazz());
} else if (type instanceof HandlerForTypeMirror) {
return types.isAssignable(types.erasure(this.type), types.erasure(((HandlerForTypeMirror) type).type));
}
return false;
}
@Override
public boolean isPrimitive() {
return type.getKind().isPrimitive();
}
@Override
public boolean isArray() {
return type instanceof ArrayType;
}
@Override
public boolean isEnum() {
if (type.getKind() != TypeKind.DECLARED) {
return false;
}
DeclaredType declaredType = (DeclaredType) type;
Element element = declaredType.asElement();
return element.getKind() == ElementKind.ENUM;
}
@Override
public boolean is(Class<?> clazz) {
if (type.getKind() == TypeKind.VOID && clazz == Void.TYPE) {
return true;
} else if (type.getKind().isPrimitive() && clazz.isPrimitive()) {
return type.toString().equals(clazz.getTypeName());
} else if (!type.getKind().isPrimitive() && !clazz.isPrimitive()) {
return types.isSameType(types.erasure(type), types.erasure(elements.getTypeElement(clazz.getTypeName()).asType()));
} else {
return false;
}
}
@Override
public boolean is(Handler.TypeWrapper type) {
if (type instanceof ForClass) {
return is(((ForClass) type).getClazz());
} else if (type instanceof HandlerForTypeMirror) {
return types.isSameType(types.erasure(this.type), types.erasure(((HandlerForTypeMirror) type).type));
}
return false;
}
@Override
public Handler.TypeWrapper getComponentType() {
if (type instanceof ArrayType) {
return new HandlerForTypeMirror(((ArrayType) type).getComponentType(), types, elements);
} else {
return new HandlerForTypeMirror(null, types, elements);
}
}
@Override
public String getName() {
return type.toString();
}
@Override
public String getTypeName() {
return type.toString();
}
}
@@ -0,0 +1,151 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.command;
import de.steamwar.command.utils.Pair;
import lombok.Getter;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.VariableElement;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import java.lang.annotation.Annotation;
import java.lang.annotation.Repeatable;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
public class HandlerForVariableElement implements Handler.ParameterWrapper {
@Getter
private final VariableElement parameter;
private final Types types;
private final Elements elements;
private final boolean varArgs;
public HandlerForVariableElement(VariableElement variableElement, Types types, Elements elements, boolean varArgs) {
this.parameter = variableElement;
this.types = types;
this.elements = elements;
this.varArgs = varArgs;
}
@Override
public Handler.TypeWrapper getType() {
return new HandlerForTypeMirror(parameter.asType(), types, elements);
}
@Override
public boolean isVarArgs() {
return varArgs;
}
@Override
public boolean isAnnotationPresent(Class<? extends Annotation> annotation) {
return parameter.getAnnotation(annotation) != null;
}
@Override
public <A extends Annotation> Handler.AnnotationWrapper<A> getAnnotation(Class<A> annotation) {
A ann = parameter.getAnnotation(annotation);
AnnotationMirror annMirror = parameter.getAnnotationMirrors()
.stream()
.filter(am -> new HandlerForTypeMirror(am.getAnnotationType(), types, elements).is(annotation))
.findFirst()
.orElse(null);
return new HandlerForAnnotationMirror<>(ann, annMirror);
}
@Override
public String getName() {
return parameter.getSimpleName().toString();
}
@Override
public List<Handler.AnnotationWrapper<?>> getAnnotations() {
return parameter.getAnnotationMirrors()
.stream()
.collect(Collectors.toMap(Function.identity(), annotationMirror -> {
Class<?> clazz = getClass(annotationMirror.getAnnotationType().toString());
if (clazz == null) return null;
return parameter.getAnnotation((Class<? extends Annotation>) clazz);
}))
.entrySet()
.stream()
.filter(entry -> entry.getValue() != null)
.collect(Collectors.toMap(Map.Entry::getKey, entry -> {
Annotation annotation = entry.getValue();
try {
Method method = annotation.annotationType().getMethod("value");
Class<?> returnType = method.getReturnType();
if (!returnType.isArray()) {
return List.of(annotation);
}
Class<?> innerReturnType = returnType.getComponentType();
if (!(innerReturnType.isAnnotation() && innerReturnType.isAnnotationPresent(Repeatable.class))) {
return List.of(annotation);
}
Repeatable repeatable = innerReturnType.getAnnotation(Repeatable.class);
Class<? extends Annotation> containerType = repeatable.value();
if (containerType == returnType) {
throw new UnsupportedOperationException("Repeatable annotation must have a container annotation");
}
try {
return Arrays.asList((Annotation[]) method.invoke(annotation));
} catch (Exception e) {
return List.of(annotation);
}
} catch (NoSuchMethodException e) {
return List.of(annotation);
}
}))
.entrySet()
.stream()
.flatMap(entry -> {
return entry.getValue()
.stream()
.map(annotation -> new Pair<AnnotationMirror, Annotation>(entry.getKey(), annotation));
})
.filter(pair -> pair.b.annotationType().isAnnotationPresent(Handler.Implementation.class))
.map(pair -> new HandlerForAnnotationMirror<>(pair.b, pair.a))
.collect(Collectors.toList());
}
private Class<?> getClass(String name) {
try {
return Class.forName(name);
} catch (ClassNotFoundException e) {
// Ignore
}
if (!name.contains(".")) return null;
Class<?> outerClass = getClass(name.substring(0, name.lastIndexOf('.')));
if (outerClass == null) return null;
name = name.substring(name.lastIndexOf('.') + 1);
for (Class<?> declaredClass : outerClass.getDeclaredClasses()) {
if (declaredClass.getSimpleName().equals(name)) {
return declaredClass;
}
}
return null;
}
}
@@ -0,0 +1,156 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.command.annotationprocessor;
import de.steamwar.command.Handler;
import de.steamwar.command.HandlerForAnnotationMirror;
import de.steamwar.command.HandlerForExecutableElement;
import de.steamwar.command.HandlerForVariableElement;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Messager;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.*;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import javax.tools.Diagnostic;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public abstract class AbstractAnnotationProcessor extends AbstractProcessor {
private Messager messager;
private Types types;
private Elements elements;
public abstract Class<? extends Annotation> getAnnotationClass();
@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);
this.messager = processingEnv.getMessager();
this.types = processingEnv.getTypeUtils();
this.elements = processingEnv.getElementUtils();
}
@Override
public Set<String> getSupportedAnnotationTypes() {
return Collections.singleton(this.getAnnotationClass().getCanonicalName());
}
@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latestSupported();
}
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
List<ExecutableElement> elements = roundEnv.getElementsAnnotatedWith(getAnnotationClass())
.stream()
.filter(element -> element.getKind() == ElementKind.METHOD)
.map(ExecutableElement.class::cast)
.collect(Collectors.toList());
if (elements.isEmpty()) return false;
elements.forEach(element -> {
checkMethodAnnotation(element, element.getAnnotation(getAnnotationClass()));
});
return false;
}
private Handler getHandler(Annotation annotation, Element element) {
Handler.Implementation implementation = annotation.annotationType().getAnnotation(Handler.Implementation.class);
if (implementation == null) return null;
try {
return implementation.value().getConstructor().newInstance();
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException |
InvocationTargetException e) {
messager.printMessage(Diagnostic.Kind.ERROR, "Handler " + implementation.value().getName() + " cannot be used to check the argument validity", element);
return null;
}
}
private void checkMethodAnnotation(ExecutableElement method, Annotation annotation) {
Handler handler = getHandler(annotation, method);
if (handler == null) return;
if (!(handler instanceof Handler.HandlerMethod)) {
messager.printMessage(Diagnostic.Kind.ERROR, "Handler " + handler.getClass().getName() + " is not a HandlerMethod", method);
return;
}
Handler.HandlerMethod handlerMethod = (Handler.HandlerMethod) handler;
try {
handlerMethod.check(new HandlerForAnnotationMirror(annotation, null), new HandlerForExecutableElement(method, types, elements), DataCheckableImpl.INSTANCE);
} catch (Handler.HandlerException e) {
Handler.CodePlace codePlace = e.getCodePlace();
AnnotationMirror[] annotationMirrors = new AnnotationMirror[0];
if (codePlace.getAnnotations().length > 0) {
annotationMirrors = Arrays.stream(codePlace.getAnnotations())
.map(annotationWrapper -> (HandlerForAnnotationMirror) annotationWrapper)
.map(HandlerForAnnotationMirror::getAnnotationMirror)
.toArray(AnnotationMirror[]::new);
}
Element element = null;
if (codePlace.getMethod() != null) {
element = ((HandlerForExecutableElement) codePlace.getMethod()).getMethod();
} else if (codePlace.getParameter() != null) {
element = ((HandlerForVariableElement) codePlace.getParameter()).getParameter();
}
if (annotationMirrors.length > 0) {
for (int i = 0; i < annotationMirrors.length; i++) {
messager.printMessage(Diagnostic.Kind.ERROR, e.getMessage(), element, annotationMirrors[i]);
}
} else {
messager.printMessage(Diagnostic.Kind.ERROR, e.getMessage(), element);
}
}
}
private static final class DataCheckableImpl implements Handler.DataCheckable {
private static final DataCheckableImpl INSTANCE = new DataCheckableImpl();
@Override
public boolean hasExecutorMapper(Class<?> clazz) {
return true;
}
@Override
public boolean hasMapper(String key) {
return true;
}
@Override
public boolean hasValidator(String key) {
return true;
}
@Override
public boolean hasSupplier(String key) {
return true;
}
}
}
@@ -0,0 +1,33 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.command.annotationprocessor.impl;
import de.steamwar.command.annotationprocessor.AbstractAnnotationProcessor;
import de.steamwar.command.annotations.Cached;
import java.lang.annotation.Annotation;
public class CachedAnnotationProcessor extends AbstractAnnotationProcessor {
@Override
public Class<? extends Annotation> getAnnotationClass() {
return Cached.class;
}
}
@@ -0,0 +1,33 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.command.annotationprocessor.impl;
import de.steamwar.command.annotationprocessor.AbstractAnnotationProcessor;
import de.steamwar.command.annotations.Mapper;
import java.lang.annotation.Annotation;
public class MapperAnnotationProcessor extends AbstractAnnotationProcessor {
@Override
public Class<? extends Annotation> getAnnotationClass() {
return Mapper.class;
}
}
@@ -0,0 +1,33 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.command.annotationprocessor.impl;
import de.steamwar.command.annotationprocessor.AbstractAnnotationProcessor;
import de.steamwar.command.annotations.Register;
import java.lang.annotation.Annotation;
public class RegisterAnnotationProcessor extends AbstractAnnotationProcessor {
@Override
public Class<? extends Annotation> getAnnotationClass() {
return Register.class;
}
}
@@ -0,0 +1,33 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.command.annotationprocessor.impl;
import de.steamwar.command.annotationprocessor.AbstractAnnotationProcessor;
import de.steamwar.command.annotations.Supplier;
import java.lang.annotation.Annotation;
public class SupplierAnnotationProcessor extends AbstractAnnotationProcessor {
@Override
public Class<? extends Annotation> getAnnotationClass() {
return Supplier.class;
}
}
@@ -0,0 +1,33 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.command.annotationprocessor.impl;
import de.steamwar.command.annotationprocessor.AbstractAnnotationProcessor;
import de.steamwar.command.annotations.Validator;
import java.lang.annotation.Annotation;
public class ValidatorAnnotationProcessor extends AbstractAnnotationProcessor {
@Override
public Class<? extends Annotation> getAnnotationClass() {
return Validator.class;
}
}
@@ -0,0 +1,27 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2024 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
plugins {
steamwar.java
}
java {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
@@ -0,0 +1,216 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2020 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.command;
import de.steamwar.command.graph.NodeData;
import de.steamwar.command.graph.RootNode;
import de.steamwar.command.utils.Pair;
import de.steamwar.command.utils.Triple;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
public abstract class AbstractCommand<T> {
private static final Map<Class<? extends AbstractCommand<?>>, Map<Class<?>, Function<?, ?>>> EXECUTOR_MAPPER = new HashMap<>();
public static <E, T> void addExecutorMapper(Class<? extends AbstractCommand<E>> wrapper, Class<T> executorType, Function<E, T> mapper) {
EXECUTOR_MAPPER.computeIfAbsent(wrapper, __ -> new HashMap<>())
.putIfAbsent(executorType, mapper);
}
protected final String command;
protected final String permission;
private final Consumer<CommandLoader<T>> initializer;
protected final String[] aliases;
protected final List<String> descriptions = new ArrayList<>();
private boolean initialized = false;
protected final RootNode<T> rootNode = new RootNode<>();
private final Map<String, AbstractTypeMapper<T, ?>> localTypeMapper = new HashMap<>();
private final Map<String, AbstractTypeValidator<T, ?>> localValidators = new HashMap<>();
private final Map<String, AbstractTypeSupplier<T, ?>> localSupplier = new HashMap<>();
protected AbstractCommand(String command, Consumer<CommandLoader<T>> initializer, String... aliases) {
this(command, null, initializer, aliases);
}
protected AbstractCommand(String command, String permission, Consumer<CommandLoader<T>> initializer, String... aliases) {
this.command = command;
this.permission = permission;
this.initializer = initializer;
this.aliases = aliases;
initCommand();
unregister();
register();
}
protected synchronized void initCommand() {
}
public abstract void unregister();
public abstract void register();
protected void commandSystemError(T sender, CommandFrameworkException e) {
Logger.getGlobal().log(Level.WARNING, "An unexpected error occurred", e);
}
protected void sendMessage(T sender, String message, Object[] args) {
}
public final void execute(T sender, String alias, String[] args) {
initialize();
List<Runnable> errors = new ArrayList<>();
try {
boolean executed = rootNode.execute(sender, new NodeData(alias, fixArgs(args, true), (s, args1) -> {
errors.add(() -> sendMessage(sender, s, args1));
}));
if (executed) return;
if (!errors.isEmpty()) {
errors.forEach(Runnable::run);
return;
}
descriptions.forEach(s -> sendMessage(sender, s, new Object[0]));
} catch (CommandFrameworkException e) {
commandSystemError(sender, e);
}
}
public final List<String> tabComplete(T sender, String alias, String[] args) throws IllegalArgumentException {
initialize();
List<Collection<String>> tabCompletes = new ArrayList<>();
rootNode.tabComplete(sender, new NodeData(alias, fixArgs(args, false), (s, args1) -> {}), tabCompletes);
return tabCompletes.stream()
.filter(Objects::nonNull)
.flatMap(Collection::stream)
.filter(Objects::nonNull)
.filter(s -> !s.isEmpty())
.distinct()
.collect(Collectors.toList());
}
private String[] fixArgs(String[] args, boolean allowEmpty) {
int removedCount = 0;
for (int i = 0; i < args.length; i++) {
String arg = args[i];
if (arg.isEmpty() && i != args.length - 1) {
removedCount++;
continue;
}
args[i] = args[i - removedCount];
}
if (removedCount != 0) {
args = Arrays.copyOf(args, args.length - removedCount);
}
if (args.length == 0 && !allowEmpty) {
return new String[]{""};
}
return args;
}
private synchronized void initialize() {
if (initialized) return;
List<Object> commandObjects = new ArrayList<>();
initializer.accept(new CommandLoader<>() {
@Override
public AbstractCommand<T> get() {
return AbstractCommand.this;
}
@Override
public void add(Object command) {
commandObjects.add(command);
}
});
List<Pair<DataImpl, Method>> methods = new ArrayList<>();
for (Object commandObject : commandObjects) {
DataImpl dataImpl = new DataImpl(this, commandObject, rootNode, EXECUTOR_MAPPER.getOrDefault(this.getClass(), Collections.emptyMap()), (Map) localTypeMapper, CommandUtils.MAPPER_FUNCTIONS, (Map) localValidators, CommandUtils.VALIDATOR_FUNCTIONS, (Map) localSupplier, CommandUtils.SUPPLIER_FUNCTIONS);
methods(commandObject).stream()
.filter(method -> Arrays.stream(method.getAnnotations()).anyMatch(anno -> anno.annotationType().isAnnotationPresent(Handler.Implementation.class)))
.forEach(method -> methods.add(new Pair<>(dataImpl, method)));
}
Map<Integer, Map<Triple<DataImpl, Method, Annotation>, List<Handler.HandlerMethod<Annotation>>>> handlerMap = new HashMap<>();
for (Pair<DataImpl, Method> commandMethod : methods) {
List<Annotation> annotations = CommandUtils.getAnnotations(commandMethod.b);
for (Annotation annotation : annotations) {
Handler.Implementation handler = annotation.annotationType().getAnnotation(Handler.Implementation.class);
Handler handlerObject;
try {
handlerObject = handler.value().getConstructor().newInstance();
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException |
InvocationTargetException e) {
throw new UnsupportedOperationException("Handler " + handler.value().getName() + " cannot be used to check the argument validity", e);
}
if (!(handlerObject instanceof Handler.HandlerMethod)) {
throw new UnsupportedOperationException("Handler " + handlerObject.getClass().getName() + " is not a HandlerMethod");
}
handlerMap.computeIfAbsent(((Handler.HandlerMethod<?>) handlerObject).getRunPriority(), k -> new LinkedHashMap<>())
.computeIfAbsent(new Triple<>(commandMethod.a, commandMethod.b, annotation), k -> new ArrayList<>())
.add((Handler.HandlerMethod<Annotation>) handlerObject);
}
}
List<Integer> runPriorities = new ArrayList<>(handlerMap.keySet());
runPriorities.sort(Comparator.naturalOrder());
for (int runPriority : runPriorities) {
handlerMap.get(runPriority).forEach((dataMethodAnnotationTriple, handlerMethods) -> {
handlerMethods.forEach(annotationHandlerMethod -> {
try {
annotationHandlerMethod.check(new Handler.AnnotationWrapper.ForAnnotation<>(dataMethodAnnotationTriple.c), new Handler.MethodWrapper.ForMethod(dataMethodAnnotationTriple.b), dataMethodAnnotationTriple.a);
} catch (Exception e) {
throw new UnsupportedOperationException("Method check failed for " + dataMethodAnnotationTriple.b.getName(), e);
}
annotationHandlerMethod.run(dataMethodAnnotationTriple.c, dataMethodAnnotationTriple.b, dataMethodAnnotationTriple.a);
});
});
}
rootNode.sort();
initialized = true;
}
// TODO: Implement this when Message System is ready
/*
public void addDefaultHelpMessage(String message) {
defaultHelpMessages.add(message);
}
*/
private List<Method> methods(Object commandObject) {
List<Method> methods = new ArrayList<>();
Class<?> current = commandObject.getClass();
while (current != null) {
methods.addAll(Arrays.asList(current.getDeclaredMethods()));
current = current.getSuperclass();
}
return methods;
}
}

Some files were not shown because too many files have changed in this diff Show More