116 Commits

Author SHA1 Message Date
254bcba0af Improve laufbau generating BlockBoundingBox on its own
All checks were successful
SteamWarCI Build successful
2025-11-26 17:07:26 +01:00
5bdbf5dff4 Fix schematic commands for SteamWarLuaPlugin
All checks were successful
SteamWarCI Build successful
Closes: #228
2025-11-25 22:10:14 +01:00
1ae445319a Improve Present.click
All checks were successful
SteamWarCI Build successful
2025-11-25 22:04:44 +01:00
a426a563db Fix SpectatorListener running the techhider all the time
All checks were successful
SteamWarCI Build successful
2025-11-25 21:40:23 +01:00
1098c5617f Redirect to Issue tracker
All checks were successful
SteamWarCI Build successful
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-25 21:11:47 +01:00
c2bca83735 Fix Tab Complete
All checks were successful
SteamWarCI Build successful
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-25 18:37:58 +01:00
cfa1b5d0cd Hotfix XrayCommand bugging players back
All checks were successful
SteamWarCI Build successful
2025-11-25 18:26:48 +01:00
500f8978e5 Fix Schematic List
All checks were successful
SteamWarCI Build successful
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-25 18:12:30 +01:00
395e4a2167 Hotfix windcharges destroying blocks
All checks were successful
SteamWarCI Build successful
2025-11-25 17:37:23 +01:00
1d65f2349e Merge pull request 'Add SWPlayer for per player storage and without Memory Leaks' (#188) from SpigotCore/SWPlayer into main
All checks were successful
SteamWarCI Build successful
Reviewed-on: #188
Reviewed-by: D4rkr34lm <dark@steamwar.de>
2025-11-25 17:00:24 +01:00
c0a4413b7a Merge branch 'main' into SpigotCore/SWPlayer
All checks were successful
SteamWarCI Build successful
2025-11-25 16:59:28 +01:00
6b71ac28fe Merge pull request 'bausystem/TLS' (#184) from bausystem/TLS into main
All checks were successful
SteamWarCI Build successful
Reviewed-on: #184
Reviewed-by: YoyoNow <yoyonow@noreply.localhost>
2025-11-25 16:58:21 +01:00
880c6f5066 Remove TypeGenerator
All checks were successful
SteamWarCI Build successful
2025-11-25 16:37:19 +01:00
e284f8f08c Fix PR
All checks were successful
SteamWarCI Build successful
2025-11-25 12:57:28 +00:00
8a5c5794c0 Replace - with : in translation
All checks were successful
SteamWarCI Build successful
2025-11-25 12:54:10 +00:00
a9e278ccd9 Fix spelling (s.a. PR)
All checks were successful
SteamWarCI Build successful
2025-11-25 12:43:38 +00:00
c9bfcc5c0c Fix not ignoring deleted teams
All checks were successful
SteamWarCI Build successful
Closes: #226
2025-11-24 20:55:58 +01:00
e343d044ff Refactor Discord authentication endpoint for improved error handling and structure
All checks were successful
SteamWarCI Build successful
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-14 23:56:04 +01:00
f923a007a7 Revert "Add EventCache for efficient retrieval of event groups and teams"
All checks were successful
SteamWarCI Build successful
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
78352a3e67 Refactor EventFights and Fight classes to improve player initialization and retrieval
All checks were successful
SteamWarCI Build successful
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-14 23:18:38 +01:00
8d705e7a84 Refactor EventFights and Fight classes to improve player initialization and retrieval
All checks were successful
SteamWarCI Build successful
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-14 23:14:13 +01:00
8b4f864f99 Add EventCache for efficient retrieval of event groups and teams
All checks were successful
SteamWarCI Build successful
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-14 22:47:27 +01:00
f9cb712b07 Merge pull request 'Simplify Tokens and add Discord OAuth' (#220) from authv3 into main
All checks were successful
SteamWarCI Build successful
Reviewed-on: #220
Reviewed-by: YoyoNow <yoyonow@noreply.localhost>
2025-11-14 22:43:04 +01:00
b3b13d2950 Move Chatter.disconnect call to ensure proper execution after IP ban check.
All checks were successful
SteamWarCI Build successful
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-13 23:01:37 +01:00
08ad5edf76 Simplify Tokens and add Discord OAuth
All checks were successful
SteamWarCI Build successful
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-13 14:31:05 +01:00
afcf3a1906 Fix Schematic Move
All checks were successful
SteamWarCI Build successful
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-12 22:52:51 +01:00
33efd26d48 Fix build.gradle.kts
All checks were successful
SteamWarCI Build successful
2025-11-12 07:43:36 +01:00
2a96b3c26a Hotfix AutoCheckerItems for 1.19
Some checks failed
SteamWarCI Build failed
2025-11-11 22:06:44 +01:00
3de4b3871d Hotfix ModifyPart
All checks were successful
SteamWarCI Build successful
2025-11-11 21:42:38 +01:00
67223be80e Trigger rebuild
All checks were successful
SteamWarCI Build successful
2025-11-11 21:28:13 +01:00
81715736ae Refactor TeamTable to introduce default values for color and deleted, and make address column nullable.
All checks were successful
SteamWarCI Build successful
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-11 18:44:46 +01:00
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
58618a3991 Fix FightTeam.removeLeader
All checks were successful
SteamWarCI Build successful
Fix FightTeam.setLeader
2025-11-11 17:36:19 +01:00
e6848b27a0 Refactor FightTable to use WinningTeam enum for win column and adjust related logic.
All checks were successful
SteamWarCI Build successful
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-11 17:25:38 +01:00
93d0011b46 Update openMaterialSelector to exclude non-item materials in UtilGui.
All checks were successful
SteamWarCI Build successful
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-11 17:20:33 +01:00
f56fedefe4 Fix Obsidian and Bedrock
All checks were successful
SteamWarCI Build successful
2025-11-11 17:07:56 +01:00
167bb4e266 Fix YMLWrapper
All checks were successful
SteamWarCI Build successful
2025-11-11 17:05:46 +01:00
f6a9ce184b Closes: #214
All checks were successful
SteamWarCI Build successful
Closes: #215
2025-11-11 16:40:26 +01:00
d5708c110c Refactor NodeDataTable to use default current timestamp for createdAt and ensure schemData reads blob as bytes.
All checks were successful
SteamWarCI Build successful
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-11 00:18:16 +01:00
f23c1215b7 Refactor NodeDataTable to use insert instead of insertIgnore and add blobParam import.
All checks were successful
SteamWarCI Build successful
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-11 00:15:19 +01:00
cfcaf1569c Add GameModeConfig.Schematic.MaxBlastResistance
All checks were successful
SteamWarCI Build successful
2025-11-10 21:39:35 +01:00
dc56b67ff6 Sort fights by start time in descending order and refactor saveFromStream method to use useDb block.
All checks were successful
SteamWarCI Build successful
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-10 14:18:13 +01:00
13c4a3ff8b Sort fights by start time in descending order and refactor saveFromStream method to use useDb block.
All checks were successful
SteamWarCI Build successful
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-10 12:27:02 +01:00
7e5a13989b Sort fights by start time in descending order and refactor saveFromStream method to use useDb block.
All checks were successful
SteamWarCI Build successful
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-10 12:24:51 +01:00
990a03ca6c Add Exposed library dependencies to WebsiteBackend build script.
All checks were successful
SteamWarCI Build successful
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-10 11:57:12 +01:00
4a608fe5b5 Fix SchematicType.fromDB
All checks were successful
SteamWarCI Build successful
2025-11-10 11:55:17 +01:00
5ca15aa117 Refactor PersonalKitTable to use explicit ID column initialization and update create method to utilize insert operation.
All checks were successful
SteamWarCI Build successful
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-10 11:50:39 +01:00
9b459bd12c Refactor PersonalKitTable to use explicit ID column initialization and update create method to utilize insert operation.
Some checks failed
SteamWarCI Build failed
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-10 11:40:34 +01:00
b20d37e252 Refactor PersonalKitTable to use explicit ID column initialization and update create method to utilize insert operation.
Some checks failed
SteamWarCI Build failed
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-10 11:40:20 +01:00
a8c98594a9 Fix GameModeConfig.Schematic.SubTypes
All checks were successful
SteamWarCI Build successful
2025-11-10 11:32:03 +01:00
1c076b5bbf Fix incorrect field references in BauweltMember methods.
All checks were successful
SteamWarCI Build successful
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-10 11:19:56 +01:00
133ddb39cc Add ID column initialization for BauweltMember
All checks were successful
SteamWarCI Build successful
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-10 11:09:57 +01:00
ebb375d8d6 Improve messages
All checks were successful
SteamWarCI Build successful
2025-11-10 11:04:29 +01:00
8ada9a6335 Fix UserElo.getEloFromDb
All checks were successful
SteamWarCI Build successful
2025-11-10 11:01:31 +01:00
0760a5a08a Update build scripts: migrate to Spigot API, adjust JVM toolchains and Java version.
All checks were successful
SteamWarCI Build successful
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-10 09:42:24 +01:00
852ff95757 Update build scripts: migrate to Spigot API, adjust JVM toolchains and Java version.
Some checks failed
SteamWarCI Build failed
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-10 09:40:36 +01:00
5c7d388876 Remove unused SLF4J exclusion from shadowJar task.
All checks were successful
SteamWarCI Build successful
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-10 09:34:44 +01:00
4f92f8132d Remove unused SLF4J exclusion from shadowJar task.
All checks were successful
SteamWarCI Build successful
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-10 09:27:58 +01:00
56fb63f781 Add MySQL dependency to KotlinCore build script.
All checks were successful
SteamWarCI Build successful
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-10 09:17:37 +01:00
273efff87d Remove unused api-version field from plugin.yml.
All checks were successful
SteamWarCI Build successful
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-10 09:16:14 +01:00
0cac6f36c1 Remove unused api-version field from plugin.yml.
All checks were successful
SteamWarCI Build successful
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-10 09:09:44 +01:00
8680b9e6cf Change api dependencies to compileOnlyApi in build.gradle.kts and rename KitName column to Name in PersonalKitTable.
All checks were successful
SteamWarCI Build successful
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-10 09:02:23 +01:00
6c94efaf90 Improve TeamCommand.info
All checks were successful
SteamWarCI Build successful
2025-11-10 09:00:18 +01:00
f6261ad989 Improve output for DevCommand reloadmodes 2025-11-10 09:00:18 +01:00
614e989892 Rename IgnoreTable to IgnoredPlayers in IgnoreSystemTable for improved clarity.
All checks were successful
SteamWarCI Build successful
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-10 08:47:32 +01:00
84e1f605bd Merge pull request 'Exposed!' (#179) from exposed into main
All checks were successful
SteamWarCI Build successful
Reviewed-on: #179
Reviewed-by: YoyoNow <yoyonow@noreply.localhost>
2025-11-10 08:42:59 +01:00
0ea5a62dbe Merge branch 'main' into exposed
All checks were successful
SteamWarCI Build successful
2025-11-10 08:40:42 +01:00
0eb6047139 Merge remote-tracking branch 'origin/exposed' into exposed
All checks were successful
SteamWarCI Build successful
2025-11-09 17:48:12 +01:00
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
dd14e9f518 Cleanup Session
All checks were successful
SteamWarCI Build successful
2025-11-09 17:30:21 +01:00
6c5239c8fc Optimize imports across SQL module: replace explicit class imports with wildcard imports, remove unused imports for cleaner structure.
All checks were successful
SteamWarCI Build successful
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-09 17:28:40 +01:00
fc71f47add Remove needsAdmin property from PunishmentType enum and refactor related declarations for cleaner structure.
All checks were successful
SteamWarCI Build successful
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-09 17:25:19 +01:00
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.
All checks were successful
SteamWarCI Build successful
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-08 22:44:22 +01:00
ebc6f50261 Refactor Gradle build scripts: update source set exclusions, add java-library plugin, and remove redundant configurations in SQL module.
Some checks failed
SteamWarCI Build failed
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-08 13:52:27 +01:00
c9d74fb656 Remove redundant SQL logger in useDb and extra newlines in SQLConfig.
All checks were successful
SteamWarCI Build successful
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-07 18:59:01 +01:00
e50e52950b Refactor Token and SteamwarUser classes: enhance owner property with memoized transformation, increase hash generation key size, and ensure database usage in useDb block.
All checks were successful
SteamWarCI Build successful
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-07 18:57:34 +01:00
aaccd4b095 Merge branch 'main' into SpigotCore/SWPlayer
All checks were successful
SteamWarCI Build successful
2025-11-07 15:41:56 +01:00
14045a3366 Update method name in Countingwand
All checks were successful
SteamWarCI Build successful
2025-11-07 15:30:18 +01:00
e5a61226ca Add newline at end of build.gradle.kts file for consistency.
All checks were successful
SteamWarCI Build successful
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-07 15:06:37 +01:00
cc3b93a8f6 Improve SelectAdjacent
All checks were successful
SteamWarCI Build successful
2025-11-07 14:54:57 +01:00
0c35ace5e2 Remove redundant Java installation paths in Gradle configuration.
Some checks failed
SteamWarCI Build failed
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-07 14:54:30 +01:00
23bcf14ca5 Update Gradle configuration to specify multiple Java installation paths for compatibility.
Some checks failed
SteamWarCI Build failed
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-07 14:53:07 +01:00
58460416c3 Improve WarpListener
All checks were successful
SteamWarCI Build successful
2025-11-07 14:49:10 +01:00
40ac7b2139 Improve NoClipCommand
All checks were successful
SteamWarCI Build successful
Improve SelectBauGuiItem
2025-11-07 14:43:52 +01:00
63a5fcff97 Add Kotlin plugin and configure build scripts for Kotlin compatibility, integrate exposed library dependencies, and enhance JVM settings.
Some checks failed
SteamWarCI Build failed
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-07 14:40:10 +01:00
b69adcd362 Improve MaterialCommand
All checks were successful
SteamWarCI Build successful
2025-11-07 14:34:30 +01:00
ceb8d2c6d4 Improve LaufbauUtils
All checks were successful
SteamWarCI Build successful
2025-11-07 14:21:05 +01:00
39b3cdb897 Introduce GDPRQuery command for GDPR data generation, refactor SQL statements, and improve null safety across modules.
Some checks failed
SteamWarCI Build failed
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-07 12:42:15 +01:00
26b4d8578a Improve ScriptRunner
All checks were successful
SteamWarCI Build successful
2025-11-07 09:43:11 +01:00
51411ceabe Improve ScriptRunner
All checks were successful
SteamWarCI Build successful
2025-11-07 09:34:28 +01:00
1ccc2c4b55 Improve Loader
All checks were successful
SteamWarCI Build successful
Improve ObserverTracer
2025-11-07 09:25:40 +01:00
941a1916b7 Improve Detonator
All checks were successful
SteamWarCI Build successful
2025-11-07 09:12:17 +01:00
6b8f791497 Add SWPlayer for per player storage and without Memory Leaks
All checks were successful
SteamWarCI Build successful
2025-11-06 21:38:24 +01:00
6ac0143459 Remove outdated SQL-related Java classes (GDPRQuery, Field, SelectStatement, SqlTypeMapper, Statement) and update references across modules.
Some checks failed
SteamWarCI Build failed
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-06 11:30:01 +01:00
56bc75763b Migrate Token class to Kotlin, remove outdated Java implementation, and refactor references across modules. Update timestamp fields to use CurrentTimestamp where applicable.
Some checks failed
SteamWarCI Build failed
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-05 21:44:52 +01:00
8272c73b48 Migrate SQL-related classes (Referee, SchemElo, Script, Session, SWException, TeamTeilnahme) to Kotlin and remove outdated Java implementations. Update references across modules.
Some checks failed
SteamWarCI Build failed
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-05 17:47:30 +01:00
9acfb32ae0 Refactor SQL classes: update GameModeConfig functions, improve null safety in SchematicNode and SchematicType, and adjust NodeMemberTable structure.
Some checks failed
SteamWarCI Build failed
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-05 17:04:01 +01:00
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
acf9325179 Add Help messages and small refactor
All checks were successful
SteamWarCI Build successful
2025-11-04 21:02:57 +00:00
89e2df0eb2 Migrate Punishment and PollAnswer classes to Kotlin and remove outdated Java implementations. Update references across modules.
Some checks failed
SteamWarCI Build failed
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-04 21:17:53 +01:00
ca3a7a82be Add /tb default subcommand
All checks were successful
SteamWarCI Build successful
2025-11-04 15:52:41 +00:00
0e5a03e139 Added tls toggle 2025-11-04 15:18:29 +00:00
73da9179bf Migrate SQL-related classes (IgnoreSystem, Mod, NodeDownload, NodeMember) to Kotlin and remove old Java implementations. Update references across modules.
Some checks failed
SteamWarCI Build failed
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-02 19:28:14 +01:00
0fbbcdacea Migrate Fight, FightPlayer, and SchematicType classes to Kotlin and remove old Java implementations. Update references across modules.
Some checks failed
SteamWarCI Build failed
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-11-01 13:52:26 +01:00
4e6933f2fd Remove Event-related SQL classes and update relevant references across modules
Some checks failed
SteamWarCI Build failed
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-10-30 23:14:25 +01:00
eea1073892 Migrate Event class to Kotlin and update references across modules
Some checks failed
SteamWarCI Build failed
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-10-29 23:17:17 +01:00
702aa1cfa6 Refactor CheckedSchematic and migrate to Kotlin
Some checks failed
SteamWarCI Build failed
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-10-29 17:42:29 +01:00
6ea73f4890 Refactor NodeData
Some checks failed
SteamWarCI Build failed
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-10-28 22:25:31 +01:00
14e82f36a5 Rename .java to .kt
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-10-28 22:25:31 +01:00
a8eaf3daa7 Fixes
Some checks failed
SteamWarCI Build failed
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-10-28 21:31:57 +01:00
b51ea484e4 Refactor UserConfig
Some checks failed
SteamWarCI Build failed
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-10-28 20:38:02 +01:00
8bef19ed8b Rename .java to .kt
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-10-28 20:38:02 +01:00
1aff7b30a6 Refactor SchematicNode
Some checks failed
SteamWarCI Build failed
2025-10-28 19:03:30 +01:00
c8ac984ad3 Rename .java to .kt 2025-10-28 19:03:30 +01:00
a462231bab Starting...
Some checks failed
SteamWarCI Build failed
2025-10-27 18:34:31 +01:00
e6bbb76a0b Rename .java to .kt 2025-10-27 18:34:30 +01:00
232 changed files with 5696 additions and 7804 deletions

View File

@@ -0,0 +1,46 @@
/*
* 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.utils;
import net.minecraft.network.protocol.game.ServerboundMovePlayerPacket;
import net.minecraft.server.level.ServerPlayer;
import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.bukkit.entity.Player;
public class PlayerMovementWrapper21 implements PlayerMovementWrapper {
@Override
public void setPosition(Player player, Object object) {
ServerboundMovePlayerPacket packetPlayInFlying = ((ServerboundMovePlayerPacket) object);
ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle();
if (packetPlayInFlying.hasPos) {
serverPlayer.setPosRaw(packetPlayInFlying.x, packetPlayInFlying.y, packetPlayInFlying.z);
}
if (packetPlayInFlying.hasRot) {
serverPlayer.setXRot(packetPlayInFlying.xRot);
serverPlayer.setYRot(packetPlayInFlying.yRot);
}
}
@Override
public Object convertToOut(Player player, Object object) {
return object;
}
}

View File

@@ -1030,6 +1030,7 @@ SCHEMATIC_GUI_ITEM=§eSchematics
# TNTListener # TNTListener
TLS_MESSAGE_79=§7TLS§8> §7Tick §e{0} §8- §7TNT §e{1} TLS_MESSAGE_79=§7TLS§8> §7Tick §e{0} §8- §7TNT §e{1}
TLS_MESSAGE_80=§7TLS§8> §7Tick §e{0} §8- §7TNT §e{1} §8(§e{2} §7with Fuse 80§8) TLS_MESSAGE_80=§7TLS§8> §7Tick §e{0} §8- §7TNT §e{1} §8(§e{2} §7with Fuse 80§8)
TLS_START_HELP=§8/§etls start §8: §7Start the TNT Listener TLS_START_HELP=§8/§etls start §8- §7Start the TNT Listener
TLS_STOP_HELP=§8/§etls stop §8: §7Stop the TNT Listener TLS_STOP_HELP=§8/§etls stop §8- §7Stop the TNT Listener
TLS_SCOREBOARD_ELEMENT=§eTLS§8: §aon TLS_SCOREBOARD_ELEMENT=§eTLS§8: §aon
TLS_TOGGLE_HELP=§8/§etls§8: §7Toggle the TNT Listener

View File

@@ -961,6 +961,7 @@ TYPEREPLACE_HELP=§8//§etyreplace §8[§7type§8] §8[§7type§8] §8- §7Erset
# Schematics # Schematics
SCHEMATIC_GUI_ITEM=§eSchematics SCHEMATIC_GUI_ITEM=§eSchematics
TLS_MESSAGE_80=§7TLS§8> §7Tick §e{0} §8- §7TNT §e{1} §8(§e{2} §7mit Fuse 80§8) TLS_MESSAGE_80=§7TLS§8> §7Tick §e{0} §8- §7TNT §e{1} §8(§e{2} §7mit Fuse 80§8)
TLS_START_HELP=§8/§etls start §8: §7Starte den TNT Listener TLS_START_HELP=§8/§etls start §8- §7Starte den TNT Listener
TLS_STOP_HELP=§8/§etls stop §8: §7Stope den TNT Listener TLS_STOP_HELP=§8/§etls stop §8- §7Stope den TNT Listener
TLS_SCOREBOARD_ELEMENT=§eTLS§8: §aan TLS_SCOREBOARD_ELEMENT=§eTLS§8: §aan
TLS_TOGGLE_HELP=§8/§etls §8: §7Toggle den TNT Listener

View File

@@ -110,9 +110,6 @@ public class BauSystem extends JavaPlugin implements Listener {
if (any instanceof ConfigConverter) { if (any instanceof ConfigConverter) {
Config.addConfigConverter((ConfigConverter) any); Config.addConfigConverter((ConfigConverter) any);
} }
if (any instanceof BoundingBoxLoader) {
((BoundingBoxLoader) any).load();
}
} }
}; };
try { try {

View File

@@ -27,8 +27,6 @@ import de.steamwar.sql.SteamwarUser;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Predicate; import java.util.function.Predicate;
@AllArgsConstructor @AllArgsConstructor
@@ -39,13 +37,12 @@ public enum Permission {
return bauweltMember.isSupervisor(); return bauweltMember.isSupervisor();
}), }),
BUILD(bauweltMember -> { BUILD(bauweltMember -> {
if (isTempOnlySpectator(bauweltMember)) return false;
return bauweltMember.isBuild() || SUPERVISOR.permissionPredicate.test(bauweltMember); return bauweltMember.isBuild() || SUPERVISOR.permissionPredicate.test(bauweltMember);
}), }),
/** /**
* Only used for {@link BauMemberUpdate} * Only used for {@link BauMemberUpdate}
*/ */
REAL_SPECTATOR(bauweltMember -> { SPECTATOR(bauweltMember -> {
return !bauweltMember.isBuild() && !bauweltMember.isSupervisor(); return !bauweltMember.isBuild() && !bauweltMember.isSupervisor();
}), }),
/** /**
@@ -55,28 +52,6 @@ public enum Permission {
return true; return true;
}); });
private static final Set<Integer> TEMP_ONLY_SPECTATOR = new HashSet<>();
private static boolean isTempOnlySpectator(BauweltMember bauweltMember) {
return TEMP_ONLY_SPECTATOR.contains(bauweltMember.getMemberID());
}
public static boolean isTempOnlySpectator(Player player) {
return TEMP_ONLY_SPECTATOR.contains(SteamwarUser.get(player.getUniqueId()).getId());
}
public static void forceOnlySpectator(Player player) {
TEMP_ONLY_SPECTATOR.add(SteamwarUser.get(player.getUniqueId()).getId());
BauMemberUpdate.baumemberUpdate();
}
/**
* Only used by {@link BauMemberUpdate}
*/
public static void removeForceOnlySpectator(Player player) {
TEMP_ONLY_SPECTATOR.remove(SteamwarUser.get(player.getUniqueId()).getId());
}
private final Predicate<BauweltMember> permissionPredicate; private final Predicate<BauweltMember> permissionPredicate;
public boolean hasPermission(BauweltMember bauweltMember) { public boolean hasPermission(BauweltMember bauweltMember) {
@@ -86,10 +61,10 @@ public enum Permission {
public boolean hasPermission(Player member) { public boolean hasPermission(Player member) {
if (SteamwarUser.get(member.getUniqueId()).getId() == BauServer.getInstance().getOwnerID()) { if (SteamwarUser.get(member.getUniqueId()).getId() == BauServer.getInstance().getOwnerID()) {
return this != REAL_SPECTATOR; return this != SPECTATOR;
} }
BauweltMember bauweltMember = BauweltMember.getBauMember(BauServer.getInstance().getOwner(), member.getUniqueId()); BauweltMember bauweltMember = BauweltMember.getBauMember(BauServer.getInstance().getOwner(), member.getUniqueId());
if (bauweltMember == null) return this == REAL_SPECTATOR; if (bauweltMember == null) return this == SPECTATOR;
return permissionPredicate.test(bauweltMember); return permissionPredicate.test(bauweltMember);
} }
} }

View File

@@ -36,7 +36,7 @@ public class BauServer {
private Integer owner; private Integer owner;
public UUID getOwner() { public UUID getOwner() {
return SteamwarUser.get(getOwnerID()).getUUID(); return SteamwarUser.byId(getOwnerID()).getUUID();
} }
public int getOwnerID() { public int getOwnerID() {

View File

@@ -1,71 +0,0 @@
/*
* 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.bau;
import de.steamwar.bausystem.Permission;
import de.steamwar.command.PreviousArguments;
import de.steamwar.command.SWCommand;
import de.steamwar.command.TypeMapper;
import de.steamwar.linkage.Linked;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.Collection;
import java.util.stream.Collectors;
@Linked
public class ForceSpectatorCommand extends SWCommand {
public ForceSpectatorCommand() {
super("forcespectator");
}
@Register
public void forceSpectator(@Validator("supervisor") Player player, @Mapper("builder") Player other) {
Permission.forceOnlySpectator(other);
}
@Mapper("builder")
public TypeMapper<Player> spectatorMapper() {
return new TypeMapper<>() {
@Override
public Player map(CommandSender commandSender, String[] previousArguments, String s) {
Player player = Bukkit.getPlayer(s);
if (player == null) {
return null;
}
if (Permission.BUILD.hasPermission(player) && !Permission.SUPERVISOR.hasPermission(player)) {
return player;
}
return null;
}
@Override
public Collection<String> tabCompletes(CommandSender sender, PreviousArguments previousArguments, String s) {
return Bukkit.getOnlinePlayers().stream()
.filter(Permission.BUILD::hasPermission)
.filter(player -> !Permission.SUPERVISOR.hasPermission(player))
.map(Player::getName)
.collect(Collectors.toList());
}
};
}
}

View File

@@ -47,7 +47,7 @@ public class InfoCommand extends SWCommand {
@Register(description = "BAU_INFO_COMMAND_HELP") @Register(description = "BAU_INFO_COMMAND_HELP")
public void genericCommand(Player p) { 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()); Region region = Region.getRegion(p.getLocation());
for (Flag flag : Flag.getFlags()) { for (Flag flag : Flag.getFlags()) {
if (!region.getFlags().has(flag).isApplicable()) continue; if (!region.getFlags().has(flag).isApplicable()) continue;
@@ -97,7 +97,7 @@ public class InfoCommand extends SWCommand {
st.append("§8, "); st.append("§8, ");
} }
st.append("§7"); st.append("§7");
st.append(SteamwarUser.get(bauweltMembers.get(i).getMemberID()).getUserName()); st.append(SteamwarUser.byId(bauweltMembers.get(i).getMemberID()).getUserName());
} }
return st.toString(); return st.toString();
} }

View File

@@ -21,9 +21,10 @@ package de.steamwar.bausystem.features.countingwand;
import de.steamwar.bausystem.BauSystem; import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.region.Point; import de.steamwar.bausystem.region.Point;
import de.steamwar.bausystem.shared.Pair;
import de.steamwar.bausystem.utils.ItemUtils; import de.steamwar.bausystem.utils.ItemUtils;
import de.steamwar.core.SWPlayer;
import de.steamwar.inventory.SWItem; import de.steamwar.inventory.SWItem;
import lombok.Data;
import lombok.experimental.UtilityClass; import lombok.experimental.UtilityClass;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@@ -31,13 +32,32 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.ItemMeta;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@UtilityClass @UtilityClass
public class Countingwand { public class Countingwand {
@Data
public class CountingWandComponent implements SWPlayer.Component {
private Point pos1;
private Point pos2;
public boolean setPosition(boolean pos1, Point point) {
if (this.pos1 == null || this.pos2 == null) {
this.pos1 = point;
this.pos2 = point;
return true;
}
Point current = pos1 ? this.pos1 : this.pos2;
if (current.equals(point)) return false;
if (pos1) {
this.pos1 = point;
} else {
this.pos2 = point;
}
return true;
}
}
public static ItemStack getWandItem(Player player) { public static ItemStack getWandItem(Player player) {
ItemStack itemStack = new SWItem(Material.STICK, BauSystem.MESSAGE.parse("COUNTINGWAND_ITEM_NAME", player), Arrays.asList(BauSystem.MESSAGE.parse("COUNTINGWAND_ITEM_LORE1", player), BauSystem.MESSAGE.parse("COUNTINGWAND_ITEM_LORE2", player)), false, null).getItemStack(); ItemStack itemStack = new SWItem(Material.STICK, BauSystem.MESSAGE.parse("COUNTINGWAND_ITEM_NAME", player), Arrays.asList(BauSystem.MESSAGE.parse("COUNTINGWAND_ITEM_LORE1", player), BauSystem.MESSAGE.parse("COUNTINGWAND_ITEM_LORE2", player)), false, null).getItemStack();
ItemUtils.setItem(itemStack, "countingwand"); ItemUtils.setItem(itemStack, "countingwand");
@@ -47,61 +67,20 @@ public class Countingwand {
return itemStack; return itemStack;
} }
private final Map<String, Pair<Point, Point>> selections = new HashMap<>(); public boolean isCountingwand(ItemStack itemStack) {
return ItemUtils.isItem(itemStack, "countingwand");
}
public boolean isCountingwand(ItemStack itemStack) { public void checkSelection(final Point point, final boolean pos1, final Player p) {
return ItemUtils.isItem(itemStack, "countingwand"); SWPlayer player = SWPlayer.of(p);
} CountingWandComponent countingWandComponent = player.getComponentOrDefault(CountingWandComponent.class, CountingWandComponent::new);
if (countingWandComponent.setPosition(pos1, point)) {
public void checkSelection(final Point point, final boolean pos1, final Player p) { Point point1 = countingWandComponent.pos1;
Pair<Point, Point> selection = selections.get(p.getUniqueId().toString()); Point point2 = countingWandComponent.pos2;
final boolean newPos; int amount = (Math.abs(point1.getX() - point2.getX()) + 1) * (Math.abs(point1.getY() - point2.getY()) + 1) * (Math.abs(point1.getZ() - point2.getZ()) + 1);
if (selection != null) { String dimension = player.using(BauSystem.MESSAGE).parse("COUNTINGWAND_MESSAGE_VOLUME", amount);
if (pos1) { String volume = player.parse("COUNTINGWAND_MESSAGE_DIMENSION", Math.abs(point1.getX() - point2.getX()) + 1, Math.abs(point1.getY() - point2.getY()) + 1, Math.abs(point1.getZ() - point2.getZ()) + 1);
newPos = !point.equals(selection.setKey(point)); player.sendMessage(pos1 ? "COUNTINGWAND_MESSAGE_RCLICK" : "COUNTINGWAND_MESSAGE_LCLICK", point.getX(), point.getY(), point.getZ(), dimension, volume);
} else { }
newPos = !point.equals(selection.setValue(point)); }
}
} else {
if (pos1) {
selection = new Pair<>(point, null);
} else {
selection = new Pair<>(null, point);
}
selections.put(p.getUniqueId().toString(), selection);
newPos = true;
}
if (newPos) {
String dimension = getDimensions(p, selection.getKey(), selection.getValue());
String volume = getVolume(p, selection.getKey(), selection.getValue());
if (pos1) {
BauSystem.MESSAGE.send("COUNTINGWAND_MESSAGE_RCLICK", p, point.getX(), point.getY(), point.getZ(), dimension, volume);
} else {
BauSystem.MESSAGE.send("COUNTINGWAND_MESSAGE_LCLICK", p, point.getX(), point.getY(), point.getZ(), dimension, volume);
}
}
}
public void removePlayer(Player p) {
selections.remove(p.getUniqueId().toString());
}
public String getVolume(Player player, final Point point1, final Point point2) {
if (point1 == null || point2 == null) {
return BauSystem.MESSAGE.parse("COUNTINGWAND_MESSAGE_VOLUME", player, 0);
}
return BauSystem.MESSAGE.parse("COUNTINGWAND_MESSAGE_VOLUME", player, getAmount(point1, point2));
}
public String getDimensions(Player player, final Point point1, final Point point2) {
if (point1 == null || point2 == null) {
return BauSystem.MESSAGE.parse("COUNTINGWAND_MESSAGE_DIMENSION", player, 0, 0, 0);
}
return BauSystem.MESSAGE.parse("COUNTINGWAND_MESSAGE_DIMENSION", player, Math.abs(point1.getX() - point2.getX()) + 1, Math.abs(point1.getY() - point2.getY()) + 1, Math.abs(point1.getZ() - point2.getZ()) + 1);
}
public int getAmount(final Point point1, final Point point2) {
return (Math.abs(point1.getX() - point2.getX()) + 1) * (Math.abs(point1.getY() - point2.getY()) + 1) * (Math.abs(point1.getZ() - point2.getZ()) + 1);
}
} }

View File

@@ -27,7 +27,6 @@ import org.bukkit.event.Listener;
import org.bukkit.event.block.Action; import org.bukkit.event.block.Action;
import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.util.RayTraceResult; import org.bukkit.util.RayTraceResult;
import java.util.Objects; import java.util.Objects;
@@ -67,9 +66,4 @@ public class CountingwandListener implements Listener {
event.setCancelled(true); event.setCancelled(true);
Countingwand.checkSelection(Point.fromLocation(Objects.requireNonNull(event.getClickedBlock()).getLocation()), false, event.getPlayer()); Countingwand.checkSelection(Point.fromLocation(Objects.requireNonNull(event.getClickedBlock()).getLocation()), false, event.getPlayer());
} }
@EventHandler
public void onLeave(PlayerQuitEvent event) {
Countingwand.removePlayer(event.getPlayer());
}
} }

View File

@@ -25,8 +25,11 @@ import de.steamwar.bausystem.configplayer.Config;
import de.steamwar.bausystem.features.autostart.AutostartListener; import de.steamwar.bausystem.features.autostart.AutostartListener;
import de.steamwar.bausystem.features.detonator.storage.DetonatorStorage; import de.steamwar.bausystem.features.detonator.storage.DetonatorStorage;
import de.steamwar.bausystem.features.detonator.storage.ItemStorage; import de.steamwar.bausystem.features.detonator.storage.ItemStorage;
import de.steamwar.core.SWPlayer;
import de.steamwar.entity.REntityServer; import de.steamwar.entity.REntityServer;
import de.steamwar.entity.RFallingBlockEntity; import de.steamwar.entity.RFallingBlockEntity;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.UtilityClass; import lombok.experimental.UtilityClass;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
@@ -45,7 +48,28 @@ import java.util.*;
@UtilityClass @UtilityClass
public class Detonator { public class Detonator {
private static final Map<Player, REntityServer> ENTITIES_MAP = new HashMap<>(); public class DetonatorComponent implements SWPlayer.Component {
private final REntityServer entities = new REntityServer();
@Getter
@Setter
private boolean hasUpdated = false;
@Override
public void onMount(SWPlayer player) {
entities.addPlayer(player.getPlayer());
entities.setCallback((player1, entity, action) -> {
Vector vector = new Vector(entity.getX(), entity.getY(), entity.getZ());
DetonatorListener.addLocationToDetonator(vector.toLocation(player.getWorld()).getBlock().getLocation(), player1);
});
}
@Override
public void onUnmount(SWPlayer player) {
entities.close();
}
}
private static final Vector HALF = new Vector(0.5, 0, 0.5); private static final Vector HALF = new Vector(0.5, 0, 0.5);
public static boolean isDetonator(ItemStack itemStack) { public static boolean isDetonator(ItemStack itemStack) {
@@ -53,28 +77,19 @@ public class Detonator {
} }
public static void showDetonator(Player p, List<Location> locs) { public static void showDetonator(Player p, List<Location> locs) {
if (ENTITIES_MAP.containsKey(p)) return; DetonatorComponent detonatorComponent = SWPlayer.of(p).getComponentOrDefault(DetonatorComponent.class, DetonatorComponent::new);
REntityServer entities = new REntityServer();
entities.setCallback((player, rEntity, entityAction) -> {
Vector vector = new Vector(rEntity.getX(), rEntity.getY(), rEntity.getZ());
DetonatorListener.addLocationToDetonator(vector.toLocation(player.getWorld()).getBlock().getLocation(), player);
DetonatorListener.HAS_UPDATED.add(player);
});
entities.addPlayer(p);
ENTITIES_MAP.put(p, entities);
locs.forEach(location -> { locs.forEach(location -> {
RFallingBlockEntity entity = new RFallingBlockEntity(entities, location.clone().add(HALF), Material.RED_STAINED_GLASS); RFallingBlockEntity entity = new RFallingBlockEntity(detonatorComponent.entities, location.clone().add(HALF), Material.RED_STAINED_GLASS);
entity.setNoGravity(true); entity.setNoGravity(true);
}); });
} }
public static void hideDetonator(Player p) { public static void hideDetonator(Player p) {
ENTITIES_MAP.remove(p).close(); SWPlayer.of(p).removeComponent(DetonatorComponent.class);
} }
public static boolean hasActiveDetonatorShow(Player p) { public static boolean hasActiveDetonatorShow(Player p) {
return ENTITIES_MAP.containsKey(p); return SWPlayer.of(p).hasComponent(DetonatorComponent.class);
} }
public static void activateDetonator(DetonatorStorage detonator) { public static void activateDetonator(DetonatorStorage detonator) {

View File

@@ -24,6 +24,7 @@ import de.steamwar.bausystem.Permission;
import de.steamwar.bausystem.SWUtils; import de.steamwar.bausystem.SWUtils;
import de.steamwar.bausystem.features.detonator.storage.DetonatorStorage; import de.steamwar.bausystem.features.detonator.storage.DetonatorStorage;
import de.steamwar.bausystem.features.detonator.storage.ItemStorage; import de.steamwar.bausystem.features.detonator.storage.ItemStorage;
import de.steamwar.core.SWPlayer;
import de.steamwar.linkage.Linked; import de.steamwar.linkage.Linked;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@@ -36,15 +37,11 @@ import org.bukkit.event.player.PlayerItemHeldEvent;
import org.bukkit.event.player.PlayerMoveEvent; import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerSwapHandItemsEvent; import org.bukkit.event.player.PlayerSwapHandItemsEvent;
import java.util.HashSet;
import java.util.Set;
@Linked @Linked
public class DetonatorListener implements Listener { public class DetonatorListener implements Listener {
static final Set<Player> HAS_UPDATED = new HashSet<>();
static void addLocationToDetonator(Location location, Player p) { static void addLocationToDetonator(Location location, Player p) {
SWPlayer.of(p).getComponent(Detonator.DetonatorComponent.class).ifPresent(detonatorComponent -> detonatorComponent.setHasUpdated(true));
Detoblock detoblock = Detonator.getBlock(location.getBlock()); Detoblock detoblock = Detonator.getBlock(location.getBlock());
if (detoblock == Detoblock.INVALID) { if (detoblock == Detoblock.INVALID) {
SWUtils.sendToActionbar(p, BauSystem.MESSAGE.parse("DETONATOR_INVALID_BLOCK", p)); SWUtils.sendToActionbar(p, BauSystem.MESSAGE.parse("DETONATOR_INVALID_BLOCK", p));
@@ -66,64 +63,59 @@ public class DetonatorListener implements Listener {
@EventHandler @EventHandler
public void onBlockBreak(BlockBreakEvent event) { public void onBlockBreak(BlockBreakEvent event) {
if(!Permission.BUILD.hasPermission(event.getPlayer())) return; if (!Permission.BUILD.hasPermission(event.getPlayer())) return;
Player p = event.getPlayer(); Player p = event.getPlayer();
if (Detonator.isDetonator(p.getInventory().getItemInMainHand())) { if (Detonator.isDetonator(p.getInventory().getItemInMainHand())) {
event.setCancelled(true); event.setCancelled(true);
addLocationToDetonator(event.getBlock().getLocation(), p); addLocationToDetonator(event.getBlock().getLocation(), p);
HAS_UPDATED.add(event.getPlayer());
} }
} }
@EventHandler @EventHandler
public void onPlayerInteract(PlayerInteractEvent event) { public void onPlayerInteract(PlayerInteractEvent event) {
if(!Permission.BUILD.hasPermission(event.getPlayer())) return; if (!Permission.BUILD.hasPermission(event.getPlayer())) return;
if (!Detonator.isDetonator(event.getItem())) { if (!Detonator.isDetonator(event.getItem())) return;
return;
}
if (event.getAction() == Action.RIGHT_CLICK_AIR || event.getAction() == Action.RIGHT_CLICK_BLOCK) { if (event.getAction() == Action.RIGHT_CLICK_AIR || event.getAction() == Action.RIGHT_CLICK_BLOCK) {
event.setCancelled(true); event.setCancelled(true);
DetonatorStorage detonator = new ItemStorage(event.getPlayer()); DetonatorStorage detonator = new ItemStorage(event.getPlayer());
Detonator.activateDetonator(detonator); Detonator.activateDetonator(detonator);
HAS_UPDATED.add(event.getPlayer()); SWPlayer.of(event.getPlayer()).getComponent(Detonator.DetonatorComponent.class).ifPresent(detonatorComponent -> detonatorComponent.setHasUpdated(true));
} }
} }
@EventHandler(ignoreCancelled = true) @EventHandler(ignoreCancelled = true)
public void onPlayerMove(PlayerMoveEvent event) { public void onPlayerMove(PlayerMoveEvent event) {
if (!Permission.BUILD.hasPermission(event.getPlayer()) ||!Detonator.isDetonator(event.getPlayer().getInventory().getItemInMainHand())) { if (!Permission.BUILD.hasPermission(event.getPlayer()) || !Detonator.isDetonator(event.getPlayer().getInventory().getItemInMainHand())) {
if (Detonator.hasActiveDetonatorShow(event.getPlayer())) { if (Detonator.hasActiveDetonatorShow(event.getPlayer())) {
Detonator.hideDetonator(event.getPlayer()); Detonator.hideDetonator(event.getPlayer());
} }
} else { return;
if (!Detonator.hasActiveDetonatorShow(event.getPlayer())) {
Detonator.showDetonator(event.getPlayer(), new ItemStorage(event.getPlayer()).getLocations());
}
} }
if (!Detonator.hasActiveDetonatorShow(event.getPlayer())) {
if (HAS_UPDATED.contains(event.getPlayer())) { Detonator.showDetonator(event.getPlayer(), new ItemStorage(event.getPlayer()).getLocations());
HAS_UPDATED.remove(event.getPlayer()); return;
if (Detonator.hasActiveDetonatorShow(event.getPlayer())) {
Detonator.hideDetonator(event.getPlayer());
Detonator.showDetonator(event.getPlayer(), new ItemStorage(event.getPlayer()).getLocations());
}
} }
Detonator.DetonatorComponent component = SWPlayer.of(event.getPlayer())
.getComponentAndFilter(Detonator.DetonatorComponent.class, Detonator.DetonatorComponent::isHasUpdated)
.orElse(null);
if (component == null) return;
component.setHasUpdated(false);
Detonator.hideDetonator(event.getPlayer());
Detonator.showDetonator(event.getPlayer(), new ItemStorage(event.getPlayer()).getLocations());
} }
@EventHandler @EventHandler
public void onPlayerItemHeld(PlayerItemHeldEvent event) { public void onPlayerItemHeld(PlayerItemHeldEvent event) {
if(!Permission.BUILD.hasPermission(event.getPlayer())) return; if (!Permission.BUILD.hasPermission(event.getPlayer())) return;
if (Detonator.isDetonator(event.getPlayer().getInventory().getItemInMainHand())) { if (!Detonator.isDetonator(event.getPlayer().getInventory().getItemInMainHand())) return;
HAS_UPDATED.add(event.getPlayer()); SWPlayer.of(event.getPlayer()).getComponent(Detonator.DetonatorComponent.class).ifPresent(detonatorComponent -> detonatorComponent.setHasUpdated(true));
}
} }
@EventHandler @EventHandler
public void onPlayerSwapHandItems(PlayerSwapHandItemsEvent event) { public void onPlayerSwapHandItems(PlayerSwapHandItemsEvent event) {
if(!Permission.BUILD.hasPermission(event.getPlayer())) return; if (!Permission.BUILD.hasPermission(event.getPlayer())) return;
if (Detonator.isDetonator(event.getMainHandItem()) || Detonator.isDetonator(event.getOffHandItem())) { if (!(Detonator.isDetonator(event.getMainHandItem()) || Detonator.isDetonator(event.getOffHandItem()))) return;
HAS_UPDATED.add(event.getPlayer()); SWPlayer.of(event.getPlayer()).getComponent(Detonator.DetonatorComponent.class).ifPresent(detonatorComponent -> detonatorComponent.setHasUpdated(true));
}
} }
} }

View File

@@ -26,6 +26,7 @@ import de.steamwar.bausystem.features.loader.elements.LoaderInteractionElement;
import de.steamwar.bausystem.features.loader.elements.impl.LoaderTNT; import de.steamwar.bausystem.features.loader.elements.impl.LoaderTNT;
import de.steamwar.bausystem.features.loader.elements.impl.LoaderWait; import de.steamwar.bausystem.features.loader.elements.impl.LoaderWait;
import de.steamwar.bausystem.shared.EnumDisplay; import de.steamwar.bausystem.shared.EnumDisplay;
import de.steamwar.core.SWPlayer;
import de.steamwar.inventory.SWAnvilInv; import de.steamwar.inventory.SWAnvilInv;
import de.steamwar.inventory.SWItem; import de.steamwar.inventory.SWItem;
import de.steamwar.inventory.SWListInv; import de.steamwar.inventory.SWListInv;
@@ -40,21 +41,17 @@ import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.player.PlayerQuitEvent;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
public class Loader implements Listener { public class Loader implements Listener, SWPlayer.Component {
private static final Map<Player, Loader> LOADER_MAP = new HashMap<>();
public static Loader getLoader(Player player) { public static Loader getLoader(Player player) {
return LOADER_MAP.get(player); return SWPlayer.of(player).getComponent(Loader.class).orElse(null);
} }
public static void newLoader(Player player) { public static void newLoader(Player player) {
LOADER_MAP.put(player, new Loader(player)); SWPlayer.of(player).setComponent(new Loader(player));
} }
private final Player p; private final Player p;
@@ -145,7 +142,7 @@ public class Loader implements Listener {
recorder = null; recorder = null;
} }
elements.clear(); elements.clear();
LOADER_MAP.remove(p); SWPlayer.of(p).removeComponent(Loader.class);
} }
public boolean setTicksBetweenShots(int delay) { public boolean setTicksBetweenShots(int delay) {

View File

@@ -21,6 +21,7 @@ package de.steamwar.bausystem.features.observer;
import de.steamwar.Reflection; import de.steamwar.Reflection;
import de.steamwar.bausystem.region.Point; import de.steamwar.bausystem.region.Point;
import de.steamwar.core.SWPlayer;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.Particle; import org.bukkit.Particle;
@@ -34,7 +35,7 @@ import org.bukkit.entity.Player;
import java.util.*; import java.util.*;
public class ObserverTracer { public class ObserverTracer implements SWPlayer.Component {
private static final Set<BlockFace> ALLOWED = EnumSet.of(BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST, BlockFace.UP, BlockFace.DOWN); private static final Set<BlockFace> ALLOWED = EnumSet.of(BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST, BlockFace.UP, BlockFace.DOWN);

View File

@@ -21,6 +21,7 @@ package de.steamwar.bausystem.features.observer;
import de.steamwar.bausystem.BauSystem; import de.steamwar.bausystem.BauSystem;
import de.steamwar.command.SWCommand; import de.steamwar.command.SWCommand;
import de.steamwar.core.SWPlayer;
import de.steamwar.linkage.Linked; import de.steamwar.linkage.Linked;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@@ -41,23 +42,23 @@ public class ObserverTracerCommand extends SWCommand {
@Register(value = "disable", description = "OBSERVER_HELP_DISABLE") @Register(value = "disable", description = "OBSERVER_HELP_DISABLE")
public void disable(Player p) { public void disable(Player p) {
ObserverTracerListener.enabled.remove(p); ObserverTracerListener.enabled.remove(p);
ObserverTracerListener.observerTracerMap.remove(p); SWPlayer.of(p).removeComponent(ObserverTracer.class);
BauSystem.MESSAGE.send("OBSERVER_DISABLE", p); BauSystem.MESSAGE.send("OBSERVER_DISABLE", p);
} }
@Register(value = "delete", description = "OBSERVER_HELP_DELETE") @Register(value = "delete", description = "OBSERVER_HELP_DELETE")
public void delete(@Validator Player p) { public void delete(@Validator Player p) {
ObserverTracerListener.observerTracerMap.remove(p); SWPlayer.of(p).removeComponent(ObserverTracer.class);
BauSystem.MESSAGE.send("OBSERVER_DELETE", p); BauSystem.MESSAGE.send("OBSERVER_DELETE", p);
} }
@Register(value = "retrace", description = "OBSERVER_HELP_RETRACE") @Register(value = "retrace", description = "OBSERVER_HELP_RETRACE")
public void retrace(@Validator Player p) { public void retrace(@Validator Player p) {
if (ObserverTracerListener.observerTracerMap.containsKey(p)) { if (SWPlayer.of(p).hasComponent(ObserverTracer.class)) {
BauSystem.MESSAGE.send("OBSERVER_RETRACE_NO_TRACE", p); BauSystem.MESSAGE.send("OBSERVER_RETRACE_NO_TRACE", p);
return; return;
} }
ObserverTracerListener.observerTracerMap.get(p).trace(); SWPlayer.of(p).getComponent(ObserverTracer.class).ifPresent(ObserverTracer::trace);
BauSystem.MESSAGE.send("OBSERVER_RETRACE_DONE", p); BauSystem.MESSAGE.send("OBSERVER_RETRACE_DONE", p);
} }
} }

View File

@@ -22,6 +22,7 @@ package de.steamwar.bausystem.features.observer;
import de.steamwar.bausystem.BauSystem; import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.Permission; import de.steamwar.bausystem.Permission;
import de.steamwar.bausystem.utils.BauMemberUpdateEvent; import de.steamwar.bausystem.utils.BauMemberUpdateEvent;
import de.steamwar.core.SWPlayer;
import de.steamwar.linkage.Linked; import de.steamwar.linkage.Linked;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.GameMode; import org.bukkit.GameMode;
@@ -34,23 +35,19 @@ import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.player.PlayerQuitEvent;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map;
import java.util.Set; import java.util.Set;
@Linked @Linked
public class ObserverTracerListener implements Listener { public class ObserverTracerListener implements Listener {
static Set<Player> enabled = new HashSet<>(); static Set<Player> enabled = new HashSet<>();
static Map<Player, ObserverTracer> observerTracerMap = new HashMap<>();
public ObserverTracerListener() { public ObserverTracerListener() {
Bukkit.getScheduler().runTaskTimer(BauSystem.getInstance(), () -> { Bukkit.getScheduler().runTaskTimer(BauSystem.getInstance(), () -> {
observerTracerMap.forEach((player, observerTracer) -> { SWPlayer.allWithSingleComponent(ObserverTracer.class).forEach(pair -> {
if (player.getGameMode() == GameMode.SPECTATOR) { if (pair.getKey().getGameMode() != GameMode.SPECTATOR) return;
observerTracer.show(); pair.getValue().show();
}
}); });
}, 15L, 15L); }, 15L, 15L);
} }
@@ -58,20 +55,16 @@ public class ObserverTracerListener implements Listener {
@EventHandler @EventHandler
public void onPlayerInteract(PlayerInteractEvent event) { public void onPlayerInteract(PlayerInteractEvent event) {
if(!Permission.BUILD.hasPermission(event.getPlayer())) return; if(!Permission.BUILD.hasPermission(event.getPlayer())) return;
if (!enabled.contains(event.getPlayer())) { if (!enabled.contains(event.getPlayer())) return;
return; if (event.getClickedBlock() == null) return;
} ObserverTracer observerTracer = SWPlayer.of(event.getPlayer()).getComponent(ObserverTracer.class).orElse(null);
if (event.getClickedBlock() == null) { if (observerTracer != null) {
return;
}
if (observerTracerMap.containsKey(event.getPlayer())) {
ObserverTracer observerTracer = observerTracerMap.get(event.getPlayer());
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> { Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> {
if (!observerTracer.trace()) { if (!observerTracer.trace()) {
createNew(event); createNew(event);
} }
observerTracerMap.forEach((player, o) -> { SWPlayer.allWithSingleComponent(ObserverTracer.class).forEach(pair -> {
o.trace(); pair.getValue().trace();
}); });
}, 1L); }, 1L);
} else { } else {
@@ -86,13 +79,13 @@ public class ObserverTracerListener implements Listener {
if (event.getClickedBlock().getType() == Material.OBSERVER) { if (event.getClickedBlock().getType() == Material.OBSERVER) {
ObserverTracer observerTracer = new ObserverTracer(event.getPlayer(), event.getClickedBlock()); ObserverTracer observerTracer = new ObserverTracer(event.getPlayer(), event.getClickedBlock());
observerTracer.trace(); observerTracer.trace();
observerTracerMap.put(event.getPlayer(), observerTracer); SWPlayer.of(event.getPlayer()).setComponent(observerTracer);
} }
} }
@EventHandler @EventHandler
public void onBauMemberUpdate(BauMemberUpdateEvent event) { public void onBauMemberUpdate(BauMemberUpdateEvent event) {
event.getNewSpectator().forEach(observerTracerMap::remove); event.getNewBuilder().forEach(player -> SWPlayer.of(player).removeComponent(ObserverTracer.class));
} }
@EventHandler @EventHandler
@@ -103,6 +96,5 @@ public class ObserverTracerListener implements Listener {
@EventHandler @EventHandler
public void onPlayerQuit(PlayerQuitEvent event) { public void onPlayerQuit(PlayerQuitEvent event) {
enabled.remove(event.getPlayer()); enabled.remove(event.getPlayer());
observerTracerMap.remove(event.getPlayer());
} }
} }

View File

@@ -31,7 +31,6 @@ import de.steamwar.command.SWCommand;
import de.steamwar.command.TypeMapper; import de.steamwar.command.TypeMapper;
import de.steamwar.linkage.Linked; import de.steamwar.linkage.Linked;
import de.steamwar.linkage.LinkedInstance; import de.steamwar.linkage.LinkedInstance;
import de.steamwar.sql.BauweltMember;
import de.steamwar.sql.Punishment; import de.steamwar.sql.Punishment;
import de.steamwar.sql.SchematicNode; import de.steamwar.sql.SchematicNode;
import de.steamwar.sql.SteamwarUser; import de.steamwar.sql.SteamwarUser;
@@ -73,6 +72,14 @@ public class TestblockCommand extends SWCommand {
resetRegion(p, node, isExtension ? RegionExtensionType.EXTENSION : RegionExtensionType.NORMAL, isIgnoreAir, isOnlyColor, replaceTNT, replaceWater); resetRegion(p, node, isExtension ? RegionExtensionType.EXTENSION : RegionExtensionType.NORMAL, isIgnoreAir, isOnlyColor, replaceTNT, replaceWater);
} }
@Register(value="default")
public void setTestblockDefault(Player p) {
Region region = regionCheck(p);
if (region == null) return;
region.getRegionData().setTestblockSchematic(null);
resetRegion(p, null, RegionExtensionType.EXTENSION, false, false, false, false);
}
private void resetRegion(Player p, SchematicNode node, RegionExtensionType regionExtensionType, boolean ignoreAir, boolean onlyColors, boolean removeTNT, boolean removeWater) { private void resetRegion(Player p, SchematicNode node, RegionExtensionType regionExtensionType, boolean ignoreAir, boolean onlyColors, boolean removeTNT, boolean removeWater) {
Region region = regionCheck(p); Region region = regionCheck(p);
if (region == null) return; if (region == null) return;
@@ -93,29 +100,10 @@ public class TestblockCommand extends SWCommand {
} }
} }
// Beta Tester enabled if (node == null) {
switch (BauServer.getInstance().getOwnerID()) { node = region.getRegionData().getTestblockSchematic();
case 245: } else {
case 403: region.getRegionData().setTestblockSchematic(node);
case 1898:
case 3320:
case 4603:
case 5262:
case 5399:
case 6032:
case 7862:
case 11077:
case 11888:
case 12258:
case 16009:
if (node == null) {
node = region.getRegionData().getTestblockSchematic();
} else {
region.getRegionData().setTestblockSchematic(node);
}
break;
default:
break;
} }
PasteBuilder.ClipboardProvider clipboardProvider; PasteBuilder.ClipboardProvider clipboardProvider;
@@ -198,7 +186,7 @@ public class TestblockCommand extends SWCommand {
@Override @Override
public List<String> tabCompletes(CommandSender commandSender, PreviousArguments previousArguments, String s) { public List<String> tabCompletes(CommandSender commandSender, PreviousArguments previousArguments, String s) {
List<String> stringList = new ArrayList<>(SchematicNode.getNodeTabcomplete(SteamwarUser.get(((Player) commandSender).getUniqueId()), 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; return stringList;
} }
@@ -206,7 +194,7 @@ public class TestblockCommand extends SWCommand {
public SchematicNode map(CommandSender commandSender, PreviousArguments previousArguments, String s) { public SchematicNode map(CommandSender commandSender, PreviousArguments previousArguments, String s) {
SchematicNode node = SchematicNode.getNodeFromPath(SteamwarUser.get(((Player) commandSender).getUniqueId()), s); SchematicNode node = SchematicNode.getNodeFromPath(SteamwarUser.get(((Player) commandSender).getUniqueId()), s);
if (node == null) { if (node == null) {
node = SchematicNode.getNodeFromPath(SteamwarUser.get(0), s); node = SchematicNode.getNodeFromPath(SteamwarUser.byId(0), s);
} }
return node; return node;
} }

View File

@@ -38,7 +38,7 @@ public class ScriptHelper {
BookMeta meta = (BookMeta) itemStack.getItemMeta(); BookMeta meta = (BookMeta) itemStack.getItemMeta();
if(!writeable) { if(!writeable) {
meta.setTitle(script.getName()); meta.setTitle(script.getName());
meta.setAuthor(SteamwarUser.get(script.getUserId()).getUserName()); meta.setAuthor(SteamwarUser.byId(script.getUserId()).getUserName());
} }
meta.setPages(getScriptPages(script)); meta.setPages(getScriptPages(script));
itemStack.setItemMeta(meta); itemStack.setItemMeta(meta);

View File

@@ -67,7 +67,7 @@ public class ScriptListener implements Listener {
@EventHandler @EventHandler
public void onPlayerQuit(PlayerQuitEvent event) { public void onPlayerQuit(PlayerQuitEvent event) {
ScriptRunner.remove(event.getPlayer()); playerSet.remove(event.getPlayer());
} }
@EventHandler @EventHandler

View File

@@ -23,8 +23,11 @@ import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.features.script.lua.CommandRegister; import de.steamwar.bausystem.features.script.lua.CommandRegister;
import de.steamwar.bausystem.features.script.lua.SteamWarGlobalLuaPlugin; import de.steamwar.bausystem.features.script.lua.SteamWarGlobalLuaPlugin;
import de.steamwar.bausystem.features.script.lua.SteamWarPlatform; import de.steamwar.bausystem.features.script.lua.SteamWarPlatform;
import de.steamwar.core.SWPlayer;
import de.steamwar.sql.Script; import de.steamwar.sql.Script;
import de.steamwar.sql.SteamwarUser; import de.steamwar.sql.SteamwarUser;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.UtilityClass; import lombok.experimental.UtilityClass;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable; import org.bukkit.event.Cancellable;
@@ -44,12 +47,25 @@ public class ScriptRunner {
// Key -> bau-script-<BUCH NAME> // Key -> bau-script-<BUCH NAME>
// Value -> <LUA Script> // Value -> <LUA Script>
private static final Map<Player, Map<SteamWarGlobalLuaPlugin.EventType, List<LuaFunction>>> EVENT_MAP = new HashMap<>(); public class ScriptData implements SWPlayer.Component {
private static final Map<Player, Map<Hotkey, List<LuaFunction>>> HOTKEY_MAP = new HashMap<>(); private Map<SteamWarGlobalLuaPlugin.EventType, List<LuaFunction>> events = new EnumMap<>(SteamWarGlobalLuaPlugin.EventType.class);
private static final Map<Player, Map<String, CommandRegister>> COMMAND_MAP = new HashMap<>(); private Map<Hotkey, List<LuaFunction>> hotkeys = new HashMap<>();
private Map<String, CommandRegister> commands = new HashMap<>();
@Getter
private Set<String> calledCommands = new HashSet<>();
@Getter
@Setter
private Long lastF = Long.MAX_VALUE;
@Getter
@Setter
private boolean ignore;
}
public Set<String> getCommandsOfPlayer(Player player) { public Set<String> getCommandsOfPlayer(Player player) {
return COMMAND_MAP.getOrDefault(player, new HashMap<>()).keySet(); return SWPlayer.of(player).getComponentOrDefault(ScriptData.class, ScriptData::new).commands.keySet();
} }
public static void runScript(String script, Player player) { public static void runScript(String script, Player player) {
@@ -64,10 +80,12 @@ public class ScriptRunner {
public static void createGlobalScript(List<String> scripts, Player player) { public static void createGlobalScript(List<String> scripts, Player player) {
remove(player); remove(player);
SWPlayer swPlayer = SWPlayer.of(player);
ScriptData scriptData = swPlayer.getComponentOrDefault(ScriptData.class, ScriptData::new);
Globals globals = SteamWarPlatform.createGlobalGlobals(player, Globals globals = SteamWarPlatform.createGlobalGlobals(player,
(s, luaFunction) -> EVENT_MAP.computeIfAbsent(player, player1 -> new EnumMap<>(SteamWarGlobalLuaPlugin.EventType.class)).computeIfAbsent(s, s1 -> new ArrayList<>()).add(luaFunction), (s, luaFunction) -> scriptData.events.computeIfAbsent(s, s1 -> new ArrayList<>()).add(luaFunction),
(s, luaFunction) -> HOTKEY_MAP.computeIfAbsent(player, player1 -> new HashMap<>()).computeIfAbsent(Hotkey.fromString(s), s1 -> new ArrayList<>()).add(luaFunction), (s, luaFunction) -> scriptData.hotkeys.computeIfAbsent(Hotkey.fromString(s), s1 -> new ArrayList<>()).add(luaFunction),
commandRegister -> COMMAND_MAP.computeIfAbsent(player, player1 -> new HashMap<>()).put(commandRegister.getName(), commandRegister)); commandRegister -> scriptData.commands.put(commandRegister.getName(), commandRegister));
for (String script : scripts) { for (String script : scripts) {
catchScript("SCRIPT_ERROR_GLOBAL", player, () -> globals.load(script).call()); catchScript("SCRIPT_ERROR_GLOBAL", player, () -> globals.load(script).call());
@@ -75,13 +93,14 @@ public class ScriptRunner {
} }
public static void remove(Player player) { public static void remove(Player player) {
EVENT_MAP.remove(player); SWPlayer.of(player).removeComponent(ScriptData.class);
COMMAND_MAP.remove(player);
HOTKEY_MAP.remove(player);
} }
public static void callEvent(Player player, SteamWarGlobalLuaPlugin.EventType event, LuaValue eventValue, Event wrappedEvent) { public static void callEvent(Player player, SteamWarGlobalLuaPlugin.EventType event, LuaValue eventValue, Event wrappedEvent) {
List<LuaFunction> luaFunctions = EVENT_MAP.getOrDefault(player, Collections.emptyMap()).getOrDefault(event, Collections.emptyList()); List<LuaFunction> luaFunctions = SWPlayer.of(player).getComponent(ScriptData.class)
.map(scriptData -> scriptData.events)
.orElse(Collections.emptyMap())
.getOrDefault(event, Collections.emptyList());
if (luaFunctions.isEmpty()) { if (luaFunctions.isEmpty()) {
if(event == SteamWarGlobalLuaPlugin.EventType.DoubleSwap) { if(event == SteamWarGlobalLuaPlugin.EventType.DoubleSwap) {
player.performCommand("gui"); player.performCommand("gui");
@@ -124,7 +143,10 @@ public class ScriptRunner {
} }
public static boolean callCommand(Player player, String command, String[] argsArray) { public static boolean callCommand(Player player, String command, String[] argsArray) {
CommandRegister commandRegister = COMMAND_MAP.getOrDefault(player, Collections.emptyMap()).get(command); CommandRegister commandRegister = SWPlayer.of(player).getComponent(ScriptData.class)
.map(scriptData -> scriptData.commands)
.orElse(Collections.emptyMap())
.get(command);
if (commandRegister == null) { if (commandRegister == null) {
return false; return false;
} }
@@ -188,7 +210,11 @@ public class ScriptRunner {
public static void callHotkey(int mods, int key, Player player, boolean pressed) { public static void callHotkey(int mods, int key, Player player, boolean pressed) {
Hotkey hotkey = Hotkey.fromChar(key, mods); Hotkey hotkey = Hotkey.fromChar(key, mods);
catchScript("SCRIPT_ERROR_GLOBAL", player, () -> HOTKEY_MAP.getOrDefault(player, Collections.emptyMap()).getOrDefault(hotkey, Collections.emptyList()).forEach(luaFunction -> luaFunction.call(LuaValue.valueOf(pressed)))); List<LuaFunction> hotkeys = SWPlayer.of(player).getComponent(ScriptData.class)
.map(scriptData -> scriptData.hotkeys)
.orElse(Collections.emptyMap())
.getOrDefault(hotkey, Collections.emptyList());
catchScript("SCRIPT_ERROR_GLOBAL", player, () -> hotkeys.forEach(luaFunction -> luaFunction.call(LuaValue.valueOf(pressed))));
} }
public static void catchScript(String errorMsg, Player player, Runnable run) { public static void catchScript(String errorMsg, Player player, Runnable run) {

View File

@@ -21,44 +21,24 @@ package de.steamwar.bausystem.features.script.event;
import de.steamwar.bausystem.Permission; import de.steamwar.bausystem.Permission;
import de.steamwar.bausystem.features.script.ScriptRunner; import de.steamwar.bausystem.features.script.ScriptRunner;
import de.steamwar.core.SWPlayer;
import de.steamwar.linkage.Linked; import de.steamwar.linkage.Linked;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerCommandPreprocessEvent; import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
@Linked @Linked
public class CommandListener implements Listener { public class CommandListener implements Listener {
private Map<Player, Set<String>> calledCommands = new HashMap<>();
@EventHandler @EventHandler
public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) { public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) {
if(!Permission.BUILD.hasPermission(event.getPlayer())) return; if(!Permission.BUILD.hasPermission(event.getPlayer())) return;
String[] split = event.getMessage().split(" "); String[] split = event.getMessage().split(" ");
if (calledCommands.getOrDefault(event.getPlayer(), new HashSet<>()).contains(split[0])) { ScriptRunner.ScriptData scriptData = SWPlayer.of(event.getPlayer()).getComponentOrDefault(ScriptRunner.ScriptData.class, ScriptRunner.ScriptData::new);
return; if (scriptData.getCalledCommands().contains(split[0])) return;
}
calledCommands.getOrDefault(event.getPlayer(), new HashSet<>()).add(split[0]); scriptData.getCalledCommands().add(split[0]);
event.setCancelled(ScriptRunner.callCommand(event.getPlayer(), split[0].substring(1), split)); event.setCancelled(ScriptRunner.callCommand(event.getPlayer(), split[0].substring(1), split));
calledCommands.getOrDefault(event.getPlayer(), new HashSet<>()).remove(split[0]); scriptData.getCalledCommands().remove(split[0]);
}
@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
calledCommands.put(event.getPlayer(), new HashSet<>());
}
@EventHandler
public void onPlayerQuit(PlayerQuitEvent event) {
calledCommands.remove(event.getPlayer());
} }
} }

View File

@@ -25,6 +25,7 @@ import de.steamwar.bausystem.features.script.ScriptRunner;
import de.steamwar.bausystem.features.script.lua.SteamWarGlobalLuaPlugin; import de.steamwar.bausystem.features.script.lua.SteamWarGlobalLuaPlugin;
import de.steamwar.bausystem.features.script.lua.libs.StorageLib; import de.steamwar.bausystem.features.script.lua.libs.StorageLib;
import de.steamwar.bausystem.region.Region; import de.steamwar.bausystem.region.Region;
import de.steamwar.core.SWPlayer;
import de.steamwar.core.TrickyTrialsWrapper; import de.steamwar.core.TrickyTrialsWrapper;
import de.steamwar.linkage.Linked; import de.steamwar.linkage.Linked;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@@ -43,32 +44,27 @@ import org.bukkit.event.player.*;
import org.luaj.vm2.LuaTable; import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue; import org.luaj.vm2.LuaValue;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
@Linked @Linked
public class EventListener implements Listener { public class EventListener implements Listener {
private static final Map<Player, Long> LAST_FS = new HashMap<>();
static { static {
Bukkit.getScheduler().runTaskTimer(BauSystem.getInstance(), () -> { Bukkit.getScheduler().runTaskTimer(BauSystem.getInstance(), () -> {
long millis = System.currentTimeMillis(); long millis = System.currentTimeMillis();
LAST_FS.entrySet().removeIf(entry -> millis - entry.getValue() > 200); SWPlayer.allWithSingleComponent(ScriptRunner.ScriptData.class)
.filter(pair -> millis - pair.getValue().getLastF() > 200)
.forEach(pair -> pair.getValue().setLastF(Long.MAX_VALUE));
}, 1, 1); }, 1, 1);
} }
@EventHandler(priority = EventPriority.MONITOR) @EventHandler(priority = EventPriority.MONITOR)
public void onPlayerJoin(PlayerJoinEvent event) { public void onPlayerJoin(PlayerJoinEvent event) {
if(!Permission.BUILD.hasPermission(event.getPlayer())) return; if (!Permission.BUILD.hasPermission(event.getPlayer())) return;
ScriptRunner.callEvent(event.getPlayer(), SteamWarGlobalLuaPlugin.EventType.SelfJoin, LuaValue.NIL, event); ScriptRunner.callEvent(event.getPlayer(), SteamWarGlobalLuaPlugin.EventType.SelfJoin, LuaValue.NIL, event);
} }
@EventHandler(priority = EventPriority.HIGH) @EventHandler(priority = EventPriority.HIGH)
public void onPlayerQuit(PlayerQuitEvent event) { public void onPlayerQuit(PlayerQuitEvent event) {
if(Permission.BUILD.hasPermission(event.getPlayer())) { if (Permission.BUILD.hasPermission(event.getPlayer())) {
ScriptRunner.callEvent(event.getPlayer(), SteamWarGlobalLuaPlugin.EventType.SelfLeave, LuaValue.NIL, event); ScriptRunner.callEvent(event.getPlayer(), SteamWarGlobalLuaPlugin.EventType.SelfLeave, LuaValue.NIL, event);
} }
StorageLib.removePlayer(event.getPlayer()); StorageLib.removePlayer(event.getPlayer());
@@ -76,19 +72,20 @@ public class EventListener implements Listener {
@EventHandler(priority = EventPriority.HIGH) @EventHandler(priority = EventPriority.HIGH)
public void onPlayerSwapHandItems(PlayerSwapHandItemsEvent event) { public void onPlayerSwapHandItems(PlayerSwapHandItemsEvent event) {
if(!Permission.BUILD.hasPermission(event.getPlayer())) return; if (!Permission.BUILD.hasPermission(event.getPlayer())) return;
if (LAST_FS.containsKey(event.getPlayer())) { ScriptRunner.ScriptData scriptData = SWPlayer.of(event.getPlayer()).getComponentOrDefault(ScriptRunner.ScriptData.class, ScriptRunner.ScriptData::new);
if (scriptData.getLastF() != Long.MAX_VALUE) {
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> { Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> {
ScriptRunner.callEvent(event.getPlayer(), SteamWarGlobalLuaPlugin.EventType.DoubleSwap, LuaValue.NIL, event); ScriptRunner.callEvent(event.getPlayer(), SteamWarGlobalLuaPlugin.EventType.DoubleSwap, LuaValue.NIL, event);
}, 1); }, 1);
} else { } else {
LAST_FS.put(event.getPlayer(), System.currentTimeMillis()); scriptData.setLastF(System.currentTimeMillis());
} }
} }
@EventHandler(priority = EventPriority.HIGH) @EventHandler(priority = EventPriority.HIGH)
public void onBlockPlace(BlockPlaceEvent event) { public void onBlockPlace(BlockPlaceEvent event) {
if(!Permission.BUILD.hasPermission(event.getPlayer())) return; if (!Permission.BUILD.hasPermission(event.getPlayer())) return;
LuaTable table = new LuaTable(); LuaTable table = new LuaTable();
table.set("x", event.getBlock().getX()); table.set("x", event.getBlock().getX());
table.set("y", event.getBlock().getY()); table.set("y", event.getBlock().getY());
@@ -99,7 +96,7 @@ public class EventListener implements Listener {
@EventHandler(priority = EventPriority.HIGH) @EventHandler(priority = EventPriority.HIGH)
public void onBlockBreak(BlockBreakEvent event) { public void onBlockBreak(BlockBreakEvent event) {
if(!Permission.BUILD.hasPermission(event.getPlayer())) return; if (!Permission.BUILD.hasPermission(event.getPlayer())) return;
LuaTable table = new LuaTable(); LuaTable table = new LuaTable();
table.set("x", event.getBlock().getX()); table.set("x", event.getBlock().getX());
table.set("y", event.getBlock().getY()); table.set("y", event.getBlock().getY());
@@ -108,12 +105,12 @@ public class EventListener implements Listener {
ScriptRunner.callEvent(event.getPlayer(), SteamWarGlobalLuaPlugin.EventType.BreakBlock, table, event); ScriptRunner.callEvent(event.getPlayer(), SteamWarGlobalLuaPlugin.EventType.BreakBlock, table, event);
} }
private final Set<Player> ignore = new HashSet<>();
@EventHandler(priority = EventPriority.LOW) @EventHandler(priority = EventPriority.LOW)
public void onPlayerInteract(PlayerInteractEvent event) { public void onPlayerInteract(PlayerInteractEvent event) {
if(!Permission.BUILD.hasPermission(event.getPlayer())) return; if (!Permission.BUILD.hasPermission(event.getPlayer())) return;
if (ignore.remove(event.getPlayer())) { ScriptRunner.ScriptData scriptData = SWPlayer.of(event.getPlayer()).getComponentOrDefault(ScriptRunner.ScriptData.class, ScriptRunner.ScriptData::new);
if (scriptData.isIgnore()) {
scriptData.setIgnore(false);
return; return;
} }
LuaTable table = new LuaTable(); LuaTable table = new LuaTable();
@@ -124,7 +121,7 @@ public class EventListener implements Listener {
table.set("hand", event.getHand().name()); table.set("hand", event.getHand().name());
} }
table.set("block", event.getItem() == null ? Material.AIR.name() : event.getItem().getType().name()); table.set("block", event.getItem() == null ? Material.AIR.name() : event.getItem().getType().name());
if(event.getAction() == Action.RIGHT_CLICK_BLOCK || event.getAction() == Action.LEFT_CLICK_BLOCK) { if (event.getAction() == Action.RIGHT_CLICK_BLOCK || event.getAction() == Action.LEFT_CLICK_BLOCK) {
table.set("hasBlock", LuaValue.valueOf(true)); table.set("hasBlock", LuaValue.valueOf(true));
table.set("blockX", event.getClickedBlock().getX()); table.set("blockX", event.getClickedBlock().getX());
table.set("blockY", event.getClickedBlock().getY()); table.set("blockY", event.getClickedBlock().getY());
@@ -150,7 +147,7 @@ public class EventListener implements Listener {
Region tntRegion = Region.getRegion(event.getLocation()); Region tntRegion = Region.getRegion(event.getLocation());
for (Player player : Bukkit.getOnlinePlayers()) { for (Player player : Bukkit.getOnlinePlayers()) {
if(!Permission.BUILD.hasPermission(player)) continue; if (!Permission.BUILD.hasPermission(player)) continue;
if (tntRegion.getArea().inRegion(player.getLocation(), false)) { if (tntRegion.getArea().inRegion(player.getLocation(), false)) {
ScriptRunner.callEvent(player, SteamWarGlobalLuaPlugin.EventType.TNTSpawn, LuaValue.NIL, event); ScriptRunner.callEvent(player, SteamWarGlobalLuaPlugin.EventType.TNTSpawn, LuaValue.NIL, event);
} }
@@ -172,7 +169,7 @@ public class EventListener implements Listener {
boolean inBuild = event.blockList().stream().anyMatch(block -> tntRegion.getBuildArea().inRegion(block.getLocation(), true)); boolean inBuild = event.blockList().stream().anyMatch(block -> tntRegion.getBuildArea().inRegion(block.getLocation(), true));
for (Player player : Bukkit.getOnlinePlayers()) { for (Player player : Bukkit.getOnlinePlayers()) {
if(!Permission.BUILD.hasPermission(player)) continue; if (!Permission.BUILD.hasPermission(player)) continue;
if (tntRegion.getArea().inRegion(player.getLocation(), false)) { if (tntRegion.getArea().inRegion(player.getLocation(), false)) {
ScriptRunner.callEvent(player, SteamWarGlobalLuaPlugin.EventType.TNTExplode, table, event); ScriptRunner.callEvent(player, SteamWarGlobalLuaPlugin.EventType.TNTExplode, table, event);
if (inBuild) { if (inBuild) {
@@ -184,8 +181,9 @@ public class EventListener implements Listener {
@EventHandler(priority = EventPriority.HIGH) @EventHandler(priority = EventPriority.HIGH)
public void onPlayerDropItem(PlayerDropItemEvent event) { public void onPlayerDropItem(PlayerDropItemEvent event) {
if(!Permission.BUILD.hasPermission(event.getPlayer())) return; if (!Permission.BUILD.hasPermission(event.getPlayer())) return;
ignore.add(event.getPlayer()); ScriptRunner.ScriptData scriptData = SWPlayer.of(event.getPlayer()).getComponentOrDefault(ScriptRunner.ScriptData.class, ScriptRunner.ScriptData::new);
scriptData.setIgnore(true);
LuaTable table = new LuaTable(); LuaTable table = new LuaTable();
table.set("type", event.getItemDrop().getItemStack().getType().name()); table.set("type", event.getItemDrop().getItemStack().getType().name());
ScriptRunner.callEvent(event.getPlayer(), SteamWarGlobalLuaPlugin.EventType.DropItem, table, event); ScriptRunner.callEvent(event.getPlayer(), SteamWarGlobalLuaPlugin.EventType.DropItem, table, event);
@@ -194,7 +192,7 @@ public class EventListener implements Listener {
@EventHandler(priority = EventPriority.HIGH) @EventHandler(priority = EventPriority.HIGH)
public void onEntityDeath(EntityDeathEvent event) { public void onEntityDeath(EntityDeathEvent event) {
for (Player player : Bukkit.getOnlinePlayers()) { for (Player player : Bukkit.getOnlinePlayers()) {
if(!Permission.BUILD.hasPermission(player)) continue; if (!Permission.BUILD.hasPermission(player)) continue;
LuaTable table = new LuaTable(); LuaTable table = new LuaTable();
table.set("type", event.getEntityType().name()); table.set("type", event.getEntityType().name());
ScriptRunner.callEvent(player, SteamWarGlobalLuaPlugin.EventType.EntityDeath, table, event); ScriptRunner.callEvent(player, SteamWarGlobalLuaPlugin.EventType.EntityDeath, table, event);

View File

@@ -48,6 +48,7 @@ import java.util.logging.Level;
public class SteamWarLuaPlugin extends TwoArgFunction { public class SteamWarLuaPlugin extends TwoArgFunction {
private static final boolean hasFAWE = Bukkit.getPluginManager().getPlugin("FastAsyncWorldEdit") != null; private static final boolean hasFAWE = Bukkit.getPluginManager().getPlugin("FastAsyncWorldEdit") != null;
private static final Set<String> ignoreCommandFromWorldEdit = Set.of("select", "schem", "/schem", "schematic", "/schematic");
protected static final Map<Class<?>, List<LuaLib>> LUA_LIBS = new HashMap<>(); protected static final Map<Class<?>, List<LuaLib>> LUA_LIBS = new HashMap<>();
@@ -116,7 +117,7 @@ public class SteamWarLuaPlugin extends TwoArgFunction {
command = preprocessEvent.getMessage().substring(1); command = preprocessEvent.getMessage().substring(1);
Bukkit.getLogger().log(Level.INFO, player.getName() + " dispatched command: " + command); Bukkit.getLogger().log(Level.INFO, player.getName() + " dispatched command: " + command);
String[] commandSplit = command.split(" "); String[] commandSplit = command.split(" ");
if (!commandSplit[0].equals("select") && hasFAWE && WorldEditListener.isWorldEditCommand("/" + commandSplit[0])) { if (!ignoreCommandFromWorldEdit.contains(commandSplit[0]) && hasFAWE && WorldEditListener.isWorldEditCommand("/" + commandSplit[0])) {
EditSession editSession = WorldEditUtils.getEditSession(player); EditSession editSession = WorldEditUtils.getEditSession(player);
Actor actor = BukkitAdapter.adapt(player); Actor actor = BukkitAdapter.adapt(player);
WorldEdit.getInstance().getPlatformManager().getPlatformCommandManager().handleCommandOnCurrentThread(new CommandEvent(actor, command, editSession)); WorldEdit.getInstance().getPlatformManager().getPlatformCommandManager().handleCommandOnCurrentThread(new CommandEvent(actor, command, editSession));

View File

@@ -89,7 +89,7 @@ public class StorageLib implements LuaLib, Enable, Disable {
jsonObject.keySet().forEach(key -> { jsonObject.keySet().forEach(key -> {
map.put(key, fromJson(jsonObject.get(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); PLAYER_STORAGE.put(steamwarUser.getUUID(), map);
} catch (Exception e) {} } catch (Exception e) {}
} }

View File

@@ -54,7 +54,7 @@ public class YAPIONFormatSimulatorLoader implements SimulatorLoader {
} }
String name = file.getName().substring(0, file.getName().length() - 7); 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<>(); List<Simulator> simulators = new ArrayList<>();
for (String s : yapionObject.getKeys()) { for (String s : yapionObject.getKeys()) {

View File

@@ -21,28 +21,16 @@ package de.steamwar.bausystem.features.slaves.laufbau;
import com.sk89q.worldedit.blocks.SkullBlock; import com.sk89q.worldedit.blocks.SkullBlock;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
import de.steamwar.bausystem.utils.NMSWrapper;
import de.steamwar.core.Core;
import de.steamwar.inventory.SWItem; import de.steamwar.inventory.SWItem;
import lombok.Getter; import lombok.Getter;
import lombok.ToString; import lombok.ToString;
import org.bukkit.Material;
import org.bukkit.block.BlockFace;
import org.bukkit.block.data.Bisected;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.Directional;
import org.bukkit.block.data.Waterlogged;
import org.bukkit.block.data.type.*;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
import java.util.function.Consumer; import java.util.function.Consumer;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.createItem;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.pixelCuboid;
@ToString @ToString
@Getter @Getter
public class BlockBoundingBox { public class BlockBoundingBox {
@@ -95,193 +83,6 @@ public class BlockBoundingBox {
return volume; return volume;
} }
static {
addPixel(Material.AIR.createBlockData(), 0, 0, 0, 0, 0, 0, null);
// addPixel(Material.COBWEB.createBlockData(), 0, 0, 0, 0, 0, 0, createItem("LAUFBAU_BLOCK_COBWEB", Material.COBWEB));
addPixel(Material.END_STONE.createBlockData(), 0, 0, 0, 16, 16, 16, null);
addPixel(NMSWrapper.impl.pathMaterial().createBlockData(), 0, 0, 0, 16, 15, 16, createItem("LAUFBAU_BLOCK_GRASS_PATH", NMSWrapper.impl.pathMaterial()));
addPixel(Material.SOUL_SAND.createBlockData(), 0, 0, 0, 16, 14, 16, createItem("LAUFBAU_BLOCK_SOUL_SAND", Material.SOUL_SAND));
Cocoa cocoaNorth = (Cocoa) Material.COCOA.createBlockData();
cocoaNorth.setAge(2);
cocoaNorth.setFacing(BlockFace.NORTH);
addPixel(cocoaNorth, 4, 3, 1, 8, 9, 8, createItem("LAUFBAU_BLOCK_COCOA", Material.COCOA_BEANS, "LAUFBAU_FACING_NORTH"));
Cocoa cocoaSouth = (Cocoa) Material.COCOA.createBlockData();
cocoaSouth.setAge(2);
cocoaSouth.setFacing(BlockFace.SOUTH);
addPixel(cocoaSouth, 4, 3, 7, 8, 9, 8, createItem("LAUFBAU_BLOCK_COCOA", Material.COCOA_BEANS, "LAUFBAU_FACING_SOUTH"));
Cocoa cocoaWest = (Cocoa) Material.COCOA.createBlockData();
cocoaWest.setAge(2);
cocoaWest.setFacing(BlockFace.WEST);
addPixel(cocoaWest, 1, 3, 4, 8, 9, 8, createItem("LAUFBAU_BLOCK_COCOA", Material.COCOA_BEANS, "LAUFBAU_FACING_WEST"));
Cocoa cocoaEast = (Cocoa) Material.COCOA.createBlockData();
cocoaEast.setAge(2);
cocoaEast.setFacing(BlockFace.EAST);
addPixel(cocoaEast, 7, 3, 4, 8, 9, 8, createItem("LAUFBAU_BLOCK_COCOA", Material.COCOA_BEANS, "LAUFBAU_FACING_EAST"));
TurtleEgg singleTurtleEgg = (TurtleEgg) Material.TURTLE_EGG.createBlockData();
singleTurtleEgg.setEggs(1);
singleTurtleEgg.setHatch(0);
addPixel(singleTurtleEgg, 4, 0, 3, 9, 7, 9, createItem("LAUFBAU_BLOCK_TURTLE_EGG", Material.TURTLE_EGG, "LAUFBAU_COUNT_1"));
TurtleEgg doubleTurtleEgg = (TurtleEgg) Material.TURTLE_EGG.createBlockData();
doubleTurtleEgg.setEggs(2);
doubleTurtleEgg.setHatch(0);
addPixel(doubleTurtleEgg, 1, 0, 1, 14, 7, 14, createItem("LAUFBAU_BLOCK_TURTLE_EGG", Material.TURTLE_EGG, "LAUFBAU_COUNT_2"));
addPixel(Material.CHEST.createBlockData(), 1, 0, 1, 14, 14, 14, createItem("LAUFBAU_BLOCK_CHEST", Material.CHEST));
Snow snowLayers8 = (Snow) Material.SNOW.createBlockData();
snowLayers8.setLayers(8);
addPixel(snowLayers8, 0, 0, 0, 16, 14, 16, createItem("LAUFBAU_BLOCK_SNOW", Material.SNOW, "LAUFBAU_LAYERS_8"));
Directional headNorth = (Directional) Material.PLAYER_WALL_HEAD.createBlockData();
headNorth.setFacing(BlockFace.NORTH);
addPixel(headNorth, 4, 4, 8, 8, 8, 8, createItem("LAUFBAU_BLOCK_PLAYER_WALL_HEAD", Material.PLAYER_HEAD, "LAUFBAU_FACING_NORTH"), BlockBoundingBox::randomPlayerHead);
Directional headSouth = (Directional) Material.PLAYER_WALL_HEAD.createBlockData();
headSouth.setFacing(BlockFace.SOUTH);
addPixel(headSouth, 4, 4, 0, 8, 8, 8, createItem("LAUFBAU_BLOCK_PLAYER_WALL_HEAD", Material.PLAYER_HEAD, "LAUFBAU_FACING_SOUTH"), BlockBoundingBox::randomPlayerHead);
Directional headWest = (Directional) Material.PLAYER_WALL_HEAD.createBlockData();
headWest.setFacing(BlockFace.WEST);
addPixel(headWest, 8, 4, 4, 8, 8, 8, createItem("LAUFBAU_BLOCK_PLAYER_WALL_HEAD", Material.PLAYER_HEAD, "LAUFBAU_FACING_WEST"), BlockBoundingBox::randomPlayerHead);
Directional headEast = (Directional) Material.PLAYER_WALL_HEAD.createBlockData();
headEast.setFacing(BlockFace.EAST);
addPixel(headEast, 0, 4, 4, 8, 8, 8, createItem("LAUFBAU_BLOCK_PLAYER_WALL_HEAD", Material.PLAYER_HEAD, "LAUFBAU_FACING_EAST"), BlockBoundingBox::randomPlayerHead);
Snow snowLayers7 = (Snow) Material.SNOW.createBlockData();
snowLayers7.setLayers(7);
addPixel(snowLayers7, 0, 0, 0, 16, 12, 16, createItem("LAUFBAU_BLOCK_SNOW", Material.SNOW, "LAUFBAU_LAYERS_7"));
Snow snowLayers6 = (Snow) Material.SNOW.createBlockData();
snowLayers6.setLayers(6);
addPixel(snowLayers6, 0, 0, 0, 16, 10, 16, createItem("LAUFBAU_BLOCK_SNOW", Material.SNOW, "LAUFBAU_LAYERS_6"));
addPixel(Material.STONECUTTER.createBlockData(), 0, 0, 0, 16, 9, 16, createItem("LAUFBAU_BLOCK_STONECUTTER", Material.STONECUTTER));
addPixel(Material.PLAYER_HEAD.createBlockData(), 4, 0, 4, 8, 8, 8, createItem("LAUFBAU_BLOCK_PLAYER_HEAD", Material.PLAYER_HEAD), BlockBoundingBox::randomPlayerHead);
addPixel(Material.CAKE.createBlockData(), 1, 0, 1, 14, 8, 14, createItem("LAUFBAU_BLOCK_CAKE", Material.CAKE));
Slab bottomSlab = (Slab) Material.END_STONE_BRICK_SLAB.createBlockData();
bottomSlab.setType(Slab.Type.BOTTOM);
addPixel(bottomSlab, 0, 0, 0, 16, 8, 16, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_SLAB", Material.END_STONE_BRICK_SLAB, "LAUFBAU_TYPE_BOTTOM"));
Slab topSlab = (Slab) Material.END_STONE_BRICK_SLAB.createBlockData();
topSlab.setType(Slab.Type.TOP);
addPixel(topSlab, 0, 8, 0, 16, 8, 16, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_SLAB", Material.END_STONE_BRICK_SLAB, "LAUFBAU_TYPE_TOP"));
SeaPickle quadSeaPickle = (SeaPickle) Material.SEA_PICKLE.createBlockData();
quadSeaPickle.setWaterlogged(false);
quadSeaPickle.setPickles(4);
addPixel(quadSeaPickle, 2, 0, 2, 12, 7, 12, createItem("LAUFBAU_BLOCK_SEA_PICKLE", Material.SEA_PICKLE, "LAUFBAU_COUNT_4"));
Campfire campfire = (Campfire) Material.CAMPFIRE.createBlockData();
campfire.setSignalFire(false);
campfire.setLit(false);
addPixel(campfire, 0, 0, 0, 16, 7, 16, createItem("LAUFBAU_BLOCK_CAMPFIRE", Material.CAMPFIRE));
SeaPickle trippleSeaPickle = (SeaPickle) Material.SEA_PICKLE.createBlockData();
trippleSeaPickle.setWaterlogged(false);
trippleSeaPickle.setPickles(3);
addPixel(trippleSeaPickle, 2, 0, 2, 12, 6, 12, createItem("LAUFBAU_BLOCK_SEA_PICKLE", Material.SEA_PICKLE, "LAUFBAU_COUNT_3"));
SeaPickle doubleSeaPickle = (SeaPickle) Material.SEA_PICKLE.createBlockData();
doubleSeaPickle.setWaterlogged(false);
doubleSeaPickle.setPickles(2);
addPixel(doubleSeaPickle, 3, 0, 3, 10, 6, 10, createItem("LAUFBAU_BLOCK_SEA_PICKLE", Material.SEA_PICKLE, "LAUFBAU_COUNT_2"));
SeaPickle singleSeaPickle = (SeaPickle) Material.SEA_PICKLE.createBlockData();
singleSeaPickle.setWaterlogged(false);
singleSeaPickle.setPickles(1);
addPixel(singleSeaPickle, 6, 0, 6, 4, 6, 4, createItem("LAUFBAU_BLOCK_SEA_PICKLE", Material.SEA_PICKLE, "LAUFBAU_COUNT_1"));
addPixel(Material.FLOWER_POT.createBlockData(), 5, 0, 5, 6, 6, 6, createItem("LAUFBAU_BLOCK_FLOWER_POT", Material.FLOWER_POT));
Snow snowLayers3 = (Snow) Material.SNOW.createBlockData();
snowLayers3.setLayers(3);
addPixel(snowLayers3, 0, 0, 0, 16, 4, 16, createItem("LAUFBAU_BLOCK_SNOW", Material.SNOW, "LAUFBAU_LAYERS_3"));
TrapDoor bottomTrapDoor = (TrapDoor) Material.IRON_TRAPDOOR.createBlockData();
bottomTrapDoor.setHalf(Bisected.Half.BOTTOM);
addPixel(bottomTrapDoor, 0, 0, 0, 16, 3, 16, createItem("LAUFBAU_BLOCK_IRON_TRAPDOOR", Material.IRON_TRAPDOOR, "LAUFBAU_HALF_BOTTOM"));
TrapDoor topTrapDoor = (TrapDoor) Material.IRON_TRAPDOOR.createBlockData();
topTrapDoor.setHalf(Bisected.Half.TOP);
addPixel(topTrapDoor, 0, 13, 0, 16, 3, 16, createItem("LAUFBAU_BLOCK_IRON_TRAPDOOR", Material.IRON_TRAPDOOR, "LAUFBAU_HALF_TOP"));
Snow snowLayers2 = (Snow) Material.SNOW.createBlockData();
snowLayers2.setLayers(2);
addPixel(snowLayers2, 0, 0, 0, 16, 2, 16, createItem("LAUFBAU_BLOCK_SNOW", Material.SNOW, "LAUFBAU_LAYERS_2"));
addPixel(Material.LILY_PAD.createBlockData(), 1, 0, 1, 14, 1.5, 14, createItem("LAUFBAU_BLOCK_LILY_PAD", Material.LILY_PAD));
addPixel(Material.WHITE_CARPET.createBlockData(), 0, 0, 0, 16, 1, 16, createItem("LAUFBAU_BLOCK_WHITE_CARPET", Material.WHITE_CARPET));
Directional endRodBottomTop = (Directional) Material.END_ROD.createBlockData();
endRodBottomTop.setFacing(BlockFace.UP);
addPixel(endRodBottomTop, 6, 0, 6, 4, 16, 4, createItem("LAUFBAU_BLOCK_END_ROD", Material.END_ROD, "LAUFBAU_FACING_UP", "LAUFBAU_FACING_DOWN"));
Directional endRodNorthSouth = (Directional) Material.END_ROD.createBlockData();
endRodNorthSouth.setFacing(BlockFace.NORTH);
addPixel(endRodNorthSouth, 6, 6, 0, 4, 4, 16, createItem("LAUFBAU_BLOCK_END_ROD", Material.END_ROD, "LAUFBAU_FACING_NORTH", "LAUFBAU_FACING_SOUTH"));
Directional endRodEastWest = (Directional) Material.END_ROD.createBlockData();
endRodEastWest.setFacing(BlockFace.EAST);
addPixel(endRodEastWest, 0, 6, 6, 16, 4, 4, createItem("LAUFBAU_BLOCK_END_ROD", Material.END_ROD, "LAUFBAU_FACING_EAST", "LAUFBAU_FACING_WEST"));
if (Core.getVersion() >= 19) {
Directional lightningRodBottomTop = (Directional) Material.LIGHTNING_ROD.createBlockData();
lightningRodBottomTop.setFacing(BlockFace.UP);
addPixel(lightningRodBottomTop, 6, 0, 6, 4, 16, 4, createItem("LAUFBAU_BLOCK_LIGHTNING_ROD", Material.LIGHTNING_ROD, "LAUFBAU_FACING_UP", "LAUFBAU_FACING_DOWN"));
Directional lightningRodNorthSouth = (Directional) Material.LIGHTNING_ROD.createBlockData();
lightningRodNorthSouth.setFacing(BlockFace.NORTH);
addPixel(lightningRodNorthSouth, 6, 6, 0, 4, 4, 16, createItem("LAUFBAU_BLOCK_LIGHTNING_ROD", Material.LIGHTNING_ROD, "LAUFBAU_FACING_NORTH", "LAUFBAU_FACING_SOUTH"));
Directional lightningRodEastWest = (Directional) Material.LIGHTNING_ROD.createBlockData();
lightningRodEastWest.setFacing(BlockFace.EAST);
addPixel(lightningRodEastWest, 0, 6, 6, 16, 4, 4, createItem("LAUFBAU_BLOCK_LIGHTNING_ROD", Material.LIGHTNING_ROD, "LAUFBAU_FACING_EAST", "LAUFBAU_FACING_WEST"));
}
Waterlogged conduit = (Waterlogged) Material.CONDUIT.createBlockData();
conduit.setWaterlogged(false);
addPixel(conduit, 5, 5, 5, 6, 6, 6, createItem("LAUFBAU_BLOCK_CONDUIT", Material.CONDUIT));
TrapDoor northTrapDoor = (TrapDoor) Material.IRON_TRAPDOOR.createBlockData();
northTrapDoor.setFacing(BlockFace.NORTH);
northTrapDoor.setOpen(true);
addPixel(northTrapDoor, 0, 0, 13, 16, 16, 3, createItem("LAUFBAU_BLOCK_IRON_TRAPDOOR", Material.IRON_TRAPDOOR, "LAUFBAU_FACING_NORTH", "LAUFBAU_OPEN"));
TrapDoor southTrapDoor = (TrapDoor) Material.IRON_TRAPDOOR.createBlockData();
southTrapDoor.setFacing(BlockFace.SOUTH);
southTrapDoor.setOpen(true);
addPixel(southTrapDoor, 0, 0, 0, 16, 16, 3, createItem("LAUFBAU_BLOCK_IRON_TRAPDOOR", Material.IRON_TRAPDOOR, "LAUFBAU_FACING_SOUTH", "LAUFBAU_OPEN"));
TrapDoor westTrapDoor = (TrapDoor) Material.IRON_TRAPDOOR.createBlockData();
westTrapDoor.setFacing(BlockFace.WEST);
westTrapDoor.setOpen(true);
addPixel(westTrapDoor, 13, 0, 0, 3, 16, 16, createItem("LAUFBAU_BLOCK_IRON_TRAPDOOR", Material.IRON_TRAPDOOR, "LAUFBAU_FACING_WEST", "LAUFBAU_OPEN"));
TrapDoor eastTrapDoor = (TrapDoor) Material.IRON_TRAPDOOR.createBlockData();
eastTrapDoor.setFacing(BlockFace.EAST);
eastTrapDoor.setOpen(true);
addPixel(eastTrapDoor, 0, 0, 0, 3, 16, 16, createItem("LAUFBAU_BLOCK_IRON_TRAPDOOR", Material.IRON_TRAPDOOR, "LAUFBAU_FACING_EAST", "LAUFBAU_OPEN"));
}
private static void addPixel(BlockData blockData, double xPixel, double yPixel, double zPixel, double dxPixel, double dyPixel, double dzPixel, SWItem swItem) {
new BlockBoundingBox(blockData, Arrays.asList(pixelCuboid(xPixel, yPixel, zPixel, dxPixel, dyPixel, dzPixel)), swItem);
}
private static void addPixel(BlockData blockData, double xPixel, double yPixel, double zPixel, double dxPixel, double dyPixel, double dzPixel, SWItem swItem, Consumer<BaseBlock> blockConsumer) {
new BlockBoundingBox(blockData, Arrays.asList(pixelCuboid(xPixel, yPixel, zPixel, dxPixel, dyPixel, dzPixel)), swItem, blockConsumer);
}
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
private static void randomPlayerHead(BaseBlock block) { private static void randomPlayerHead(BaseBlock block) {
if (block instanceof SkullBlock) { if (block instanceof SkullBlock) {

View File

@@ -19,7 +19,243 @@
package de.steamwar.bausystem.features.slaves.laufbau; package de.steamwar.bausystem.features.slaves.laufbau;
public interface BoundingBoxLoader { import de.steamwar.core.Core;
import de.steamwar.inventory.SWItem;
import de.steamwar.linkage.Linked;
import de.steamwar.linkage.MinVersion;
import de.steamwar.linkage.api.Enable;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.type.*;
import org.bukkit.util.BoundingBox;
import org.bukkit.util.VoxelShape;
void load(); import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.*;
import java.util.Comparator;
import java.util.stream.Collectors;
@MinVersion(20)
@Linked
public class BoundingBoxLoader implements Enable {
private static final World world = Bukkit.getWorlds().get(0);
@Override
public void enable() {
Block block = world.getBlockAt(0, 0, 0);
BlockState blockState = block.getState();
List<Material> materials = Arrays.stream(Material.values())
.filter(material -> !material.isLegacy())
.filter(material -> material.isBlock())
.filter(material -> material.getBlastResistance() <= 9)
.filter(material -> !(material.createBlockData() instanceof Door))
.sorted(Comparator.comparingDouble(material -> -material.getBlastResistance()))
.collect(Collectors.toList());
materials.remove(Material.PITCHER_PLANT);
materials.remove(Material.PITCHER_CROP);
materials.remove(Material.PITCHER_POD);
materials.remove(Material.SCAFFOLDING);
materials.remove(Material.CAULDRON);
if (Core.getVersion() > 20) {
materials.remove(Material.CHISELED_BOOKSHELF);
}
Map<Collection<BoundingBox>, BlockData> uniqueBoundinxBoxes = new HashMap<>();
Sink last = new Sink() {
@Override
protected void sink(BlockData current) {
try {
if (current instanceof Cocoa) {
if (((Cocoa) current).getAge() != ((Cocoa) current).getMaximumAge()) return;
}
if (current instanceof Snow) {
if (((Snow) current).getLayers() == 2) return;
}
if (current instanceof Cake) {
if (((Cake) current).getBites() != 0) return;
}
if (current instanceof Wall) {
((Wall) current).setUp(true);
}
block.setType(Material.AIR);
block.setBlockData(current, false);
} catch (NullPointerException e) {
return;
}
VoxelShape voxelShape = block.getCollisionShape();
if (voxelShape.getBoundingBoxes().isEmpty()) return;
uniqueBoundinxBoxes.putIfAbsent(voxelShape.getBoundingBoxes(), current);
}
};
for (Material material : materials) {
BlockData blockData = material.createBlockData();
Set<Class<? extends BlockData>> interfaces = getInterfaces(blockData.getClass());
interfaces.remove(BlockData.class);
List<Sink> sinks = interfaces.stream()
.map(this::getSetters)
.flatMap(Set::stream)
.map(method -> {
try {
return getSink(method);
} catch (UnsupportedOperationException e) {
return null;
}
})
.filter(Objects::nonNull)
.collect(Collectors.toList());
for (int i = 1; i < sinks.size(); i++) {
sinks.get(i - 1).next = sinks.get(i);
}
if (!sinks.isEmpty()) {
sinks.get(sinks.size() - 1).next = last;
sinks.get(0).sink(blockData);
} else {
last.sink(blockData);
}
}
uniqueBoundinxBoxes.forEach((boundingBoxes, blockData) -> {
List<Cuboid> cuboidList = boundingBoxes.stream()
.map(boundingBox -> {
return new Cuboid(boundingBox.getMinX(), boundingBox.getMinY(), boundingBox.getMinZ(), boundingBox.getWidthX(), boundingBox.getHeight(), boundingBox.getWidthZ());
})
.collect(Collectors.toList());
Material material = blockData.getMaterial();
if (!material.isItem()) {
material = blockData.getPlacementMaterial();
}
if (material.isAir() || !material.isItem()) {
material = Material.BARRIER;
}
new BlockBoundingBox(blockData, cuboidList, new SWItem(material, blockData.getMaterial().name()));
});
blockState.update(true, false);
}
private Set<Class<? extends BlockData>> getInterfaces(Class<?> clazz) {
if (clazz == null) return Collections.emptySet();
Set<Class<? extends BlockData>> interfaces = Arrays.stream(clazz.getInterfaces())
.filter(BlockData.class::isAssignableFrom)
.map(aClass -> (Class<? extends BlockData>) aClass)
.collect(Collectors.toSet());
interfaces.addAll(getInterfaces(clazz.getSuperclass()));
interfaces.addAll(interfaces.stream()
.map(this::getInterfaces)
.flatMap(Set::stream)
.collect(Collectors.toSet()));
return interfaces;
}
private Set<Method> getSetters(Class<? extends BlockData> clazz) {
Method[] methods = clazz.getDeclaredMethods();
Set<Method> setters = new HashSet<>();
for (Method method : methods) {
if (method.getName().startsWith("set")) {
setters.add(method);
}
}
return setters;
}
private abstract class Sink {
protected Sink next = null;
protected abstract void sink(BlockData current);
}
private Sink getSink(Method method) {
if (method.getParameterCount() == 1) {
Parameter parameter = method.getParameters()[0];
Object[] values = getValues(parameter);
return new Sink() {
@Override
protected void sink(BlockData current) {
for (Object o : values) {
BlockData cloned = current.clone();
try {
method.invoke(cloned, o);
} catch (Exception e) {
}
next.sink(cloned);
}
}
};
} else if (method.getParameterCount() == 2) {
Parameter firstParameter = method.getParameters()[0];
Parameter secondParameter = method.getParameters()[1];
Object[] firstValues = getValues(firstParameter);
Object[] secondValues = getValues(secondParameter);
return new Sink() {
private Sink outerThis = this;
private List<Sink> sinks = new ArrayList<>();
{
for (int i = 0; i < firstValues.length; i++) {
Object first = firstValues[i];
boolean last = i == firstValues.length - 1;
Sink current = new Sink() {
@Override
protected void sink(BlockData current) {
for (Object second : secondValues) {
BlockData cloned = current.clone();
try {
method.invoke(cloned, first, second);
} catch (Exception e) {
}
if (last) {
outerThis.next.sink(cloned);
} else {
next.sink(cloned);
}
}
}
};
if (!sinks.isEmpty()) {
sinks.get(sinks.size() - 1).next = current;
}
sinks.add(current);
}
}
@Override
protected void sink(BlockData current) {
sinks.get(0).sink(current);
}
};
} else {
throw new UnsupportedOperationException();
}
}
private Object[] getValues(Parameter parameter) {
if (parameter.getType().isEnum()) {
if (BlockFace.class.isAssignableFrom(parameter.getType())) {
return new BlockFace[]{
BlockFace.NORTH,
BlockFace.SOUTH,
BlockFace.EAST,
BlockFace.WEST,
BlockFace.UP,
BlockFace.DOWN
};
}
return parameter.getType().getEnumConstants();
} else if (parameter.getType() == boolean.class || parameter.getType() == Boolean.class) {
return new Object[]{false, true};
} else if (parameter.getType() == int.class || parameter.getType() == Integer.class) {
return new Object[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
} else {
throw new UnsupportedOperationException();
}
}
} }

View File

@@ -115,12 +115,12 @@ public class LaufbauSettings {
} else { } else {
long count = blockBoundingBoxes.stream().filter(bb -> LaufbauUtils.isDeactivated(p, bb)).count(); long count = blockBoundingBoxes.stream().filter(bb -> LaufbauUtils.isDeactivated(p, bb)).count();
if (count == 0) { if (count == 0) {
return new SWItem(material, BauSystem.MESSAGE.parse(group, p), Arrays.asList("", BauSystem.MESSAGE.parse("LAUFBAU_SETTINGS_ACTIVE", p), "", BauSystem.MESSAGE.parse("LAUFBAU_SETTINGS_ADVANCED", p), BauSystem.MESSAGE.parse("LAUFBAU_SETTINGS_TOGGLE", p)), false, clickType -> {}); return new SWItem(material, group/*BauSystem.MESSAGE.parse(group, p)*/, Arrays.asList("", BauSystem.MESSAGE.parse("LAUFBAU_SETTINGS_ACTIVE", p), "", BauSystem.MESSAGE.parse("LAUFBAU_SETTINGS_ADVANCED", p), BauSystem.MESSAGE.parse("LAUFBAU_SETTINGS_TOGGLE", p)), false, clickType -> {});
} }
if (count == blockBoundingBoxes.size()) { if (count == blockBoundingBoxes.size()) {
return new SWItem(material, BauSystem.MESSAGE.parse(group, p), Arrays.asList("", BauSystem.MESSAGE.parse("LAUFBAU_SETTINGS_INACTIVE", p), "", BauSystem.MESSAGE.parse("LAUFBAU_SETTINGS_ADVANCED", p), BauSystem.MESSAGE.parse("LAUFBAU_SETTINGS_TOGGLE", p)), false, clickType -> {}); return new SWItem(material, group/*BauSystem.MESSAGE.parse(group, p)*/, Arrays.asList("", BauSystem.MESSAGE.parse("LAUFBAU_SETTINGS_INACTIVE", p), "", BauSystem.MESSAGE.parse("LAUFBAU_SETTINGS_ADVANCED", p), BauSystem.MESSAGE.parse("LAUFBAU_SETTINGS_TOGGLE", p)), false, clickType -> {});
} }
return new SWItem(material, BauSystem.MESSAGE.parse(group, p), Arrays.asList("", BauSystem.MESSAGE.parse("LAUFBAU_SETTINGS_MIXED", p, blockBoundingBoxes.size() - count, blockBoundingBoxes.size()), "", BauSystem.MESSAGE.parse("LAUFBAU_SETTINGS_ADVANCED", p), BauSystem.MESSAGE.parse("LAUFBAU_SETTINGS_TOGGLE", p)), false, clickType -> {}); return new SWItem(material, group/*BauSystem.MESSAGE.parse(group, p)*/, Arrays.asList("", BauSystem.MESSAGE.parse("LAUFBAU_SETTINGS_MIXED", p, blockBoundingBoxes.size() - count, blockBoundingBoxes.size()), "", BauSystem.MESSAGE.parse("LAUFBAU_SETTINGS_ADVANCED", p), BauSystem.MESSAGE.parse("LAUFBAU_SETTINGS_TOGGLE", p)), false, clickType -> {});
} }
} }

View File

@@ -20,17 +20,14 @@
package de.steamwar.bausystem.features.slaves.laufbau; package de.steamwar.bausystem.features.slaves.laufbau;
import de.steamwar.bausystem.BauSystem; import de.steamwar.bausystem.BauSystem;
import de.steamwar.core.SWPlayer;
import de.steamwar.inventory.SWItem; import de.steamwar.inventory.SWItem;
import de.steamwar.linkage.Linked;
import de.steamwar.sql.UserConfig; import de.steamwar.sql.UserConfig;
import lombok.Cleanup; import lombok.Cleanup;
import lombok.SneakyThrows; import lombok.SneakyThrows;
import lombok.experimental.UtilityClass;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.ItemMeta;
import yapion.hierarchy.output.StreamOutput; import yapion.hierarchy.output.StreamOutput;
import yapion.hierarchy.types.YAPIONObject; import yapion.hierarchy.types.YAPIONObject;
@@ -39,44 +36,45 @@ import yapion.parser.options.StreamOptions;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.util.*; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.zip.GZIPInputStream; import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream; import java.util.zip.GZIPOutputStream;
@Linked @UtilityClass
public class LaufbauUtils implements Listener { public class LaufbauUtils {
private static Map<Player, YAPIONObject> yapionObjectMap = new HashMap<>(); public static class LaufbauComponent implements SWPlayer.Component {
@EventHandler private YAPIONObject yapionObject = new YAPIONObject();
@SneakyThrows
public void onPlayerJoin(PlayerJoinEvent event) {
String config = UserConfig.getConfig(event.getPlayer().getUniqueId(), "bausystem-laufbau");
if (config == null) {
return;
}
byte[] bytes = Base64.getDecoder().decode(config);
@Cleanup GZIPInputStream gzipInputStream = new GZIPInputStream(new ByteArrayInputStream(bytes));
YAPIONObject yapionObject = new YAPIONParser(gzipInputStream, new StreamOptions().stopOnStreamEnd(true)).parse().result();
yapionObjectMap.put(event.getPlayer(), yapionObject);
}
@EventHandler @Override
@SneakyThrows @SneakyThrows
public void onPlayerQuit(PlayerQuitEvent event) { public void onMount(SWPlayer player) {
YAPIONObject yapionObject = yapionObjectMap.get(event.getPlayer()); String config = UserConfig.getConfig(player.getPlayer().getUniqueId(), "bausystem-laufbau");
if (yapionObject == null) { if (config == null) {
return; return;
}
byte[] bytes = Base64.getDecoder().decode(config);
@Cleanup GZIPInputStream gzipInputStream = new GZIPInputStream(new ByteArrayInputStream(bytes));
yapionObject = new YAPIONParser(gzipInputStream, new StreamOptions().stopOnStreamEnd(true)).parse().result();
} }
if (yapionObject.isEmpty()) {
UserConfig.removePlayerConfig(event.getPlayer().getUniqueId(), "bausystem-laufbau"); @Override
return; @SneakyThrows
public void onUnmount(SWPlayer player) {
if (yapionObject.isEmpty()) {
UserConfig.removePlayerConfig(player.getPlayer().getUniqueId(), "bausystem-laufbau");
return;
}
@Cleanup ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
@Cleanup GZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream);
yapionObject.toYAPION(new StreamOutput(gzipOutputStream)).close();
UserConfig.updatePlayerConfig(player.getPlayer().getUniqueId(), "bausystem-laufbau", Base64.getEncoder().encodeToString(byteArrayOutputStream.toByteArray()));
} }
@Cleanup ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
@Cleanup GZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream);
yapionObject.toYAPION(new StreamOutput(gzipOutputStream)).close();
UserConfig.updatePlayerConfig(event.getPlayer().getUniqueId(), "bausystem-laufbau", Base64.getEncoder().encodeToString(byteArrayOutputStream.toByteArray()));
} }
public static Cuboid pixelCuboid(double pixelX, double pixelY, double pixelZ, double pixelDX, double pixelDY, double pixelDZ) { public static Cuboid pixelCuboid(double pixelX, double pixelY, double pixelZ, double pixelDX, double pixelDY, double pixelDZ) {
@@ -93,6 +91,7 @@ public class LaufbauUtils implements Listener {
} }
public static SWItem translateItem(SWItem item, Player p) { public static SWItem translateItem(SWItem item, Player p) {
if (true) return item;
ItemMeta itemMeta = item.getItemMeta(); ItemMeta itemMeta = item.getItemMeta();
List<String> lore = new ArrayList<>(); List<String> lore = new ArrayList<>();
if (itemMeta.getLore() != null) { if (itemMeta.getLore() != null) {
@@ -121,28 +120,22 @@ public class LaufbauUtils implements Listener {
@SneakyThrows @SneakyThrows
public static boolean isDeactivated(Player p, BlockBoundingBox bb) { public static boolean isDeactivated(Player p, BlockBoundingBox bb) {
if (true) return false;
if (bb.getSwItem() == null) { if (bb.getSwItem() == null) {
return false; return false;
} }
String identifier = identifier(bb); String identifier = identifier(bb);
YAPIONObject yapionObject = yapionObjectMap.get(p); return SWPlayer.of(p).getComponentOrDefault(LaufbauComponent.class, LaufbauComponent::new).yapionObject.containsKey(identifier);
if (yapionObject == null) {
return false;
}
return yapionObject.containsKey(identifier);
} }
@SneakyThrows @SneakyThrows
public static void toggle(Player p, BlockBoundingBox bb) { public static void toggle(Player p, BlockBoundingBox bb) {
if (true) return;
if (bb.getSwItem() == null) { if (bb.getSwItem() == null) {
return; return;
} }
String identifier = identifier(bb); String identifier = identifier(bb);
YAPIONObject yapionObject = yapionObjectMap.get(p); YAPIONObject yapionObject = SWPlayer.of(p).getComponentOrDefault(LaufbauComponent.class, LaufbauComponent::new).yapionObject;
if (yapionObject == null) {
yapionObject = new YAPIONObject();
yapionObjectMap.put(p, yapionObject);
}
if (yapionObject.containsKey(identifier)) { if (yapionObject.containsKey(identifier)) {
yapionObject.remove(identifier); yapionObject.remove(identifier);
} else { } else {

View File

@@ -1,263 +0,0 @@
/*
* 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.slaves.laufbau.boundingboxes;
import de.steamwar.bausystem.features.slaves.laufbau.BlockBoundingBox;
import de.steamwar.bausystem.features.slaves.laufbau.BoundingBoxLoader;
import de.steamwar.bausystem.features.slaves.laufbau.Cuboid;
import de.steamwar.linkage.Linked;
import de.steamwar.linkage.MinVersion;
import org.bukkit.Material;
import org.bukkit.block.BlockFace;
import org.bukkit.block.data.type.AmethystCluster;
import java.util.ArrayList;
import java.util.List;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.createItem;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.pixelCuboid;
@Linked
@MinVersion(19)
public class AmethystBoundingBox implements BoundingBoxLoader {
@Override
public void load() {
floorSmallAmethystBud();
ceilingSmallAmethystBud();
northSmallAmethystBud();
southSmallAmethystBud();
eastSmallAmethystBud();
westSmallAmethystBud();
floorMediumAmethystBud();
ceilingMediumAmethystBud();
northMediumAmethystBud();
southMediumAmethystBud();
eastMediumAmethystBud();
westMediumAmethystBud();
floorLargeAmethystBud();
ceilingLargeAmethystBud();
northLargeAmethystBud();
southLargeAmethystBud();
eastLargeAmethystBud();
westLargeAmethystBud();
floorAmethystCluster();
ceilingAmethystCluster();
northAmethystCluster();
southAmethystCluster();
eastAmethystCluster();
westAmethystCluster();
}
private void floorSmallAmethystBud() {
AmethystCluster cluster = (AmethystCluster) Material.SMALL_AMETHYST_BUD.createBlockData();
cluster.setFacing(BlockFace.UP);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(4, 0, 4, 8, 3, 8));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_SMALL_AMETHYST_BUD", Material.SMALL_AMETHYST_BUD, "LAUFBAU_FACING_UP"));
}
private void ceilingSmallAmethystBud() {
AmethystCluster cluster = (AmethystCluster) Material.SMALL_AMETHYST_BUD.createBlockData();
cluster.setFacing(BlockFace.DOWN);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(4, 13, 4, 8, 3, 8));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_SMALL_AMETHYST_BUD", Material.SMALL_AMETHYST_BUD, "LAUFBAU_FACING_DOWN"));
}
private void northSmallAmethystBud() {
AmethystCluster cluster = (AmethystCluster) Material.SMALL_AMETHYST_BUD.createBlockData();
cluster.setFacing(BlockFace.NORTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(4, 4, 13, 8, 8, 3));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_SMALL_AMETHYST_BUD", Material.SMALL_AMETHYST_BUD, "LAUFBAU_FACING_NORTH"));
}
private void southSmallAmethystBud() {
AmethystCluster cluster = (AmethystCluster) Material.SMALL_AMETHYST_BUD.createBlockData();
cluster.setFacing(BlockFace.SOUTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(4, 4, 0, 8, 8, 3));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_SMALL_AMETHYST_BUD", Material.SMALL_AMETHYST_BUD, "LAUFBAU_FACING_SOUTH"));
}
private void eastSmallAmethystBud() {
AmethystCluster cluster = (AmethystCluster) Material.SMALL_AMETHYST_BUD.createBlockData();
cluster.setFacing(BlockFace.EAST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 4, 4, 3, 8, 8));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_SMALL_AMETHYST_BUD", Material.SMALL_AMETHYST_BUD, "LAUFBAU_FACING_EAST"));
}
private void westSmallAmethystBud() {
AmethystCluster cluster = (AmethystCluster) Material.SMALL_AMETHYST_BUD.createBlockData();
cluster.setFacing(BlockFace.WEST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(13, 4, 4, 3, 8, 8));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_SMALL_AMETHYST_BUD", Material.SMALL_AMETHYST_BUD, "LAUFBAU_FACING_WEST"));
}
private void floorMediumAmethystBud() {
AmethystCluster cluster = (AmethystCluster) Material.MEDIUM_AMETHYST_BUD.createBlockData();
cluster.setFacing(BlockFace.UP);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(3, 0, 3, 10, 4, 10));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_MEDIUM_AMETHYST_BUD", Material.MEDIUM_AMETHYST_BUD, "LAUFBAU_FACING_UP"));
}
private void ceilingMediumAmethystBud() {
AmethystCluster cluster = (AmethystCluster) Material.MEDIUM_AMETHYST_BUD.createBlockData();
cluster.setFacing(BlockFace.DOWN);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(3, 12, 3, 10, 4, 10));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_MEDIUM_AMETHYST_BUD", Material.MEDIUM_AMETHYST_BUD, "LAUFBAU_FACING_DOWN"));
}
private void northMediumAmethystBud() {
AmethystCluster cluster = (AmethystCluster) Material.MEDIUM_AMETHYST_BUD.createBlockData();
cluster.setFacing(BlockFace.NORTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(3, 3, 12, 10, 10, 4));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_MEDIUM_AMETHYST_BUD", Material.MEDIUM_AMETHYST_BUD, "LAUFBAU_FACING_NORTH"));
}
private void southMediumAmethystBud() {
AmethystCluster cluster = (AmethystCluster) Material.MEDIUM_AMETHYST_BUD.createBlockData();
cluster.setFacing(BlockFace.SOUTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(3, 3, 0, 10, 10, 4));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_MEDIUM_AMETHYST_BUD", Material.MEDIUM_AMETHYST_BUD, "LAUFBAU_FACING_SOUTH"));
}
private void eastMediumAmethystBud() {
AmethystCluster cluster = (AmethystCluster) Material.MEDIUM_AMETHYST_BUD.createBlockData();
cluster.setFacing(BlockFace.EAST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 3, 3, 4, 10, 10));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_MEDIUM_AMETHYST_BUD", Material.MEDIUM_AMETHYST_BUD, "LAUFBAU_FACING_EAST"));
}
private void westMediumAmethystBud() {
AmethystCluster cluster = (AmethystCluster) Material.MEDIUM_AMETHYST_BUD.createBlockData();
cluster.setFacing(BlockFace.WEST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(12, 3, 3, 4, 10, 10));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_MEDIUM_AMETHYST_BUD", Material.MEDIUM_AMETHYST_BUD, "LAUFBAU_FACING_WEST"));
}
private void floorLargeAmethystBud() {
AmethystCluster cluster = (AmethystCluster) Material.LARGE_AMETHYST_BUD.createBlockData();
cluster.setFacing(BlockFace.UP);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(3, 0, 3, 10, 5, 10));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_LARGE_AMETHYST_BUD", Material.LARGE_AMETHYST_BUD, "LAUFBAU_FACING_UP"));
}
private void ceilingLargeAmethystBud() {
AmethystCluster cluster = (AmethystCluster) Material.LARGE_AMETHYST_BUD.createBlockData();
cluster.setFacing(BlockFace.DOWN);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(3, 11, 3, 10, 5, 10));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_LARGE_AMETHYST_BUD", Material.LARGE_AMETHYST_BUD, "LAUFBAU_FACING_DOWN"));
}
private void northLargeAmethystBud() {
AmethystCluster cluster = (AmethystCluster) Material.LARGE_AMETHYST_BUD.createBlockData();
cluster.setFacing(BlockFace.NORTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(3, 3, 11, 10, 10, 5));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_LARGE_AMETHYST_BUD", Material.LARGE_AMETHYST_BUD, "LAUFBAU_FACING_NORTH"));
}
private void southLargeAmethystBud() {
AmethystCluster cluster = (AmethystCluster) Material.LARGE_AMETHYST_BUD.createBlockData();
cluster.setFacing(BlockFace.SOUTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(3, 3, 0, 10, 10, 5));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_LARGE_AMETHYST_BUD", Material.LARGE_AMETHYST_BUD, "LAUFBAU_FACING_SOUTH"));
}
private void eastLargeAmethystBud() {
AmethystCluster cluster = (AmethystCluster) Material.LARGE_AMETHYST_BUD.createBlockData();
cluster.setFacing(BlockFace.EAST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 3, 3, 5, 10, 10));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_LARGE_AMETHYST_BUD", Material.LARGE_AMETHYST_BUD, "LAUFBAU_FACING_EAST"));
}
private void westLargeAmethystBud() {
AmethystCluster cluster = (AmethystCluster) Material.LARGE_AMETHYST_BUD.createBlockData();
cluster.setFacing(BlockFace.WEST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(11, 3, 3, 5, 10, 10));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_LARGE_AMETHYST_BUD", Material.LARGE_AMETHYST_BUD, "LAUFBAU_FACING_WEST"));
}
private void floorAmethystCluster() {
AmethystCluster cluster = (AmethystCluster) Material.AMETHYST_CLUSTER.createBlockData();
cluster.setFacing(BlockFace.UP);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(3, 0, 3, 10, 7, 10));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_AMETHYST_CLUSTER", Material.AMETHYST_CLUSTER, "LAUFBAU_FACING_UP"));
}
private void ceilingAmethystCluster() {
AmethystCluster cluster = (AmethystCluster) Material.AMETHYST_CLUSTER.createBlockData();
cluster.setFacing(BlockFace.DOWN);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(3, 9, 3, 10, 7, 10));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_AMETHYST_CLUSTER", Material.AMETHYST_CLUSTER, "LAUFBAU_FACING_DOWN"));
}
private void northAmethystCluster() {
AmethystCluster cluster = (AmethystCluster) Material.AMETHYST_CLUSTER.createBlockData();
cluster.setFacing(BlockFace.NORTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(3, 3, 9, 10, 10, 7));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_AMETHYST_CLUSTER", Material.AMETHYST_CLUSTER, "LAUFBAU_FACING_NORTH"));
}
private void southAmethystCluster() {
AmethystCluster cluster = (AmethystCluster) Material.AMETHYST_CLUSTER.createBlockData();
cluster.setFacing(BlockFace.SOUTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(3, 3, 0, 10, 10, 7));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_AMETHYST_CLUSTER", Material.AMETHYST_CLUSTER, "LAUFBAU_FACING_SOUTH"));
}
private void eastAmethystCluster() {
AmethystCluster cluster = (AmethystCluster) Material.AMETHYST_CLUSTER.createBlockData();
cluster.setFacing(BlockFace.EAST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 3, 3, 7, 10, 10));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_AMETHYST_CLUSTER", Material.AMETHYST_CLUSTER, "LAUFBAU_FACING_EAST"));
}
private void westAmethystCluster() {
AmethystCluster cluster = (AmethystCluster) Material.AMETHYST_CLUSTER.createBlockData();
cluster.setFacing(BlockFace.WEST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(9, 3, 3, 7, 10, 10));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_AMETHYST_CLUSTER", Material.AMETHYST_CLUSTER, "LAUFBAU_FACING_WEST"));
}
}

View File

@@ -1,48 +0,0 @@
/*
* 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.slaves.laufbau.boundingboxes;
import de.steamwar.bausystem.features.slaves.laufbau.BlockBoundingBox;
import de.steamwar.bausystem.features.slaves.laufbau.BoundingBoxLoader;
import de.steamwar.bausystem.features.slaves.laufbau.Cuboid;
import de.steamwar.linkage.Linked;
import de.steamwar.linkage.MinVersion;
import org.bukkit.Material;
import org.bukkit.block.data.BlockData;
import java.util.ArrayList;
import java.util.List;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.createItem;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.pixelCuboid;
@Linked
@MinVersion(19)
public class AzaleaBoundingBox implements BoundingBoxLoader {
@Override
public void load() {
BlockData blockData = Material.FLOWERING_AZALEA.createBlockData();
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 8, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(6, 0, 6, 4, 8, 4));
new BlockBoundingBox(blockData, cuboidList, createItem("LAUFBAU_BLOCK_AZALEA", Material.FLOWERING_AZALEA));
}
}

View File

@@ -1,149 +0,0 @@
/*
* 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.slaves.laufbau.boundingboxes;
import de.steamwar.bausystem.features.slaves.laufbau.BlockBoundingBox;
import de.steamwar.bausystem.features.slaves.laufbau.BoundingBoxLoader;
import de.steamwar.bausystem.features.slaves.laufbau.Cuboid;
import de.steamwar.linkage.Linked;
import org.bukkit.Material;
import org.bukkit.block.BlockFace;
import org.bukkit.block.data.type.Bell;
import java.util.ArrayList;
import java.util.List;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.createItem;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.pixelCuboid;
@Linked
public class BellBoundingBox implements BoundingBoxLoader {
@Override
public void load() {
ceilingBell();
floorNorthBell();
floorEastBell();
doubleWallNorthBell();
doubleWallEastBell();
singleWallNorthBell();
singleWallSouthBell();
singleWallEastBell();
singleWallWestBell();
}
public void ceilingBell() {
Bell bell = (Bell) Material.BELL.createBlockData();
bell.setAttachment(Bell.Attachment.CEILING);
bell.setFacing(BlockFace.NORTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(4, 4, 4, 8, 2, 8));
cuboidList.add(pixelCuboid(5, 6, 5, 6, 8, 6));
cuboidList.add(pixelCuboid(7, 13, 7, 2, 3, 2));
new BlockBoundingBox(bell, cuboidList, createItem("LAUFBAU_BLOCK_BELL", Material.BELL, "LAUFBAU_ATTACHMENT_CEILING"));
}
public void floorNorthBell() {
Bell bell = (Bell) Material.BELL.createBlockData();
bell.setAttachment(Bell.Attachment.FLOOR);
bell.setFacing(BlockFace.NORTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 0, 4, 16, 16, 8));
new BlockBoundingBox(bell, cuboidList, createItem("LAUFBAU_BLOCK_BELL", Material.BELL, "LAUFBAU_ATTACHMENT_FLOOR", "LAUFBAU_FACING_NORTH", "LAUFBAU_FACING_SOUTH"));
}
public void floorEastBell() {
Bell bell = (Bell) Material.BELL.createBlockData();
bell.setAttachment(Bell.Attachment.FLOOR);
bell.setFacing(BlockFace.EAST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(4, 0, 0, 8, 16, 16));
new BlockBoundingBox(bell, cuboidList, createItem("LAUFBAU_BLOCK_BELL", Material.BELL, "LAUFBAU_ATTACHMENT_FLOOR", "LAUFBAU_FACING_EAST", "LAUFBAU_FACING_WEST"));
}
public void doubleWallNorthBell() {
Bell bell = (Bell) Material.BELL.createBlockData();
bell.setAttachment(Bell.Attachment.DOUBLE_WALL);
bell.setFacing(BlockFace.NORTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(4, 4, 4, 8, 2, 8));
cuboidList.add(pixelCuboid(5, 6, 5, 6, 8, 6));
cuboidList.add(pixelCuboid(7, 13, 0, 2, 2, 16));
new BlockBoundingBox(bell, cuboidList, createItem("LAUFBAU_BLOCK_BELL", Material.BELL, "LAUFBAU_ATTACHMENT_DOUBLE_WALL", "LAUFBAU_FACING_NORTH"));
}
public void doubleWallEastBell() {
Bell bell = (Bell) Material.BELL.createBlockData();
bell.setAttachment(Bell.Attachment.DOUBLE_WALL);
bell.setFacing(BlockFace.EAST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(4, 4, 4, 8, 2, 8));
cuboidList.add(pixelCuboid(5, 6, 5, 6, 8, 6));
cuboidList.add(pixelCuboid(0, 13, 7, 16, 2, 2));
new BlockBoundingBox(bell, cuboidList, createItem("LAUFBAU_BLOCK_BELL", Material.BELL, "LAUFBAU_ATTACHMENT_DOUBLE_WALL", "LAUFBAU_FACING_EAST"));
}
public void singleWallNorthBell() {
Bell bell = (Bell) Material.BELL.createBlockData();
bell.setAttachment(Bell.Attachment.SINGLE_WALL);
bell.setFacing(BlockFace.NORTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(4, 4, 4, 8, 2, 8));
cuboidList.add(pixelCuboid(5, 6, 5, 6, 8, 6));
cuboidList.add(pixelCuboid(7, 13, 0, 2, 2, 13));
new BlockBoundingBox(bell, cuboidList, createItem("LAUFBAU_BLOCK_BELL", Material.BELL, "LAUFBAU_ATTACHMENT_SINGLE_WALL", "LAUFBAU_FACING_NORTH"));
}
public void singleWallSouthBell() {
Bell bell = (Bell) Material.BELL.createBlockData();
bell.setAttachment(Bell.Attachment.SINGLE_WALL);
bell.setFacing(BlockFace.SOUTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(4, 4, 4, 8, 2, 8));
cuboidList.add(pixelCuboid(5, 6, 5, 6, 8, 6));
cuboidList.add(pixelCuboid(7, 13, 3, 2, 2, 13));
new BlockBoundingBox(bell, cuboidList, createItem("LAUFBAU_BLOCK_BELL", Material.BELL, "LAUFBAU_ATTACHMENT_SINGLE_WALL", "LAUFBAU_FACING_SOUTH"));
}
public void singleWallEastBell() {
Bell bell = (Bell) Material.BELL.createBlockData();
bell.setAttachment(Bell.Attachment.SINGLE_WALL);
bell.setFacing(BlockFace.EAST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(4, 4, 4, 8, 2, 8));
cuboidList.add(pixelCuboid(5, 6, 5, 6, 8, 6));
cuboidList.add(pixelCuboid(3, 13, 7, 13, 2, 2));
new BlockBoundingBox(bell, cuboidList, createItem("LAUFBAU_BLOCK_BELL", Material.BELL, "LAUFBAU_ATTACHMENT_SINGLE_WALL", "LAUFBAU_FACING_EAST"));
}
public void singleWallWestBell() {
Bell bell = (Bell) Material.BELL.createBlockData();
bell.setAttachment(Bell.Attachment.SINGLE_WALL);
bell.setFacing(BlockFace.WEST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(4, 4, 4, 8, 2, 8));
cuboidList.add(pixelCuboid(5, 6, 5, 6, 8, 6));
cuboidList.add(pixelCuboid(0, 13, 7, 13, 2, 2));
new BlockBoundingBox(bell, cuboidList, createItem("LAUFBAU_BLOCK_BELL", Material.BELL, "LAUFBAU_ATTACHMENT_SINGLE_WALL", "LAUFBAU_FACING_WEST"));
}
}

View File

@@ -1,46 +0,0 @@
/*
* 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.slaves.laufbau.boundingboxes;
import de.steamwar.bausystem.features.slaves.laufbau.BlockBoundingBox;
import de.steamwar.bausystem.features.slaves.laufbau.BoundingBoxLoader;
import de.steamwar.bausystem.features.slaves.laufbau.Cuboid;
import de.steamwar.linkage.Linked;
import org.bukkit.Material;
import org.bukkit.block.data.type.BrewingStand;
import java.util.ArrayList;
import java.util.List;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.createItem;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.pixelCuboid;
@Linked
public class BrewingStandBoundingBox implements BoundingBoxLoader {
@Override
public void load() {
BrewingStand brewingStand = (BrewingStand) Material.BREWING_STAND.createBlockData();
List<Cuboid> cuboids = new ArrayList<>();
cuboids.add(pixelCuboid(1, 0, 1, 14, 2, 14));
cuboids.add(pixelCuboid(7, 2, 7, 2, 12, 2));
new BlockBoundingBox(brewingStand, cuboids, createItem("LAUFBAU_BLOCK_BREWING_STAND", Material.BREWING_STAND));
}
}

View File

@@ -1,64 +0,0 @@
/*
* 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.slaves.laufbau.boundingboxes;
import de.steamwar.bausystem.features.slaves.laufbau.BlockBoundingBox;
import de.steamwar.bausystem.features.slaves.laufbau.BoundingBoxLoader;
import de.steamwar.bausystem.features.slaves.laufbau.Cuboid;
import de.steamwar.linkage.Linked;
import de.steamwar.linkage.MinVersion;
import org.bukkit.Material;
import org.bukkit.block.data.Lightable;
import org.bukkit.block.data.type.Candle;
import java.util.ArrayList;
import java.util.List;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.createItem;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.pixelCuboid;
@Linked
@MinVersion(19)
public class CandleBoundingBox implements BoundingBoxLoader {
@Override
public void load() {
caked();
single();
}
private void caked() {
Lightable candleCake = (Lightable) Material.CYAN_CANDLE_CAKE.createBlockData();
candleCake.setLit(true);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 0, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(7, 8, 7, 2, 6, 2));
new BlockBoundingBox(candleCake, cuboidList, createItem("LAUFBAU_BLOCK_CANDLE_CAKE", Material.CAKE));
}
private void single() {
Candle candle = (Candle) Material.CYAN_CANDLE.createBlockData();
candle.setCandles(1);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(7, 0,7, 2, 6, 2));
new BlockBoundingBox(candle, cuboidList, createItem("LAUFBAU_BLOCK_CANDLE", Material.CYAN_CANDLE, "LAUFBAU_COUNT_1"));
}
}

View File

@@ -1,71 +0,0 @@
/*
* 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.slaves.laufbau.boundingboxes;
import de.steamwar.bausystem.features.slaves.laufbau.BlockBoundingBox;
import de.steamwar.bausystem.features.slaves.laufbau.BoundingBoxLoader;
import de.steamwar.bausystem.features.slaves.laufbau.Cuboid;
import de.steamwar.linkage.Linked;
import de.steamwar.linkage.MinVersion;
import org.bukkit.Axis;
import org.bukkit.Material;
import org.bukkit.block.data.Orientable;
import java.util.ArrayList;
import java.util.List;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.createItem;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.pixelCuboid;
@Linked
@MinVersion(19)
public class ChainBoundingBox implements BoundingBoxLoader {
@Override
public void load() {
bottomTopChain();
northSouthChain();
eastWestChain();
}
private void bottomTopChain() {
Orientable chainBottomTop = (Orientable) Material.CHAIN.createBlockData();
chainBottomTop.setAxis(Axis.Y);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(6.5, 0, 6.5, 3, 16, 3));
new BlockBoundingBox(chainBottomTop, cuboidList, createItem("LAUFBAU_BLOCK_CHAIN", Material.CHAIN, "LAUFBAU_FACING_UP", "LAUFBAU_FACING_DOWN"));
}
private void northSouthChain() {
Orientable chainBottomTop = (Orientable) Material.CHAIN.createBlockData();
chainBottomTop.setAxis(Axis.Z);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(6.5, 6.5, 0, 3, 3, 16));
new BlockBoundingBox(chainBottomTop, cuboidList, createItem("LAUFBAU_BLOCK_CHAIN", Material.CHAIN, "LAUFBAU_FACING_NORTH", "LAUFBAU_FACING_SOUTH"));
}
private void eastWestChain() {
Orientable chainBottomTop = (Orientable) Material.CHAIN.createBlockData();
chainBottomTop.setAxis(Axis.X);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 6.5, 6.5, 16, 3, 3));
new BlockBoundingBox(chainBottomTop, cuboidList, createItem("LAUFBAU_BLOCK_CHAIN", Material.CHAIN, "LAUFBAU_FACING_EAST", "LAUFBAU_FACING_WEST"));
}
}

View File

@@ -1,89 +0,0 @@
/*
* 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.slaves.laufbau.boundingboxes;
import de.steamwar.bausystem.features.slaves.laufbau.BlockBoundingBox;
import de.steamwar.bausystem.features.slaves.laufbau.BoundingBoxLoader;
import de.steamwar.bausystem.features.slaves.laufbau.Cuboid;
import de.steamwar.linkage.Linked;
import org.bukkit.Material;
import org.bukkit.block.BlockFace;
import org.bukkit.block.data.MultipleFacing;
import java.util.ArrayList;
import java.util.List;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.createItem;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.pixelCuboid;
@Linked
public class ChorusPlantBoundingBox implements BoundingBoxLoader {
@Override
public void load() {
for (int nx = 0; nx < 2; nx++) {
for (int ny = 0; ny < 2; ny++) {
for (int nz = 0; nz < 2; nz++) {
for (int px = 0; px < 2; px++) {
for (int py = 0; py < 2; py++) {
for (int pz = 0; pz < 2; pz++) {
MultipleFacing chorusPlant = (MultipleFacing) Material.CHORUS_PLANT.createBlockData();
List<String> lore = new ArrayList<>();
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(3, 3, 3, 10, 10, 10));
if (nx == 1) {
lore.add("LAUFBAU_CONNECTION_WEST");
chorusPlant.setFace(BlockFace.WEST, true);
cuboidList.add(pixelCuboid(0, 3, 3, 3, 10, 10));
}
if (ny == 1) {
lore.add("LAUFBAU_CONNECTION_DOWN");
chorusPlant.setFace(BlockFace.DOWN, true);
cuboidList.add(pixelCuboid(3, 0, 3, 10, 3, 10));
}
if (nz == 1) {
lore.add("LAUFBAU_CONNECTION_NORTH");
chorusPlant.setFace(BlockFace.NORTH, true);
cuboidList.add(pixelCuboid(3, 3, 0, 10, 10, 3));
}
if (px == 1) {
lore.add("LAUFBAU_CONNECTION_EAST");
chorusPlant.setFace(BlockFace.EAST, true);
cuboidList.add(pixelCuboid(13, 3, 3, 3, 10, 10));
}
if (py == 1) {
lore.add("LAUFBAU_CONNECTION_UP");
chorusPlant.setFace(BlockFace.UP, true);
cuboidList.add(pixelCuboid(3, 13, 3, 10, 3, 10));
}
if (pz == 1) {
lore.add("LAUFBAU_CONNECTION_SOUTH");
chorusPlant.setFace(BlockFace.SOUTH, true);
cuboidList.add(pixelCuboid(3, 3, 13, 10, 10, 3));
}
new BlockBoundingBox(chorusPlant, cuboidList, createItem("LAUFBAU_BLOCK_CHORUS_PLANT", Material.CHORUS_PLANT, lore.toArray(new String[0])));
}
}
}
}
}
}
}
}

View File

@@ -1,47 +0,0 @@
/*
* 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.slaves.laufbau.boundingboxes;
import de.steamwar.bausystem.features.slaves.laufbau.BlockBoundingBox;
import de.steamwar.bausystem.features.slaves.laufbau.BoundingBoxLoader;
import de.steamwar.bausystem.features.slaves.laufbau.Cuboid;
import de.steamwar.linkage.Linked;
import de.steamwar.linkage.MinVersion;
import org.bukkit.Material;
import org.bukkit.block.data.BlockData;
import java.util.ArrayList;
import java.util.List;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.createItem;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.pixelCuboid;
@Linked
@MinVersion(19)
public class DragonEggBoundingBox implements BoundingBoxLoader {
@Override
public void load() {
BlockData blockData = Material.DRAGON_EGG.createBlockData();
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(1, 0, 1, 14, 16, 14));
new BlockBoundingBox(blockData, cuboidList, createItem("LAUFBAU_BLOCK_DRAGON_EGG", Material.DRAGON_EGG));
}
}

View File

@@ -1,61 +0,0 @@
/*
* 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.slaves.laufbau.boundingboxes;
import de.steamwar.bausystem.features.slaves.laufbau.BlockBoundingBox;
import de.steamwar.bausystem.features.slaves.laufbau.BoundingBoxLoader;
import de.steamwar.bausystem.features.slaves.laufbau.Cuboid;
import de.steamwar.linkage.Linked;
import de.steamwar.linkage.MinVersion;
import org.bukkit.Material;
import org.bukkit.block.data.type.BigDripleaf;
import java.util.ArrayList;
import java.util.List;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.createItem;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.pixelCuboid;
@Linked
@MinVersion(19)
public class DripLeafBoundingBox implements BoundingBoxLoader {
@Override
public void load() {
tiltNone();
tiltPartial();
}
private void tiltNone() {
BigDripleaf bigDripleaf = (BigDripleaf) Material.BIG_DRIPLEAF.createBlockData();
bigDripleaf.setTilt(BigDripleaf.Tilt.NONE);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 11, 0, 16, 4, 16));
new BlockBoundingBox(bigDripleaf, cuboidList, createItem("LAUFBAU_BLOCK_BIG_DRIP_LEAF", Material.BIG_DRIPLEAF, "LAUFBAU_TILT_NONE"));
}
private void tiltPartial() {
BigDripleaf bigDripleaf = (BigDripleaf) Material.BIG_DRIPLEAF.createBlockData();
bigDripleaf.setTilt(BigDripleaf.Tilt.PARTIAL);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 11, 0, 16, 2, 16));
new BlockBoundingBox(bigDripleaf, cuboidList, createItem("LAUFBAU_BLOCK_BIG_DRIP_LEAF", Material.BIG_DRIPLEAF, "LAUFBAU_TILT_PARTIAL"));
}
}

View File

@@ -1,75 +0,0 @@
/*
* 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.slaves.laufbau.boundingboxes;
import de.steamwar.bausystem.features.slaves.laufbau.BlockBoundingBox;
import de.steamwar.bausystem.features.slaves.laufbau.BoundingBoxLoader;
import de.steamwar.bausystem.features.slaves.laufbau.Cuboid;
import de.steamwar.linkage.Linked;
import org.bukkit.Material;
import org.bukkit.block.BlockFace;
import org.bukkit.block.data.type.Fence;
import java.util.ArrayList;
import java.util.List;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.createItem;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.pixelCuboid;
@Linked
public class FencesBoundingBox implements BoundingBoxLoader {
@Override
public void load() {
for (int nx = 0; nx < 2; nx++) {
for (int nz = 0; nz < 2; nz++) {
for (int px = 0; px < 2; px++) {
for (int pz = 0; pz < 2; pz++) {
Fence fence = (Fence) Material.NETHER_BRICK_FENCE.createBlockData();
List<String> lore = new ArrayList<>();
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(6, 0, 6, 4, 24, 4));
if (nz == 1) {
lore.add("LAUFBAU_CONNECTION_NORTH");
fence.setFace(BlockFace.NORTH, true);
cuboidList.add(pixelCuboid(6, 0, 0, 4, 24, 6));
}
if (pz == 1) {
lore.add("LAUFBAU_CONNECTION_SOUTH");
fence.setFace(BlockFace.SOUTH, true);
cuboidList.add(pixelCuboid(6, 0, 10, 4, 24, 6));
}
if (nx == 1) {
lore.add("LAUFBAU_CONNECTION_WEST");
fence.setFace(BlockFace.WEST, true);
cuboidList.add(pixelCuboid(0, 0, 6, 6, 24, 4));
}
if (px == 1) {
lore.add("LAUFBAU_CONNECTION_EAST");
fence.setFace(BlockFace.EAST, true);
cuboidList.add(pixelCuboid(10, 0, 6, 6, 24, 4));
}
new BlockBoundingBox(fence, cuboidList, createItem("LAUFBAU_BLOCK_NETHER_BRICK_FENCE", Material.NETHER_BRICK_FENCE, lore.toArray(new String[0])));
}
}
}
}
}
}

View File

@@ -1,157 +0,0 @@
/*
* 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.slaves.laufbau.boundingboxes;
import de.steamwar.bausystem.features.slaves.laufbau.BlockBoundingBox;
import de.steamwar.bausystem.features.slaves.laufbau.BoundingBoxLoader;
import de.steamwar.bausystem.features.slaves.laufbau.Cuboid;
import de.steamwar.linkage.Linked;
import org.bukkit.Material;
import org.bukkit.block.BlockFace;
import org.bukkit.block.data.FaceAttachable;
import org.bukkit.block.data.type.Grindstone;
import java.util.ArrayList;
import java.util.List;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.createItem;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.pixelCuboid;
@Linked
public class GrindstoneBoundingBox implements BoundingBoxLoader {
@Override
public void load() {
floorNorthGrindstone();
floorEastGrindstone();
ceilingNorthGrindstone();
ceilingEastGrindstone();
wallNorthGrindstone();
wallSouthGrindstone();
wallEastGrindstone();
wallWestGrindstone();
}
public void floorNorthGrindstone() {
Grindstone grindstone = (Grindstone) Material.GRINDSTONE.createBlockData();
grindstone.setAttachedFace(FaceAttachable.AttachedFace.FLOOR);
grindstone.setFacing(BlockFace.NORTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(4, 4, 2, 8, 12, 12));
cuboidList.add(pixelCuboid(2, 0, 6, 2, 7, 4));
cuboidList.add(pixelCuboid(12, 0, 6, 2, 7, 4));
cuboidList.add(pixelCuboid(2, 7, 5, 2, 6, 6));
cuboidList.add(pixelCuboid(12, 7, 5, 2, 6, 6));
new BlockBoundingBox(grindstone, cuboidList, createItem("LAUFBAU_BLOCK_GRINDSTONE", Material.GRINDSTONE, "LAUFBAU_ATTACHMENT_FLOOR", "LAUFBAU_FACING_NORTH", "LAUFBAU_FACING_SOUTH"));
}
public void floorEastGrindstone() {
Grindstone grindstone = (Grindstone) Material.GRINDSTONE.createBlockData();
grindstone.setAttachedFace(FaceAttachable.AttachedFace.FLOOR);
grindstone.setFacing(BlockFace.EAST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(2, 4, 4, 12, 12, 8));
cuboidList.add(pixelCuboid(6, 0, 2, 4, 7, 2));
cuboidList.add(pixelCuboid(6, 0, 12, 4, 7, 2));
cuboidList.add(pixelCuboid(5, 7, 2, 6, 6, 2));
cuboidList.add(pixelCuboid(5, 7, 12, 6, 6, 2));
new BlockBoundingBox(grindstone, cuboidList, createItem("LAUFBAU_BLOCK_GRINDSTONE", Material.GRINDSTONE, "LAUFBAU_ATTACHMENT_FLOOR", "LAUFBAU_FACING_EAST", "LAUFBAU_FACING_WEST"));
}
public void ceilingNorthGrindstone() {
Grindstone grindstone = (Grindstone) Material.GRINDSTONE.createBlockData();
grindstone.setAttachedFace(FaceAttachable.AttachedFace.CEILING);
grindstone.setFacing(BlockFace.NORTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(4, 0, 2, 8, 12, 12));
cuboidList.add(pixelCuboid(2, 9, 6, 2, 7, 4));
cuboidList.add(pixelCuboid(12, 9, 6, 2, 7, 4));
cuboidList.add(pixelCuboid(2, 3, 5, 2, 6, 6));
cuboidList.add(pixelCuboid(12, 3, 5, 2, 6, 6));
new BlockBoundingBox(grindstone, cuboidList, createItem("LAUFBAU_BLOCK_GRINDSTONE", Material.GRINDSTONE, "LAUFBAU_ATTACHMENT_CEILING", "LAUFBAU_FACING_NORTH", "LAUFBAU_FACING_SOUTH"));
}
public void ceilingEastGrindstone() {
Grindstone grindstone = (Grindstone) Material.GRINDSTONE.createBlockData();
grindstone.setAttachedFace(FaceAttachable.AttachedFace.CEILING);
grindstone.setFacing(BlockFace.EAST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(2, 0, 4, 12, 12, 8));
cuboidList.add(pixelCuboid(6, 9, 2, 4, 7, 2));
cuboidList.add(pixelCuboid(6, 9, 12, 4, 7, 2));
cuboidList.add(pixelCuboid(5, 3, 2, 6, 6, 2));
cuboidList.add(pixelCuboid(5, 3, 12, 6, 6, 2));
new BlockBoundingBox(grindstone, cuboidList, createItem("LAUFBAU_BLOCK_GRINDSTONE", Material.GRINDSTONE, "LAUFBAU_ATTACHMENT_CEILING", "LAUFBAU_FACING_EAST", "LAUFBAU_FACING_WEST"));
}
public void wallNorthGrindstone() {
Grindstone grindstone = (Grindstone) Material.GRINDSTONE.createBlockData();
grindstone.setAttachedFace(FaceAttachable.AttachedFace.WALL);
grindstone.setFacing(BlockFace.NORTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(4, 2, 0, 8, 12, 12));
cuboidList.add(pixelCuboid(2, 6, 9, 2, 4, 7));
cuboidList.add(pixelCuboid(12, 6, 9, 2, 4, 7));
cuboidList.add(pixelCuboid(2, 5, 3, 2, 6, 6));
cuboidList.add(pixelCuboid(12, 5, 3, 2, 6, 6));
new BlockBoundingBox(grindstone, cuboidList, createItem("LAUFBAU_BLOCK_GRINDSTONE", Material.GRINDSTONE, "LAUFBAU_ATTACHMENT_WALL", "LAUFBAU_FACING_NORTH"));
}
public void wallSouthGrindstone() {
Grindstone grindstone = (Grindstone) Material.GRINDSTONE.createBlockData();
grindstone.setAttachedFace(FaceAttachable.AttachedFace.WALL);
grindstone.setFacing(BlockFace.SOUTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(4, 2, 4, 8, 12, 12));
cuboidList.add(pixelCuboid(2, 6, 0, 2, 4, 7));
cuboidList.add(pixelCuboid(12, 6, 0, 2, 4, 7));
cuboidList.add(pixelCuboid(2, 5, 7, 2, 6, 6));
cuboidList.add(pixelCuboid(12, 5, 7, 2, 6, 6));
new BlockBoundingBox(grindstone, cuboidList, createItem("LAUFBAU_BLOCK_GRINDSTONE", Material.GRINDSTONE, "LAUFBAU_ATTACHMENT_WALL", "LAUFBAU_FACING_SOUTH"));
}
public void wallEastGrindstone() {
Grindstone grindstone = (Grindstone) Material.GRINDSTONE.createBlockData();
grindstone.setAttachedFace(FaceAttachable.AttachedFace.WALL);
grindstone.setFacing(BlockFace.EAST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(4, 2, 4, 12, 12, 8));
cuboidList.add(pixelCuboid(0, 6, 2, 7, 4, 2));
cuboidList.add(pixelCuboid(0, 6, 12, 7, 4, 2));
cuboidList.add(pixelCuboid(7, 5, 2, 6, 6, 2));
cuboidList.add(pixelCuboid(7, 5, 12, 6, 6, 2));
new BlockBoundingBox(grindstone, cuboidList, createItem("LAUFBAU_BLOCK_GRINDSTONE", Material.GRINDSTONE, "LAUFBAU_ATTACHMENT_WALL", "LAUFBAU_FACING_EAST"));
}
public void wallWestGrindstone() {
Grindstone grindstone = (Grindstone) Material.GRINDSTONE.createBlockData();
grindstone.setAttachedFace(FaceAttachable.AttachedFace.WALL);
grindstone.setFacing(BlockFace.WEST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 2, 4, 12, 12, 8));
cuboidList.add(pixelCuboid(9, 6, 2, 7, 4, 2));
cuboidList.add(pixelCuboid(9, 6, 12, 7, 4, 2));
cuboidList.add(pixelCuboid(3, 5, 2, 6, 6, 2));
cuboidList.add(pixelCuboid(3, 5, 12, 6, 6, 2));
new BlockBoundingBox(grindstone, cuboidList, createItem("LAUFBAU_BLOCK_GRINDSTONE", Material.GRINDSTONE, "LAUFBAU_ATTACHMENT_WALL", "LAUFBAU_FACING_WEST"));
}
}

View File

@@ -1,97 +0,0 @@
/*
* 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.slaves.laufbau.boundingboxes;
import de.steamwar.bausystem.features.slaves.laufbau.BlockBoundingBox;
import de.steamwar.bausystem.features.slaves.laufbau.BoundingBoxLoader;
import de.steamwar.bausystem.features.slaves.laufbau.Cuboid;
import de.steamwar.linkage.Linked;
import org.bukkit.Material;
import org.bukkit.block.BlockFace;
import org.bukkit.block.data.type.Hopper;
import java.util.ArrayList;
import java.util.List;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.createItem;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.pixelCuboid;
@Linked
public class HopperBoundingBox implements BoundingBoxLoader {
@Override
public void load() {
downHopper();
northHopper();
southHopper();
eastHopper();
westHopper();
}
public void downHopper() {
Hopper hopper = (Hopper) Material.HOPPER.createBlockData();
hopper.setFacing(BlockFace.DOWN);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 10, 0, 16, 6, 16));
cuboidList.add(pixelCuboid(4, 4, 4, 8, 6, 8));
cuboidList.add(pixelCuboid(6, 0, 6, 4, 4, 4));
new BlockBoundingBox(hopper, cuboidList, createItem("LAUFBAU_BLOCK_HOPPER", Material.HOPPER, "LAUFBAU_CONNECTION_FLOOR"));
}
public void northHopper() {
Hopper hopper = (Hopper) Material.HOPPER.createBlockData();
hopper.setFacing(BlockFace.NORTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 10, 0, 16, 6, 16));
cuboidList.add(pixelCuboid(4, 4, 4, 8, 6, 8));
cuboidList.add(pixelCuboid(6, 4, 0, 4, 4, 4));
new BlockBoundingBox(hopper, cuboidList, createItem("LAUFBAU_BLOCK_HOPPER", Material.HOPPER, "LAUFBAU_CONNECTION_NORTH"));
}
public void southHopper() {
Hopper hopper = (Hopper) Material.HOPPER.createBlockData();
hopper.setFacing(BlockFace.SOUTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 10, 0, 16, 6, 16));
cuboidList.add(pixelCuboid(4, 4, 4, 8, 6, 8));
cuboidList.add(pixelCuboid(6, 4, 12, 4, 4, 4));
new BlockBoundingBox(hopper, cuboidList, createItem("LAUFBAU_BLOCK_HOPPER", Material.HOPPER, "LAUFBAU_CONNECTION_SOUTH"));
}
public void eastHopper() {
Hopper hopper = (Hopper) Material.HOPPER.createBlockData();
hopper.setFacing(BlockFace.EAST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 10, 0, 16, 6, 16));
cuboidList.add(pixelCuboid(4, 4, 4, 8, 6, 8));
cuboidList.add(pixelCuboid(12, 4, 6, 4, 4, 4));
new BlockBoundingBox(hopper, cuboidList, createItem("LAUFBAU_BLOCK_HOPPER", Material.HOPPER, "LAUFBAU_CONNECTION_EAST"));
}
public void westHopper() {
Hopper hopper = (Hopper) Material.HOPPER.createBlockData();
hopper.setFacing(BlockFace.WEST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 10, 0, 16, 6, 16));
cuboidList.add(pixelCuboid(4, 4, 4, 8, 6, 8));
cuboidList.add(pixelCuboid(0, 4, 6, 4, 4, 4));
new BlockBoundingBox(hopper, cuboidList, createItem("LAUFBAU_BLOCK_HOPPER", Material.HOPPER, "LAUFBAU_CONNECTION_WEST"));
}
}

View File

@@ -1,75 +0,0 @@
/*
* 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.slaves.laufbau.boundingboxes;
import de.steamwar.bausystem.features.slaves.laufbau.BlockBoundingBox;
import de.steamwar.bausystem.features.slaves.laufbau.BoundingBoxLoader;
import de.steamwar.bausystem.features.slaves.laufbau.Cuboid;
import de.steamwar.linkage.Linked;
import org.bukkit.Material;
import org.bukkit.block.BlockFace;
import org.bukkit.block.data.type.Fence;
import java.util.ArrayList;
import java.util.List;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.createItem;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.pixelCuboid;
@Linked
public class IronBarBoundingBox implements BoundingBoxLoader {
@Override
public void load() {
for (int nx = 0; nx < 2; nx++) {
for (int nz = 0; nz < 2; nz++) {
for (int px = 0; px < 2; px++) {
for (int pz = 0; pz < 2; pz++) {
Fence fence = (Fence) Material.IRON_BARS.createBlockData();
List<String> lore = new ArrayList<>();
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(7, 0, 7, 2, 16, 2));
if (nz == 1) {
lore.add("LAUFBAU_CONNECTION_NORTH");
fence.setFace(BlockFace.NORTH, true);
cuboidList.add(pixelCuboid(7, 0, 0, 2, 16, 7));
}
if (pz == 1) {
lore.add("LAUFBAU_CONNECTION_SOUTH");
fence.setFace(BlockFace.SOUTH, true);
cuboidList.add(pixelCuboid(7, 0, 9, 2, 16, 7));
}
if (nx == 1) {
lore.add("LAUFBAU_CONNECTION_WEST");
fence.setFace(BlockFace.WEST, true);
cuboidList.add(pixelCuboid(0, 0, 7, 7, 16, 2));
}
if (px == 1) {
lore.add("LAUFBAU_CONNECTION_EAST");
fence.setFace(BlockFace.EAST, true);
cuboidList.add(pixelCuboid(9, 0, 7, 7, 16, 2));
}
new BlockBoundingBox(fence, cuboidList, createItem("LAUFBAU_BLOCK_IRON_BARS", Material.IRON_BARS, lore.toArray(new String[0])));
}
}
}
}
}
}

View File

@@ -1,61 +0,0 @@
/*
* 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.slaves.laufbau.boundingboxes;
import de.steamwar.bausystem.features.slaves.laufbau.BlockBoundingBox;
import de.steamwar.bausystem.features.slaves.laufbau.BoundingBoxLoader;
import de.steamwar.bausystem.features.slaves.laufbau.Cuboid;
import de.steamwar.linkage.Linked;
import org.bukkit.Material;
import org.bukkit.block.data.type.Lantern;
import java.util.ArrayList;
import java.util.List;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.createItem;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.pixelCuboid;
@Linked
public class LanternBoundingBox implements BoundingBoxLoader {
@Override
public void load() {
lantern();
hangingLantern();
}
public void lantern() {
Lantern lantern = (Lantern) Material.LANTERN.createBlockData();
lantern.setHanging(false);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(5, 0, 5, 6, 7, 6));
cuboidList.add(pixelCuboid(6, 7, 6, 4, 2, 4));
new BlockBoundingBox(lantern, cuboidList, createItem("LAUFBAU_BLOCK_LANTERN", Material.LANTERN));
}
public void hangingLantern() {
Lantern lantern = (Lantern) Material.LANTERN.createBlockData();
lantern.setHanging(true);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(5, 1, 5, 6, 7, 6));
cuboidList.add(pixelCuboid(6, 8, 6, 4, 2, 4));
new BlockBoundingBox(lantern, cuboidList, createItem("LAUFBAU_BLOCK_LANTERN", Material.LANTERN, "LAUFBAU_HANGING"));
}
}

View File

@@ -1,46 +0,0 @@
/*
* 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.slaves.laufbau.boundingboxes;
import de.steamwar.bausystem.features.slaves.laufbau.BlockBoundingBox;
import de.steamwar.bausystem.features.slaves.laufbau.BoundingBoxLoader;
import de.steamwar.bausystem.features.slaves.laufbau.Cuboid;
import de.steamwar.linkage.Linked;
import org.bukkit.Material;
import org.bukkit.block.data.BlockData;
import java.util.ArrayList;
import java.util.List;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.createItem;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.pixelCuboid;
@Linked
public class LecternBoundingBox implements BoundingBoxLoader {
@Override
public void load() {
BlockData blockData = Material.LECTERN.createBlockData();
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 0, 0, 16, 2, 16));
cuboidList.add(pixelCuboid(4, 2, 4, 8, 12, 8));
new BlockBoundingBox(blockData, cuboidList, createItem("LAUFBAU_BLOCK_LECTERN", Material.LECTERN));
}
}

View File

@@ -1,343 +0,0 @@
/*
* 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.slaves.laufbau.boundingboxes;
import de.steamwar.bausystem.features.slaves.laufbau.BlockBoundingBox;
import de.steamwar.bausystem.features.slaves.laufbau.BoundingBoxLoader;
import de.steamwar.bausystem.features.slaves.laufbau.Cuboid;
import de.steamwar.linkage.Linked;
import org.bukkit.Material;
import org.bukkit.block.BlockFace;
import org.bukkit.block.data.type.Stairs;
import java.util.ArrayList;
import java.util.List;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.createItem;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.pixelCuboid;
@Linked
public class StairBoundingBox implements BoundingBoxLoader {
@Override
public void load() {
straightBottomNorthStair();
straightBottomSouthStair();
straightBottomEastStair();
straightBottomWestStair();
straightTopNorthStair();
straightTopSouthStair();
straightTopEastStair();
straightTopWestStair();
outerLeftBottomNorthStair();
outerLeftBottomSouthStair();
outerLeftBottomEastStair();
outerLeftBottomWestStair();
outerLeftTopNorthStair();
outerLeftTopSouthStair();
outerLeftTopEastStair();
outerLeftTopWestStair();
innerLeftBottomNorthStair();
innerLeftBottomSouthStair();
innerLeftBottomEastStair();
innerLeftBottomWestStair();
innerLeftTopNorthStair();
innerLeftTopSouthStair();
innerLeftTopEastStair();
innerLeftTopWestStair();
}
public void straightBottomNorthStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.STRAIGHT);
stairs.setHalf(Stairs.Half.BOTTOM);
stairs.setFacing(BlockFace.NORTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 0, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(0, 8, 0, 16, 8, 8));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_STRAIGHT", "LAUFBAU_HALF_BOTTOM", "LAUFBAU_FACING_NORTH"));
}
public void straightBottomSouthStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.STRAIGHT);
stairs.setHalf(Stairs.Half.BOTTOM);
stairs.setFacing(BlockFace.SOUTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 0, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(0, 8, 8, 16, 8, 8));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_STRAIGHT", "LAUFBAU_HALF_BOTTOM", "LAUFBAU_FACING_SOUTH"));
}
public void straightBottomEastStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.STRAIGHT);
stairs.setHalf(Stairs.Half.BOTTOM);
stairs.setFacing(BlockFace.EAST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 0, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(8, 8, 0, 8, 8, 16));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_STRAIGHT", "LAUFBAU_HALF_BOTTOM", "LAUFBAU_FACING_EAST"));
}
public void straightBottomWestStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.STRAIGHT);
stairs.setHalf(Stairs.Half.BOTTOM);
stairs.setFacing(BlockFace.WEST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 0, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(0, 8, 0, 8, 8, 16));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_STRAIGHT", "LAUFBAU_HALF_BOTTOM", "LAUFBAU_FACING_WEST"));
}
public void straightTopNorthStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.STRAIGHT);
stairs.setHalf(Stairs.Half.TOP);
stairs.setFacing(BlockFace.NORTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 8, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(0, 0, 0, 16, 8, 8));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_STRAIGHT", "LAUFBAU_HALF_TOP", "LAUFBAU_FACING_NORTH"));
}
public void straightTopSouthStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.STRAIGHT);
stairs.setHalf(Stairs.Half.TOP);
stairs.setFacing(BlockFace.SOUTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 8, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(0, 0, 8, 16, 8, 8));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_STRAIGHT", "LAUFBAU_HALF_TOP", "LAUFBAU_FACING_SOUTH"));
}
public void straightTopEastStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.STRAIGHT);
stairs.setHalf(Stairs.Half.TOP);
stairs.setFacing(BlockFace.EAST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 8, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(8, 0, 0, 8, 8, 16));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_STRAIGHT", "LAUFBAU_HALF_TOP", "LAUFBAU_FACING_EAST"));
}
public void straightTopWestStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.STRAIGHT);
stairs.setHalf(Stairs.Half.TOP);
stairs.setFacing(BlockFace.WEST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 8, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(0, 0, 0, 8, 8, 16));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_STRAIGHT", "LAUFBAU_HALF_TOP", "LAUFBAU_FACING_WEST"));
}
public void outerLeftBottomNorthStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.OUTER_LEFT);
stairs.setHalf(Stairs.Half.BOTTOM);
stairs.setFacing(BlockFace.NORTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 0, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(0, 8, 0, 8, 8, 8));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_OUTER_LEFT", "LAUFBAU_HALF_BOTTOM", "LAUFBAU_FACING_NORTH"));
}
public void outerLeftBottomSouthStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.OUTER_LEFT);
stairs.setHalf(Stairs.Half.BOTTOM);
stairs.setFacing(BlockFace.SOUTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 0, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(8, 8, 8, 8, 8, 8));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_OUTER_LEFT", "LAUFBAU_HALF_BOTTOM", "LAUFBAU_FACING_SOUTH"));
}
public void outerLeftBottomEastStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.OUTER_LEFT);
stairs.setHalf(Stairs.Half.BOTTOM);
stairs.setFacing(BlockFace.EAST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 0, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(8, 8, 0, 8, 8, 8));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_OUTER_LEFT", "LAUFBAU_HALF_BOTTOM", "LAUFBAU_FACING_EAST"));
}
public void outerLeftBottomWestStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.OUTER_LEFT);
stairs.setHalf(Stairs.Half.BOTTOM);
stairs.setFacing(BlockFace.WEST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 0, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(0, 8, 8, 8, 8, 8));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_OUTER_LEFT", "LAUFBAU_HALF_BOTTOM", "LAUFBAU_FACING_WEST"));
}
public void outerLeftTopNorthStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.OUTER_LEFT);
stairs.setHalf(Stairs.Half.TOP);
stairs.setFacing(BlockFace.NORTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 8, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(0, 0, 0, 8, 8, 8));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_OUTER_LEFT", "LAUFBAU_HALF_TOP", "LAUFBAU_FACING_NORTH"));
}
public void outerLeftTopSouthStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.OUTER_LEFT);
stairs.setHalf(Stairs.Half.TOP);
stairs.setFacing(BlockFace.SOUTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 8, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(8, 0, 8, 8, 8, 8));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_OUTER_LEFT", "LAUFBAU_HALF_TOP", "LAUFBAU_FACING_SOUTH"));
}
public void outerLeftTopEastStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.OUTER_LEFT);
stairs.setHalf(Stairs.Half.TOP);
stairs.setFacing(BlockFace.EAST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 8, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(8, 0, 0, 8, 8, 8));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_OUTER_LEFT", "LAUFBAU_HALF_TOP", "LAUFBAU_FACING_EAST"));
}
public void outerLeftTopWestStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.OUTER_LEFT);
stairs.setHalf(Stairs.Half.TOP);
stairs.setFacing(BlockFace.WEST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 8, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(0, 0, 8, 8, 8, 8));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_OUTER_LEFT", "LAUFBAU_HALF_TOP", "LAUFBAU_FACING_WEST"));
}
public void innerLeftBottomNorthStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.INNER_LEFT);
stairs.setHalf(Stairs.Half.BOTTOM);
stairs.setFacing(BlockFace.NORTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 0, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(0, 8, 0, 16, 8, 8));
cuboidList.add(pixelCuboid(0, 8, 8, 8, 8, 8));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_INNER_LEFT", "LAUFBAU_HALF_BOTTOM", "LAUFBAU_FACING_NORTH"));
}
public void innerLeftBottomSouthStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.INNER_LEFT);
stairs.setHalf(Stairs.Half.BOTTOM);
stairs.setFacing(BlockFace.SOUTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 0, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(0, 8, 8, 16, 8, 8));
cuboidList.add(pixelCuboid(8, 8, 0, 8, 8, 8));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_INNER_LEFT", "LAUFBAU_HALF_BOTTOM", "LAUFBAU_FACING_SOUTH"));
}
public void innerLeftBottomEastStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.INNER_LEFT);
stairs.setHalf(Stairs.Half.BOTTOM);
stairs.setFacing(BlockFace.EAST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 0, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(0, 8, 0, 16, 8, 8));
cuboidList.add(pixelCuboid(8, 8, 8, 8, 8, 8));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_INNER_LEFT", "LAUFBAU_HALF_BOTTOM", "LAUFBAU_FACING_EAST"));
}
public void innerLeftBottomWestStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.INNER_LEFT);
stairs.setHalf(Stairs.Half.BOTTOM);
stairs.setFacing(BlockFace.WEST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 0, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(0, 8, 8, 16, 8, 8));
cuboidList.add(pixelCuboid(0, 8, 0, 8, 8, 8));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_INNER_LEFT", "LAUFBAU_HALF_BOTTOM", "LAUFBAU_FACING_WEST"));
}
public void innerLeftTopNorthStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.INNER_LEFT);
stairs.setHalf(Stairs.Half.TOP);
stairs.setFacing(BlockFace.NORTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 8, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(0, 0, 0, 16, 8, 8));
cuboidList.add(pixelCuboid(0, 0, 8, 8, 8, 8));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_INNER_LEFT", "LAUFBAU_HALF_TOP", "LAUFBAU_FACING_NORTH"));
}
public void innerLeftTopSouthStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.INNER_LEFT);
stairs.setHalf(Stairs.Half.TOP);
stairs.setFacing(BlockFace.SOUTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 8, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(0, 0, 8, 16, 8, 8));
cuboidList.add(pixelCuboid(8, 0, 0, 8, 8, 8));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_INNER_LEFT", "LAUFBAU_HALF_TOP", "LAUFBAU_FACING_SOUTH"));
}
public void innerLeftTopEastStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.INNER_LEFT);
stairs.setHalf(Stairs.Half.TOP);
stairs.setFacing(BlockFace.EAST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 8, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(0, 0, 0, 16, 8, 8));
cuboidList.add(pixelCuboid(8, 0, 8, 8, 8, 8));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_INNER_LEFT", "LAUFBAU_HALF_TOP", "LAUFBAU_FACING_EAST"));
}
public void innerLeftTopWestStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.INNER_LEFT);
stairs.setHalf(Stairs.Half.TOP);
stairs.setFacing(BlockFace.WEST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 8, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(0, 0, 8, 16, 8, 8));
cuboidList.add(pixelCuboid(0, 0, 0, 8, 8, 8));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_INNER_LEFT", "LAUFBAU_HALF_TOP", "LAUFBAU_FACING_WEST"));
}
}

View File

@@ -1,121 +0,0 @@
/*
* 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.slaves.laufbau.boundingboxes;
import de.steamwar.bausystem.features.slaves.laufbau.BlockBoundingBox;
import de.steamwar.bausystem.features.slaves.laufbau.BoundingBoxLoader;
import de.steamwar.bausystem.features.slaves.laufbau.Cuboid;
import de.steamwar.core.Core;
import de.steamwar.linkage.Linked;
import org.bukkit.Material;
import org.bukkit.block.BlockFace;
import org.bukkit.block.data.type.Fence;
import org.bukkit.block.data.type.Wall;
import java.util.ArrayList;
import java.util.List;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.createItem;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.pixelCuboid;
@Linked
public class WallBoundingBox implements BoundingBoxLoader {
@Override
public void load() {
if (Core.getVersion() > 15) {
v18();
} else {
v15();
}
}
private void v18() {
for (int nx = 0; nx < 2; nx++) {
for (int nz = 0; nz < 2; nz++) {
for (int px = 0; px < 2; px++) {
for (int pz = 0; pz < 2; pz++) {
Wall fence = (Wall) Material.END_STONE_BRICK_WALL.createBlockData();
List<String> lore = new ArrayList<>();
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(4, 0, 4, 8, 24, 8));
if (nz == 1) {
lore.add("LAUFBAU_CONNECTION_NORTH");
fence.setHeight(BlockFace.NORTH, Wall.Height.LOW);
cuboidList.add(pixelCuboid(5, 0, 0, 6, 24, 4));
}
if (pz == 1) {
lore.add("LAUFBAU_CONNECTION_SOUTH");
fence.setHeight(BlockFace.SOUTH, Wall.Height.LOW);
cuboidList.add(pixelCuboid(5, 0, 12, 6, 24, 4));
}
if (nx == 1) {
lore.add("LAUFBAU_CONNECTION_WEST");
fence.setHeight(BlockFace.WEST, Wall.Height.LOW);
cuboidList.add(pixelCuboid(0, 0, 5, 4, 24, 6));
}
if (px == 1) {
lore.add("LAUFBAU_CONNECTION_EAST");
fence.setHeight(BlockFace.EAST, Wall.Height.LOW);
cuboidList.add(pixelCuboid(12, 0, 5, 4, 24, 6));
}
new BlockBoundingBox(fence, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_WALL", Material.END_STONE_BRICK_WALL, lore.toArray(new String[0])));
}
}
}
}
}
private void v15() {
for (int nx = 0; nx < 2; nx++) {
for (int nz = 0; nz < 2; nz++) {
for (int px = 0; px < 2; px++) {
for (int pz = 0; pz < 2; pz++) {
Fence fence = (Fence) Material.END_STONE_BRICK_WALL.createBlockData();
List<String> lore = new ArrayList<>();
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(4, 0, 4, 8, 24, 8));
if (nz == 1) {
lore.add("LAUFBAU_CONNECTION_NORTH");
fence.setFace(BlockFace.NORTH, true);
cuboidList.add(pixelCuboid(5, 0, 0, 6, 24, 4));
}
if (pz == 1) {
lore.add("LAUFBAU_CONNECTION_SOUTH");
fence.setFace(BlockFace.SOUTH, true);
cuboidList.add(pixelCuboid(5, 0, 12, 6, 24, 4));
}
if (nx == 1) {
lore.add("LAUFBAU_CONNECTION_WEST");
fence.setFace(BlockFace.WEST, true);
cuboidList.add(pixelCuboid(0, 0, 5, 4, 24, 6));
}
if (px == 1) {
lore.add("LAUFBAU_CONNECTION_EAST");
fence.setFace(BlockFace.EAST, true);
cuboidList.add(pixelCuboid(12, 0, 5, 4, 24, 6));
}
new BlockBoundingBox(fence, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_WALL", Material.END_STONE_BRICK_WALL, lore.toArray(new String[0])));
}
}
}
}
}
}

View File

@@ -107,7 +107,7 @@ public class TechHiderCommand extends SWCommand implements Listener, ScoreboardE
@Override @Override
public Player map(CommandSender commandSender, String[] previousArguments, String s) { public Player map(CommandSender commandSender, String[] previousArguments, String s) {
Player player = Bukkit.getPlayer(s); Player player = Bukkit.getPlayer(s);
if (player != null && Permission.REAL_SPECTATOR.hasPermission(player)) { if (player != null && Permission.SPECTATOR.hasPermission(player)) {
return player; return player;
} }
return null; return null;
@@ -116,7 +116,7 @@ public class TechHiderCommand extends SWCommand implements Listener, ScoreboardE
@Override @Override
public Collection<String> tabCompletes(CommandSender sender, PreviousArguments previousArguments, String s) { public Collection<String> tabCompletes(CommandSender sender, PreviousArguments previousArguments, String s) {
return Bukkit.getOnlinePlayers().stream() return Bukkit.getOnlinePlayers().stream()
.filter(Permission.REAL_SPECTATOR::hasPermission) .filter(Permission.SPECTATOR::hasPermission)
.map(Player::getName) .map(Player::getName)
.collect(Collectors.toList()); .collect(Collectors.toList());
} }

View File

@@ -17,7 +17,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package de.steamwar.bausystem.features.tntlistener; package de.steamwar.bausystem.features.tls;
import de.steamwar.command.SWCommand; import de.steamwar.command.SWCommand;
import de.steamwar.linkage.Linked; import de.steamwar.linkage.Linked;
@@ -43,4 +43,13 @@ public class TLSCommand extends SWCommand {
public void stop(@Validator Player player) { public void stop(@Validator Player player) {
listener.stopListening(player); listener.stopListening(player);
} }
@Register(description = "TLS_TOGGLE_HELP")
public void toggle(@Validator Player player) {
if (listener.isActiveFor(player)) {
listener.stopListening(player);
} else {
listener.startListening(player);
}
}
} }

View File

@@ -17,7 +17,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package de.steamwar.bausystem.features.tntlistener; package de.steamwar.bausystem.features.tls;
import de.steamwar.bausystem.BauSystem; import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.features.tpslimit.TPSUtils; import de.steamwar.bausystem.features.tpslimit.TPSUtils;

View File

@@ -17,7 +17,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package de.steamwar.bausystem.features.tntlistener; package de.steamwar.bausystem.features.tls;
import de.steamwar.bausystem.BauSystem; import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.Permission; import de.steamwar.bausystem.Permission;

View File

@@ -20,6 +20,7 @@ package de.steamwar.bausystem.features.util;
import de.steamwar.bausystem.BauSystem; import de.steamwar.bausystem.BauSystem;
import de.steamwar.command.SWCommand; import de.steamwar.command.SWCommand;
import de.steamwar.core.SWPlayer;
import de.steamwar.linkage.Linked; import de.steamwar.linkage.Linked;
import org.bukkit.GameMode; import org.bukkit.GameMode;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@@ -39,10 +40,11 @@ public class GamemodeCommand extends SWCommand {
@Register @Register
public void genericCommand(final Player p) { public void genericCommand(final Player p) {
if (NoClipCommand.getNOCLIPS().contains(p)) { SWPlayer swPlayer = SWPlayer.of(p);
p.performCommand("noclip"); if (swPlayer.hasComponent(NoClipCommand.NoClipData.class)) {
return; swPlayer.removeComponent(NoClipCommand.NoClipData.class);
} return;
}
if (p.getGameMode() == GameMode.CREATIVE) { if (p.getGameMode() == GameMode.CREATIVE) {
p.setGameMode(GameMode.SPECTATOR); p.setGameMode(GameMode.SPECTATOR);
} else { } else {
@@ -52,9 +54,7 @@ public class GamemodeCommand extends SWCommand {
@Register @Register
public void gamemodeCommand(final Player p, final GameMode gameMode) { public void gamemodeCommand(final Player p, final GameMode gameMode) {
if (NoClipCommand.getNOCLIPS().contains(p)) { SWPlayer.of(p).removeComponent(NoClipCommand.NoClipData.class);
p.performCommand("noclip");
}
p.setGameMode(gameMode); p.setGameMode(gameMode);
} }
} }

View File

@@ -26,6 +26,7 @@ import de.steamwar.bausystem.shared.EnumDisplay;
import de.steamwar.command.PreviousArguments; import de.steamwar.command.PreviousArguments;
import de.steamwar.command.SWCommand; import de.steamwar.command.SWCommand;
import de.steamwar.command.TypeMapper; import de.steamwar.command.TypeMapper;
import de.steamwar.core.SWPlayer;
import de.steamwar.data.CMDs; import de.steamwar.data.CMDs;
import de.steamwar.inventory.SWAnvilInv; import de.steamwar.inventory.SWAnvilInv;
import de.steamwar.inventory.SWInventory; import de.steamwar.inventory.SWInventory;
@@ -56,11 +57,9 @@ public class MaterialCommand extends SWCommand implements Listener {
WorldEditListener.addCommandExclusion("material"); WorldEditListener.addCommandExclusion("material");
} }
private Map<Player, Search> searchMap = new HashMap<>();
@Getter @Getter
@Setter @Setter
static class Search { public class SearchParameter implements SWPlayer.Component {
SearchType transparent = SearchType.IGNORE; SearchType transparent = SearchType.IGNORE;
SearchType solid = SearchType.IGNORE; SearchType solid = SearchType.IGNORE;
SearchType gravity = SearchType.IGNORE; SearchType gravity = SearchType.IGNORE;
@@ -104,10 +103,10 @@ public class MaterialCommand extends SWCommand implements Listener {
@Register @Register
public void materialGUI(Player p) { public void materialGUI(Player p) {
materialGUI(p, searchMap.get(p)); materialGUI(p, SWPlayer.of(p).getComponentOrDefault(SearchParameter.class, SearchParameter::new));
} }
private static final Map<String, BiConsumer<Search, SearchType>> elements = new HashMap<>(); private static final Map<String, BiConsumer<SearchParameter, SearchType>> elements = new HashMap<>();
static { static {
elements.put("-transparent", (search, searchType) -> search.transparent = searchType); elements.put("-transparent", (search, searchType) -> search.transparent = searchType);
elements.put("-solid", (search, searchType) -> search.solid = searchType); elements.put("-solid", (search, searchType) -> search.solid = searchType);
@@ -122,15 +121,15 @@ public class MaterialCommand extends SWCommand implements Listener {
@Register @Register
public void search(Player p, @Mapper("search") String... searches) { public void search(Player p, @Mapper("search") String... searches) {
Search search = new Search(); SearchParameter searchParameter = SWPlayer.of(p).getComponentOrDefault(SearchParameter.class, SearchParameter::new);
for (String s : searches) { for (String s : searches) {
boolean has = false; boolean has = false;
for (Map.Entry<String, BiConsumer<Search, SearchType>> element: elements.entrySet()) { for (Map.Entry<String, BiConsumer<SearchParameter, SearchType>> element: elements.entrySet()) {
if (s.startsWith(element.getKey() + ":")) { if (s.startsWith(element.getKey() + ":")) {
element.getValue().accept(search, SearchType.valueOf(s.substring(element.getKey().length() + 1).toUpperCase())); element.getValue().accept(searchParameter, SearchType.valueOf(s.substring(element.getKey().length() + 1).toUpperCase()));
has = true; has = true;
} else if (s.startsWith(element.getKey().substring(0, 2) + ":")) { } else if (s.startsWith(element.getKey().substring(0, 2) + ":")) {
element.getValue().accept(search, SearchType.valueOf(s.substring(element.getKey().substring(0, 2).length() + 1).toUpperCase())); element.getValue().accept(searchParameter, SearchType.valueOf(s.substring(element.getKey().substring(0, 2).length() + 1).toUpperCase()));
has = true; has = true;
} }
if (has) break; if (has) break;
@@ -141,15 +140,15 @@ public class MaterialCommand extends SWCommand implements Listener {
case "-blastresistance:": case "-blastresistance:":
s = s.substring(s.indexOf(':') + 1).replace('_', ' '); s = s.substring(s.indexOf(':') + 1).replace('_', ' ');
if (s.isEmpty() || s.matches("((([><]=?)|!|=)\\d+(\\.|,\\d+)?)( ((([><]=?)|!|=)\\d+(\\.|,\\d+)?))*")) { if (s.isEmpty() || s.matches("((([><]=?)|!|=)\\d+(\\.|,\\d+)?)( ((([><]=?)|!|=)\\d+(\\.|,\\d+)?))*")) {
search.blastResistance = s; searchParameter.blastResistance = s;
} }
break; break;
default: default:
search.name = s; searchParameter.name = s;
break; break;
} }
} }
materialGUI(p, search); materialGUI(p, searchParameter);
} }
@Mapper(value = "search", local = true) @Mapper(value = "search", local = true)
@@ -182,7 +181,7 @@ public class MaterialCommand extends SWCommand implements Listener {
}; };
} }
public void materialGUI(Player p, Search search) { public void materialGUI(Player p, SearchParameter search) {
List<SWListInv.SWListEntry<Material>> swListEntries = new ArrayList<>(); List<SWListInv.SWListEntry<Material>> swListEntries = new ArrayList<>();
MaterialLazyInit.materialData.forEach(data -> { MaterialLazyInit.materialData.forEach(data -> {
if (data.is(search)) { if (data.is(search)) {
@@ -202,59 +201,59 @@ public class MaterialCommand extends SWCommand implements Listener {
private void searchGUI(Player p) { private void searchGUI(Player p) {
SWInventory swInventory = new SWInventory(p, 54, BauSystem.MESSAGE.parse("MATERIAL_SEARCH", p)); SWInventory swInventory = new SWInventory(p, 54, BauSystem.MESSAGE.parse("MATERIAL_SEARCH", p));
Search search = searchMap.get(p); SearchParameter searchParameter = SWPlayer.of(p).getComponentOrDefault(SearchParameter.class, SearchParameter::new);
swInventory.setItem(0, new SWItem(Material.ARROW, BauSystem.MESSAGE.parse("MATERIAL_BACK", p), clickType -> { swInventory.setItem(0, new SWItem(Material.ARROW, BauSystem.MESSAGE.parse("MATERIAL_BACK", p), clickType -> {
materialGUI(p); materialGUI(p);
}).setCustomModelData(CMDs.BACK)); }).setCustomModelData(CMDs.BACK));
swInventory.setItem(10, new SWItem(Material.NAME_TAG, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_NAME", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, search.name), clickType -> { swInventory.setItem(10, new SWItem(Material.NAME_TAG, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_NAME", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, searchParameter.name), clickType -> {
SWAnvilInv swAnvilInv = new SWAnvilInv(p, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_NAME", p), search.name); SWAnvilInv swAnvilInv = new SWAnvilInv(p, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_NAME", p), searchParameter.name);
swAnvilInv.setCallback(s -> { swAnvilInv.setCallback(s -> {
search.name = s; searchParameter.name = s;
searchGUI(p); searchGUI(p);
}); });
swAnvilInv.open(); swAnvilInv.open();
})); }));
swInventory.setItem(19, new SWItem(Material.GLASS, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_TRANSPARENT", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, BauSystem.MESSAGE.parse(search.transparent.getChatValue(), p)), clickType -> { swInventory.setItem(19, new SWItem(Material.GLASS, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_TRANSPARENT", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, BauSystem.MESSAGE.parse(searchParameter.transparent.getChatValue(), p)), clickType -> {
search.transparent = search.transparent.next(); searchParameter.transparent = searchParameter.transparent.next();
searchGUI(p); searchGUI(p);
})); }));
swInventory.setItem(20, new SWItem(Material.BRICK, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_SOLID", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, BauSystem.MESSAGE.parse(search.solid.getChatValue(), p)), clickType -> { swInventory.setItem(20, new SWItem(Material.BRICK, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_SOLID", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, BauSystem.MESSAGE.parse(searchParameter.solid.getChatValue(), p)), clickType -> {
search.solid = search.solid.next(); searchParameter.solid = searchParameter.solid.next();
searchGUI(p); searchGUI(p);
})); }));
swInventory.setItem(21, new SWItem(Material.BLACK_CONCRETE_POWDER, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_GRAVITY", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, BauSystem.MESSAGE.parse(search.gravity.getChatValue(), p)), clickType -> { swInventory.setItem(21, new SWItem(Material.BLACK_CONCRETE_POWDER, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_GRAVITY", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, BauSystem.MESSAGE.parse(searchParameter.gravity.getChatValue(), p)), clickType -> {
search.gravity = search.gravity.next(); searchParameter.gravity = searchParameter.gravity.next();
searchGUI(p); searchGUI(p);
})); }));
swInventory.setItem(22, new SWItem(Material.BIRCH_LOG, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_OCCLUDING", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, BauSystem.MESSAGE.parse(search.occluding.getChatValue(), p)), clickType -> { swInventory.setItem(22, new SWItem(Material.BIRCH_LOG, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_OCCLUDING", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, BauSystem.MESSAGE.parse(searchParameter.occluding.getChatValue(), p)), clickType -> {
search.occluding = search.occluding.next(); searchParameter.occluding = searchParameter.occluding.next();
searchGUI(p); searchGUI(p);
})); }));
swInventory.setItem(23, new SWItem(Material.OAK_BUTTON, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_INTERACTEABLE", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, BauSystem.MESSAGE.parse(search.interacteable.getChatValue(), p)), clickType -> { swInventory.setItem(23, new SWItem(Material.OAK_BUTTON, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_INTERACTEABLE", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, BauSystem.MESSAGE.parse(searchParameter.interacteable.getChatValue(), p)), clickType -> {
search.interacteable = search.interacteable.next(); searchParameter.interacteable = searchParameter.interacteable.next();
searchGUI(p); searchGUI(p);
})); }));
swInventory.setItem(24, new SWItem(Material.FLINT_AND_STEEL, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_FLAMMABLE", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, BauSystem.MESSAGE.parse(search.flammable.getChatValue(), p)), clickType -> { swInventory.setItem(24, new SWItem(Material.FLINT_AND_STEEL, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_FLAMMABLE", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, BauSystem.MESSAGE.parse(searchParameter.flammable.getChatValue(), p)), clickType -> {
search.flammable = search.flammable.next(); searchParameter.flammable = searchParameter.flammable.next();
searchGUI(p); searchGUI(p);
})); }));
swInventory.setItem(25, new SWItem(Material.LAVA_BUCKET, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_BURNABLE", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, BauSystem.MESSAGE.parse(search.burnable.getChatValue(), p)), clickType -> { swInventory.setItem(25, new SWItem(Material.LAVA_BUCKET, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_BURNABLE", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, BauSystem.MESSAGE.parse(searchParameter.burnable.getChatValue(), p)), clickType -> {
search.burnable = search.burnable.next(); searchParameter.burnable = searchParameter.burnable.next();
searchGUI(p); searchGUI(p);
})); }));
swInventory.setItem(28, new SWItem(Material.WATER_BUCKET, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_WATERLOGGABLE", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, BauSystem.MESSAGE.parse(search.waterloggable.getChatValue(), p)), clickType -> { swInventory.setItem(28, new SWItem(Material.WATER_BUCKET, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_WATERLOGGABLE", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, BauSystem.MESSAGE.parse(searchParameter.waterloggable.getChatValue(), p)), clickType -> {
search.waterloggable = search.waterloggable.next(); searchParameter.waterloggable = searchParameter.waterloggable.next();
searchGUI(p); searchGUI(p);
})); }));
swInventory.setItem(29, new SWItem(Material.PISTON, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_UNMOVEABLE", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, BauSystem.MESSAGE.parse(search.unmoveable.getChatValue(), p)), clickType -> { swInventory.setItem(29, new SWItem(Material.PISTON, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_UNMOVEABLE", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, BauSystem.MESSAGE.parse(searchParameter.unmoveable.getChatValue(), p)), clickType -> {
search.unmoveable = search.unmoveable.next(); searchParameter.unmoveable = searchParameter.unmoveable.next();
searchGUI(p); searchGUI(p);
})); }));
swInventory.setItem(34, new SWItem(Material.NETHER_BRICK, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_BLASTRESISTANCE", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, search.blastResistance), clickType -> { swInventory.setItem(34, new SWItem(Material.NETHER_BRICK, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_BLASTRESISTANCE", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, searchParameter.blastResistance), clickType -> {
SWAnvilInv swAnvilInv = new SWAnvilInv(p, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_BLASTRESISTANCE", p), search.blastResistance); SWAnvilInv swAnvilInv = new SWAnvilInv(p, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_BLASTRESISTANCE", p), searchParameter.blastResistance);
swAnvilInv.setCallback(s -> { swAnvilInv.setCallback(s -> {
if (s.isEmpty() || s.matches("((([><]=?)|!|=)\\d+(\\.|,\\d+)?)( ((([><]=?)|!|=)\\d+(\\.|,\\d+)?))*")) { if (s.isEmpty() || s.matches("((([><]=?)|!|=)\\d+(\\.|,\\d+)?)( ((([><]=?)|!|=)\\d+(\\.|,\\d+)?))*")) {
search.blastResistance = s; searchParameter.blastResistance = s;
} }
searchGUI(p); searchGUI(p);
}); });
@@ -262,14 +261,4 @@ public class MaterialCommand extends SWCommand implements Listener {
})); }));
swInventory.open(); swInventory.open();
} }
@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
searchMap.put(event.getPlayer(), new Search());
}
@EventHandler
public void onPlayerQuit(PlayerQuitEvent event) {
searchMap.remove(event.getPlayer());
}
} }

View File

@@ -133,7 +133,7 @@ public class MaterialLazyInit {
}), originalMaterial); }), originalMaterial);
} }
public boolean is(MaterialCommand.Search search) { public boolean is(MaterialCommand.SearchParameter search) {
boolean result = true; boolean result = true;
result &= search.transparent.test(transparent); result &= search.transparent.test(transparent);
result &= search.solid.test(solid); result &= search.solid.test(solid);

View File

@@ -19,17 +19,17 @@
package de.steamwar.bausystem.features.util; package de.steamwar.bausystem.features.util;
import de.steamwar.Reflection;
import com.comphenix.tinyprotocol.TinyProtocol; import com.comphenix.tinyprotocol.TinyProtocol;
import com.mojang.authlib.GameProfile; import com.mojang.authlib.GameProfile;
import de.steamwar.Reflection;
import de.steamwar.bausystem.BauSystem; import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.features.tpslimit.TPSUtils; import de.steamwar.bausystem.features.tpslimit.TPSUtils;
import de.steamwar.bausystem.utils.BauMemberUpdateEvent; import de.steamwar.bausystem.utils.BauMemberUpdateEvent;
import de.steamwar.bausystem.utils.NMSWrapper; import de.steamwar.bausystem.utils.NMSWrapper;
import de.steamwar.command.SWCommand; import de.steamwar.command.SWCommand;
import de.steamwar.core.ProtocolWrapper; import de.steamwar.core.ProtocolWrapper;
import de.steamwar.core.SWPlayer;
import de.steamwar.linkage.Linked; import de.steamwar.linkage.Linked;
import lombok.Getter;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.GameMode; import org.bukkit.GameMode;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@@ -40,10 +40,6 @@ import org.bukkit.event.player.PlayerGameModeChangeEvent;
import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.event.player.PlayerToggleFlightEvent; import org.bukkit.event.player.PlayerToggleFlightEvent;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction; import java.util.function.BiFunction;
@Linked @Linked
@@ -59,29 +55,34 @@ public class NoClipCommand extends SWCommand implements Listener {
private static final Class<?> windowClick = Reflection.getClass("net.minecraft.network.protocol.game.ServerboundContainerClickPacket"); private static final Class<?> windowClick = Reflection.getClass("net.minecraft.network.protocol.game.ServerboundContainerClickPacket");
private static final Class<?> setSlotStack = Reflection.getClass("net.minecraft.network.protocol.game.ServerboundSetCreativeModeSlotPacket"); private static final Class<?> setSlotStack = Reflection.getClass("net.minecraft.network.protocol.game.ServerboundSetCreativeModeSlotPacket");
@Getter public static class NoClipData implements SWPlayer.Component {
private static final List<Player> NOCLIPS = new ArrayList<>(); private long lastTick = -1;
private static final Map<Player, Long> LAST_TICKS = new HashMap<>();
@Override
public void onUnmount(SWPlayer player) {
player.setGameMode(GameMode.CREATIVE);
}
}
public NoClipCommand() { public NoClipCommand() {
super("noclip", "nc"); super("noclip", "nc");
BiFunction<Player, Object, Object> first = (player, o) -> { BiFunction<Player, Object, Object> first = (player, o) -> {
if (NOCLIPS.contains(player)) { NoClipData noClipData = SWPlayer.of(player).getComponent(NoClipData.class).orElse(null);
if (LAST_TICKS.getOrDefault(player, -1L).equals(TPSUtils.currentTick.get())) return o; if (noClipData == null) return o;
NMSWrapper.impl.setInternalGameMode(player, GameMode.SPECTATOR); if (noClipData.lastTick == TPSUtils.currentTick.get()) return o;
LAST_TICKS.put(player, TPSUtils.currentTick.get()); NMSWrapper.impl.setInternalGameMode(player, GameMode.SPECTATOR);
} noClipData.lastTick = TPSUtils.currentTick.get();
return o; return o;
}; };
TinyProtocol.instance.addFilter(position, first); TinyProtocol.instance.addFilter(position, first);
TinyProtocol.instance.addFilter(positionLook, first); TinyProtocol.instance.addFilter(positionLook, first);
BiFunction<Player, Object, Object> second = (player, o) -> { BiFunction<Player, Object, Object> second = (player, o) -> {
if (NOCLIPS.contains(player)) { NoClipData noClipData = SWPlayer.of(player).getComponent(NoClipData.class).orElse(null);
NMSWrapper.impl.setInternalGameMode(player, GameMode.CREATIVE); if (noClipData == null) return o;
LAST_TICKS.put(player, TPSUtils.currentTick.get()); NMSWrapper.impl.setInternalGameMode(player, GameMode.CREATIVE);
} noClipData.lastTick = TPSUtils.currentTick.get();
return o; return o;
}; };
TinyProtocol.instance.addFilter(useItem, second); TinyProtocol.instance.addFilter(useItem, second);
@@ -89,7 +90,7 @@ public class NoClipCommand extends SWCommand implements Listener {
TinyProtocol.instance.addFilter(windowClick, second); TinyProtocol.instance.addFilter(windowClick, second);
BiFunction<Player, Object, Object> third = (player, o) -> { BiFunction<Player, Object, Object> third = (player, o) -> {
if (NOCLIPS.contains(player)) { if (SWPlayer.of(player).hasComponent(NoClipData.class)) {
NMSWrapper.impl.setSlotToItemStack(player, o); NMSWrapper.impl.setSlotToItemStack(player, o);
} }
return o; return o;
@@ -99,9 +100,9 @@ public class NoClipCommand extends SWCommand implements Listener {
@Register(help = true) @Register(help = true)
public void genericCommand(@Validator Player player) { public void genericCommand(@Validator Player player) {
if (NOCLIPS.contains(player)) { SWPlayer swPlayer = SWPlayer.of(player);
NOCLIPS.remove(player); if (swPlayer.hasComponent(NoClipData.class)) {
player.setGameMode(GameMode.CREATIVE); swPlayer.removeComponent(NoClipData.class);
} else { } else {
player.setGameMode(GameMode.SPECTATOR); player.setGameMode(GameMode.SPECTATOR);
NMSWrapper.impl.setPlayerBuildAbilities(player); NMSWrapper.impl.setPlayerBuildAbilities(player);
@@ -110,7 +111,7 @@ public class NoClipCommand extends SWCommand implements Listener {
NMSWrapper.impl.setGameStateChangeReason(gameStateChangeObject); NMSWrapper.impl.setGameStateChangeReason(gameStateChangeObject);
floatFieldAccessor.set(gameStateChangeObject, 1F); floatFieldAccessor.set(gameStateChangeObject, 1F);
NOCLIPS.add(player); swPlayer.setComponent(new NoClipData());
BauSystem.MESSAGE.send("OTHER_NOCLIP_SLOT_INFO", player); BauSystem.MESSAGE.send("OTHER_NOCLIP_SLOT_INFO", player);
TinyProtocol.instance.sendPacket(player, gameStateChangeObject); TinyProtocol.instance.sendPacket(player, gameStateChangeObject);
pseudoGameMode(player, GameMode.SPECTATOR); pseudoGameMode(player, GameMode.SPECTATOR);
@@ -120,30 +121,27 @@ public class NoClipCommand extends SWCommand implements Listener {
@EventHandler @EventHandler
public void onBauMemberUpdate(BauMemberUpdateEvent event) { public void onBauMemberUpdate(BauMemberUpdateEvent event) {
event.getNewSpectator().forEach(player -> { event.getNewSpectator().forEach(player -> {
if (NOCLIPS.contains(player)) { SWPlayer.of(player).removeComponent(NoClipData.class);
NOCLIPS.remove(player);
player.setGameMode(GameMode.CREATIVE);
}
}); });
} }
@EventHandler(ignoreCancelled = true) @EventHandler(ignoreCancelled = true)
public void onPlayerGameModeChange(PlayerGameModeChangeEvent event) { public void onPlayerGameModeChange(PlayerGameModeChangeEvent event) {
if (NOCLIPS.contains(event.getPlayer())) { if (SWPlayer.of(event.getPlayer()).hasComponent(NoClipData.class)) {
event.setCancelled(true); event.setCancelled(true);
} }
} }
@EventHandler(ignoreCancelled = true) @EventHandler(ignoreCancelled = true)
public void onBlock(BlockCanBuildEvent event) { public void onBlock(BlockCanBuildEvent event) {
if (NOCLIPS.contains(event.getPlayer())) { if (SWPlayer.of(event.getPlayer()).hasComponent(NoClipData.class)) {
event.setBuildable(true); event.setBuildable(true);
} }
} }
@EventHandler(ignoreCancelled = true) @EventHandler(ignoreCancelled = true)
public void onPlayerToggleFlight(PlayerToggleFlightEvent event) { public void onPlayerToggleFlight(PlayerToggleFlightEvent event) {
if (NOCLIPS.contains(event.getPlayer())) { if (SWPlayer.of(event.getPlayer()).hasComponent(NoClipData.class)) {
event.setCancelled(true); event.setCancelled(true);
event.getPlayer().setFlying(true); event.getPlayer().setFlying(true);
} }
@@ -154,7 +152,7 @@ public class NoClipCommand extends SWCommand implements Listener {
if (event.getCause() != PlayerTeleportEvent.TeleportCause.SPECTATE) { if (event.getCause() != PlayerTeleportEvent.TeleportCause.SPECTATE) {
return; return;
} }
if (NOCLIPS.contains(event.getPlayer())) { if (SWPlayer.of(event.getPlayer()).hasComponent(NoClipData.class)) {
event.setCancelled(true); event.setCancelled(true);
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> { Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> {
event.getPlayer().setSpectatorTarget(null); event.getPlayer().setSpectatorTarget(null);

View File

@@ -24,6 +24,7 @@ import de.steamwar.bausystem.Permission;
import de.steamwar.bausystem.linkage.BauGuiItem; import de.steamwar.bausystem.linkage.BauGuiItem;
import de.steamwar.bausystem.region.utils.RegionExtensionType; import de.steamwar.bausystem.region.utils.RegionExtensionType;
import de.steamwar.bausystem.region.utils.RegionType; import de.steamwar.bausystem.region.utils.RegionType;
import de.steamwar.core.SWPlayer;
import de.steamwar.inventory.SWInventory; import de.steamwar.inventory.SWInventory;
import de.steamwar.inventory.SWItem; import de.steamwar.inventory.SWItem;
import de.steamwar.linkage.Linked; import de.steamwar.linkage.Linked;
@@ -35,15 +36,11 @@ import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap;
import java.util.Locale; import java.util.Locale;
import java.util.Map;
@Linked @Linked
public class SelectBauGuiItem extends BauGuiItem { public class SelectBauGuiItem extends BauGuiItem {
private static final Map<Player, LastSelect> LAST_SELECT_MAP = new HashMap<>();
public SelectBauGuiItem() { public SelectBauGuiItem() {
super(13); super(13);
} }
@@ -58,13 +55,13 @@ public class SelectBauGuiItem extends BauGuiItem {
private static void selectFinish(Player p, RegionType type, RegionExtensionType extensionType) { private static void selectFinish(Player p, RegionType type, RegionExtensionType extensionType) {
p.closeInventory(); p.closeInventory();
LAST_SELECT_MAP.put(p, new LastSelect(type, extensionType)); SWPlayer.of(p).setComponent(new LastSelect(type, extensionType));
p.performCommand("select " + type.name() + " " + extensionType.toString()); p.performCommand("select " + type.name() + " " + extensionType.toString());
} }
@Override @Override
public ItemStack getItem(Player player) { public ItemStack getItem(Player player) {
LastSelect last = LAST_SELECT_MAP.getOrDefault(player, new LastSelect(RegionType.BUILD, RegionExtensionType.NORMAL)); LastSelect last = SWPlayer.of(player).getComponentOrDefault(LastSelect.class, () -> new LastSelect(RegionType.BUILD, RegionExtensionType.NORMAL));
return new SWItem(Material.SCAFFOLDING, BauSystem.MESSAGE.parse("SELECT_ITEM_SELECT", player), Arrays.asList(BauSystem.MESSAGE.parse("SELECT_ITEM_AUSWAHL", player, BauSystem.MESSAGE.parse(last.type.getChatValue(), player), last.extensionType.name()), BauSystem.MESSAGE.parse("SELECT_ITEM_RIGHT_CLICK", player)), false, clickType -> { return new SWItem(Material.SCAFFOLDING, BauSystem.MESSAGE.parse("SELECT_ITEM_SELECT", player), Arrays.asList(BauSystem.MESSAGE.parse("SELECT_ITEM_AUSWAHL", player, BauSystem.MESSAGE.parse(last.type.getChatValue(), player), last.extensionType.name()), BauSystem.MESSAGE.parse("SELECT_ITEM_RIGHT_CLICK", player)), false, clickType -> {
}).getItemStack(); }).getItemStack();
} }
@@ -80,7 +77,7 @@ public class SelectBauGuiItem extends BauGuiItem {
inv.open(); inv.open();
} else { } else {
p.closeInventory(); p.closeInventory();
LastSelect last = LAST_SELECT_MAP.getOrDefault(p, new LastSelect(RegionType.BUILD, RegionExtensionType.NORMAL)); LastSelect last = SWPlayer.of(p).getComponentOrDefault(LastSelect.class, () -> new LastSelect(RegionType.BUILD, RegionExtensionType.NORMAL));
p.performCommand("select " + last.getType().name() + " " + last.getExtensionType().toString()); p.performCommand("select " + last.getType().name() + " " + last.getExtensionType().toString());
} }
return false; return false;
@@ -92,7 +89,7 @@ public class SelectBauGuiItem extends BauGuiItem {
} }
@AllArgsConstructor @AllArgsConstructor
private static class LastSelect { private static class LastSelect implements SWPlayer.Component {
@Getter @Getter
private final RegionType type; private final RegionType type;
@Getter @Getter

View File

@@ -21,6 +21,7 @@ package de.steamwar.bausystem.features.warp;
import de.steamwar.bausystem.region.Region; import de.steamwar.bausystem.region.Region;
import de.steamwar.core.Core; import de.steamwar.core.Core;
import de.steamwar.core.SWPlayer;
import de.steamwar.entity.RArmorStand; import de.steamwar.entity.RArmorStand;
import de.steamwar.entity.REntityServer; import de.steamwar.entity.REntityServer;
import de.steamwar.linkage.Linked; import de.steamwar.linkage.Linked;
@@ -30,7 +31,10 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.block.Action; import org.bukkit.event.block.Action;
import org.bukkit.event.player.*; import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerItemHeldEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerToggleSneakEvent;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
@@ -42,8 +46,21 @@ import java.util.Map;
@Linked @Linked
public class WarpListener implements Listener { public class WarpListener implements Listener {
private Map<Player, REntityServer> warpEntityServer = new HashMap<>(); public static class WarpComponent implements SWPlayer.Component {
private Map<Player, List<Location>> selected = new HashMap<>(); private REntityServer server;
private List<Location> selected = new ArrayList<>();
@Override
public void onMount(SWPlayer player) {
server = new REntityServer();
server.addPlayer(player.getPlayer());
}
@Override
public void onUnmount(SWPlayer player) {
server.close();
}
}
@EventHandler @EventHandler
public void onPlayerItemHeld(PlayerItemHeldEvent e) { public void onPlayerItemHeld(PlayerItemHeldEvent e) {
@@ -65,20 +82,11 @@ public class WarpListener implements Listener {
} }
private void reshow(Player p, Material material, boolean sneaking) { private void reshow(Player p, Material material, boolean sneaking) {
REntityServer entityServer = warpEntityServer.get(p); SWPlayer swPlayer = SWPlayer.of(p);
if (entityServer != null) { swPlayer.removeComponent(WarpComponent.class);
entityServer.close(); if (material != Material.COMPASS) return;
}
if (material != Material.COMPASS) {
warpEntityServer.remove(p);
return;
}
selected.remove(p);
entityServer = new REntityServer();
entityServer.addPlayer(p);
warpEntityServer.put(p, entityServer);
WarpComponent warpComponent = swPlayer.getComponentOrDefault(WarpComponent.class, WarpComponent::new);
Vector current = p.getLocation().clone().add(p.getLocation().getDirection().multiply(5)).toVector(); Vector current = p.getLocation().clone().add(p.getLocation().getDirection().multiply(5)).toVector();
Map<String, Location> locations = new HashMap<>(); Map<String, Location> locations = new HashMap<>();
@@ -99,12 +107,9 @@ public class WarpListener implements Listener {
} }
} }
REntityServer finalEntityServer = entityServer;
locations.forEach((name, location) -> { locations.forEach((name, location) -> {
Vector vector = location.toVector().subtract(p.getLocation().toVector()); Vector vector = location.toVector().subtract(p.getLocation().toVector());
if (vector.getX() * vector.getX() + vector.getZ() * vector.getZ() < 25) { if (vector.getX() * vector.getX() + vector.getZ() * vector.getZ() < 25) return;
return;
}
vector.setY(0); vector.setY(0);
Vector position = p.getLocation().toVector().clone().add(vector.normalize().multiply(5)); Vector position = p.getLocation().toVector().clone().add(vector.normalize().multiply(5));
@@ -112,9 +117,9 @@ public class WarpListener implements Listener {
if ((position.getX() - current.getX()) * (position.getX() - current.getX()) + (position.getZ() - current.getZ()) * (position.getZ() - current.getZ()) < 0.1) { if ((position.getX() - current.getX()) * (position.getX() - current.getX()) + (position.getZ() - current.getZ()) * (position.getZ() - current.getZ()) < 0.1) {
name = "§a§l" + name; name = "§a§l" + name;
selected.computeIfAbsent(p, player -> new ArrayList<>()).add(location); warpComponent.selected.add(location);
} }
RArmorStand armorStand = new RArmorStand(finalEntityServer, position.toLocation(p.getWorld()), RArmorStand.Size.MARKER); RArmorStand armorStand = new RArmorStand(warpComponent.server, position.toLocation(p.getWorld()), RArmorStand.Size.MARKER);
armorStand.setDisplayName(name); armorStand.setDisplayName(name);
armorStand.setNoGravity(true); armorStand.setNoGravity(true);
armorStand.setInvisible(true); armorStand.setInvisible(true);
@@ -123,28 +128,13 @@ public class WarpListener implements Listener {
@EventHandler(priority = EventPriority.LOWEST) @EventHandler(priority = EventPriority.LOWEST)
public void onPlayerInteract(PlayerInteractEvent event) { public void onPlayerInteract(PlayerInteractEvent event) {
if (event.getPlayer().getInventory().getItemInMainHand().getType() != Material.COMPASS) { if (event.getPlayer().getInventory().getItemInMainHand().getType() != Material.COMPASS) return;
return; if (event.getAction() != Action.RIGHT_CLICK_AIR) return;
} WarpComponent warpComponent = SWPlayer.of(event.getPlayer()).getComponent(WarpComponent.class).orElse(null);
if (event.getAction() != Action.RIGHT_CLICK_AIR) { if (warpComponent == null || warpComponent.selected.size() != 1) return;
return; Location location = warpComponent.selected.get(0);
}
List<Location> locations = selected.getOrDefault(event.getPlayer(), new ArrayList<>());
if (locations.size() != 1) {
return;
}
Location location = locations.get(0);
event.getPlayer().teleport(location); event.getPlayer().teleport(location);
event.getPlayer().playSound(location, Sound.ENTITY_ENDERMAN_TELEPORT, SoundCategory.PLAYERS, 1, 1); event.getPlayer().playSound(location, Sound.ENTITY_ENDERMAN_TELEPORT, SoundCategory.PLAYERS, 1, 1);
event.setCancelled(true); event.setCancelled(true);
} }
@EventHandler
public void onPlayerQuit(PlayerQuitEvent event) {
warpEntityServer.computeIfPresent(event.getPlayer(), (player, rEntityServer) -> {
rEntityServer.close();
return null;
});
selected.remove(event.getPlayer());
}
} }

View File

@@ -41,7 +41,7 @@ public class AntiBauAddMemberFix implements Listener {
} }
if (BauweltMember.getBauMember(BauServer.getInstance().getOwner(), event.getPlayer().getUniqueId()) == null) { if (BauweltMember.getBauMember(BauServer.getInstance().getOwner(), event.getPlayer().getUniqueId()) == null) {
event.getPlayer().kickPlayer(""); 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!");
} }
} }

View File

@@ -59,18 +59,14 @@ public class BauMemberUpdate extends PacketHandler implements Listener {
Set<Player> newSpectator = new HashSet<>(); Set<Player> newSpectator = new HashSet<>();
Set<Player> newBuilder = new HashSet<>(); Set<Player> newBuilder = new HashSet<>();
Bukkit.getOnlinePlayers().forEach(player -> { Bukkit.getOnlinePlayers().forEach(player -> {
if (Permission.REAL_SPECTATOR.hasPermission(player)) { if (Permission.SPECTATOR.hasPermission(player)) {
if (!SPECTATORS.contains(player)) { if (!SPECTATORS.contains(player)) {
SPECTATORS.add(player); SPECTATORS.add(player);
Permission.removeForceOnlySpectator(player);
newSpectator.add(player); newSpectator.add(player);
player.addPotionEffect(new PotionEffect(PotionEffectType.GLOWING, -1, 1, false,false, false)); player.addPotionEffect(new PotionEffect(PotionEffectType.GLOWING, -1, 1, false,false, false));
showSpectatorNotice(player); showSpectatorNotice(player);
} }
} else { } else {
if (Permission.SUPERVISOR.hasPermission(player)) {
Permission.removeForceOnlySpectator(player);
}
if (SPECTATORS.contains(player)) { if (SPECTATORS.contains(player)) {
SPECTATORS.remove(player); SPECTATORS.remove(player);
newBuilder.add(player); newBuilder.add(player);

View File

@@ -21,6 +21,7 @@ package de.steamwar.bausystem.features.world;
import de.steamwar.linkage.Linked; import de.steamwar.linkage.Linked;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.TNTPrimed;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
@@ -31,6 +32,7 @@ public class OtherTNTListener implements Listener {
@EventHandler(priority = EventPriority.MONITOR) @EventHandler(priority = EventPriority.MONITOR)
public void onExplosion(EntityExplodeEvent e) { public void onExplosion(EntityExplodeEvent e) {
if (!(e instanceof TNTPrimed)) return;
e.blockList().removeIf(block -> { e.blockList().removeIf(block -> {
if(block.getType() == Material.TNT) { if(block.getType() == Material.TNT) {
return false; return false;

View File

@@ -49,6 +49,7 @@ import java.util.Set;
@Linked @Linked
public class SpectatorListener implements Listener { public class SpectatorListener implements Listener {
private static final TechHider techHider;
private static final Set<Player> NO_TECHHIDER = new HashSet<>(); private static final Set<Player> NO_TECHHIDER = new HashSet<>();
static { static {
@@ -100,10 +101,20 @@ public class SpectatorListener implements Listener {
materials.add(Material.WATER); materials.add(Material.WATER);
materials.remove(Material.BARRIER); materials.remove(Material.BARRIER);
materials.remove(Material.STONE); materials.remove(Material.STONE);
TechHider techHider = new TechHider((TechHider.LocationEvaluator) (player, i, i1) -> { techHider = new TechHider((TechHider.LocationEvaluator) (player, i, i1) -> {
return Permission.BUILD.hasPermission(player) || Permission.isTempOnlySpectator(player) || NO_TECHHIDER.contains(player); return Permission.BUILD.hasPermission(player) || NO_TECHHIDER.contains(player);
}, Material.END_STONE, materials, new HashSet<>()); }, Material.END_STONE, materials, new HashSet<>());
techHider.enable(); }
private static void enableOrDisableTechhider() {
boolean enable = Bukkit.getOnlinePlayers()
.stream()
.anyMatch(player -> !(Permission.BUILD.hasPermission(player) || NO_TECHHIDER.contains(player)));
if (enable) {
techHider.enable();
} else {
techHider.disable();
}
} }
public static void toggleNoTechHider(Player player) { public static void toggleNoTechHider(Player player) {
@@ -113,6 +124,7 @@ public class SpectatorListener implements Listener {
NO_TECHHIDER.add(player); NO_TECHHIDER.add(player);
} }
resendChunks(player); resendChunks(player);
enableOrDisableTechhider();
} }
private static void resendChunks(Player player) { private static void resendChunks(Player player) {
@@ -131,6 +143,7 @@ public class SpectatorListener implements Listener {
@EventHandler @EventHandler
public void onPlayerJoin(PlayerJoinEvent event) { public void onPlayerJoin(PlayerJoinEvent event) {
enableOrDisableTechhider();
if (BauSystem.DEV_SERVER) return; if (BauSystem.DEV_SERVER) return;
if (event.getPlayer().getUniqueId().equals(BauServer.getInstance().getOwner())) { if (event.getPlayer().getUniqueId().equals(BauServer.getInstance().getOwner())) {
return; return;
@@ -152,6 +165,7 @@ public class SpectatorListener implements Listener {
@EventHandler @EventHandler
public void onBauMemberUpdate(BauMemberUpdateEvent event) { public void onBauMemberUpdate(BauMemberUpdateEvent event) {
enableOrDisableTechhider();
if (!anySupervisorOnline(null) && !BauSystem.DEV_SERVER) { if (!anySupervisorOnline(null) && !BauSystem.DEV_SERVER) {
Bukkit.getOnlinePlayers().forEach(player -> { Bukkit.getOnlinePlayers().forEach(player -> {
player.kickPlayer(""); player.kickPlayer("");
@@ -161,7 +175,6 @@ public class SpectatorListener implements Listener {
event.getChanged().forEach(player -> { event.getChanged().forEach(player -> {
NO_TECHHIDER.remove(player); NO_TECHHIDER.remove(player);
if (Permission.isTempOnlySpectator(player)) return;
resendChunks(player); resendChunks(player);
}); });
} }
@@ -169,6 +182,7 @@ public class SpectatorListener implements Listener {
@EventHandler @EventHandler
public void onPlayerQuit(PlayerQuitEvent event) { public void onPlayerQuit(PlayerQuitEvent event) {
NO_TECHHIDER.remove(event.getPlayer()); NO_TECHHIDER.remove(event.getPlayer());
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), SpectatorListener::enableOrDisableTechhider, 1);
if (BauSystem.DEV_SERVER) return; if (BauSystem.DEV_SERVER) return;
if (!anySupervisorOnline(event.getPlayer())) { if (!anySupervisorOnline(event.getPlayer())) {
Bukkit.getOnlinePlayers().forEach(player -> { Bukkit.getOnlinePlayers().forEach(player -> {

View File

@@ -23,6 +23,7 @@ import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.region.Point; import de.steamwar.bausystem.region.Point;
import de.steamwar.bausystem.region.Region; import de.steamwar.bausystem.region.Region;
import de.steamwar.bausystem.utils.FlatteningWrapper; import de.steamwar.bausystem.utils.FlatteningWrapper;
import de.steamwar.core.SWPlayer;
import de.steamwar.core.WorldEditRenderer; import de.steamwar.core.WorldEditRenderer;
import de.steamwar.linkage.Linked; import de.steamwar.linkage.Linked;
import de.steamwar.linkage.MinVersion; import de.steamwar.linkage.MinVersion;
@@ -35,13 +36,10 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.block.Action; import org.bukkit.event.block.Action;
import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.scheduler.BukkitTask; import org.bukkit.scheduler.BukkitTask;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.function.Predicate; import java.util.function.Predicate;
@@ -71,32 +69,23 @@ public class SelectAdjacent implements Listener {
new Vector(0, -1, -1), new Vector(0, -1, -1),
}; };
private Map<Player, Selector> selectors = new HashMap<>();
@EventHandler @EventHandler
public void onPlayerInteract(PlayerInteractEvent event) { public void onPlayerInteract(PlayerInteractEvent event) {
if (!event.hasItem()) return; if (!event.hasItem()) return;
if (event.getItem().getType() != Material.WOODEN_AXE) return; if (event.getItem().getType() != Material.WOODEN_AXE) return;
Selector selector = selectors.get(event.getPlayer());
if (selector != null) selector.cancel();
if (!event.getPlayer().isSneaking()) return; if (!event.getPlayer().isSneaking()) return;
if (event.getAction() != Action.LEFT_CLICK_BLOCK) return; if (event.getAction() != Action.LEFT_CLICK_BLOCK) return;
Material material = event.getPlayer().getInventory().getItemInOffHand().getType(); Material material = event.getPlayer().getInventory().getItemInOffHand().getType();
Selector selector;
if (material.isAir()) { if (material.isAir()) {
selector = new Selector(event.getClickedBlock(), event.getPlayer(), __ -> true); selector = new Selector(event.getClickedBlock(), event.getPlayer(), __ -> true);
} else { } else {
selector = new Selector(event.getClickedBlock(), event.getPlayer(), type -> type == material); selector = new Selector(event.getClickedBlock(), event.getPlayer(), type -> type == material);
} }
selectors.put(event.getPlayer(), selector); SWPlayer.of(event.getPlayer()).setComponent(selector);
} }
@EventHandler private class Selector implements SWPlayer.Component {
public void onPlayerQuit(PlayerQuitEvent event) {
Selector selector = selectors.remove(event.getPlayer());
if (selector != null) selector.cancel();
}
private class Selector {
private static final int MAX_BLOCKS = 500_000; private static final int MAX_BLOCKS = 500_000;
@@ -154,6 +143,7 @@ public class SelectAdjacent implements Listener {
if (toCalc.isEmpty() || seen.size() > MAX_BLOCKS) { if (toCalc.isEmpty() || seen.size() > MAX_BLOCKS) {
bukkitTask.cancel(); bukkitTask.cancel();
player.sendTitle("§aDone", "§e" + volume + " §7Blocks", 0, 20, 5); player.sendTitle("§aDone", "§e" + volume + " §7Blocks", 0, 20, 5);
SWPlayer.of(player).removeComponent(Selector.class);
} }
}, 1, 1); }, 1, 1);
} }
@@ -190,5 +180,10 @@ public class SelectAdjacent implements Listener {
} }
} }
} }
@Override
public void onUnmount(SWPlayer player) {
cancel();
}
} }
} }

View File

@@ -104,7 +104,7 @@ public class XrayCommand extends SWCommand implements Listener, ScoreboardElemen
if (hidden.containsKey(region) && hidden.get(region).contains(player)) { if (hidden.containsKey(region) && hidden.get(region).contains(player)) {
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> { Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> {
PlayerMovementWrapper.impl.setPosition(player, o); PlayerMovementWrapper.impl.setPosition(player, o);
}, 1L); }, 0);
return null; return null;
} }
return o; return o;

View File

@@ -50,5 +50,6 @@ tasks.register<DevServer>("DevBau21") {
description = "Run a 1.21 Dev Bau" description = "Run a 1.21 Dev Bau"
dependsOn(":SpigotCore:shadowJar") dependsOn(":SpigotCore:shadowJar")
dependsOn(":BauSystem:shadowJar") dependsOn(":BauSystem:shadowJar")
dependsOn(":SchematicSystem:shadowJar")
template = "Bau21" template = "Bau21"
} }

View File

@@ -18,11 +18,26 @@
*/ */
plugins { plugins {
steamwar.java steamwar.kotlin
}
kotlin {
jvmToolchain(8)
}
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
} }
dependencies { dependencies {
compileOnly(libs.sqlite) compileOnly(libs.sqlite)
implementation("org.yaml:snakeyaml:2.2") implementation("org.yaml:snakeyaml:2.2")
compileOnlyApi("org.jetbrains.kotlin:kotlin-stdlib:2.2.21")
compileOnlyApi(libs.exposedCore)
compileOnlyApi(libs.exposedDao)
compileOnlyApi(libs.exposedJdbc)
compileOnlyApi(libs.exposedTime)
} }

View File

@@ -1,125 +0,0 @@
/*
* 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.sql;
import de.steamwar.sql.internal.Field;
import de.steamwar.sql.internal.SqlTypeMapper;
import de.steamwar.sql.internal.Statement;
import de.steamwar.sql.internal.Table;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NonNull;
import java.sql.Timestamp;
import java.time.Instant;
@AllArgsConstructor
public class AuditLog {
static {
SqlTypeMapper.nameEnumMapper(AuditLog.Type.class);
}
public static final String SERVER_NAME_VELOCITY = "Velocity";
private static final Table<AuditLog> table = new Table<>(AuditLog.class);
private static final Statement create = table.insertFields(true, "time", "serverName", "serverOwner", "actor", "actionType", "actionText");
@Getter
@Field
private final Timestamp time;
@Getter
@Field
private final String serverName;
@Field(nullable = true)
private final int serverOwner;
@Field
private final int actor;
@Getter
@Field
private final Type actionType;
@Getter
@Field
private final String actionText;
public enum Type {
JOIN,
LEAVE,
COMMAND,
SENSITIVE_COMMAND,
CHAT,
GUI_OPEN,
GUI_CLOSE,
GUI_CLICK,
}
private static void create(String serverName, SteamwarUser serverOwner, SteamwarUser actor, Type actionType, String text) {
create.insertGetKey(Timestamp.from(Instant.now()), serverName, serverOwner, actor, actionType, text);
}
public static void createJoin(@NonNull String jointServerName, SteamwarUser serverOwner, @NonNull SteamwarUser joinedPlayer) {
create(jointServerName, serverOwner, joinedPlayer, Type.JOIN, "");
}
public static void createLeave(@NonNull String leftServerName, SteamwarUser serverOwner, @NonNull SteamwarUser joinedPlayer) {
create(leftServerName, serverOwner, joinedPlayer, Type.LEAVE, "");
}
public static void createCommand(@NonNull String serverName, SteamwarUser serverOwner, SteamwarUser player, @NonNull String command) {
if (player == null) return;
create(serverName, serverOwner, player, Type.COMMAND, command);
}
public static void createSensitiveCommand(@NonNull String serverName, SteamwarUser serverOwner, SteamwarUser player, @NonNull String command) {
if (player == null) return;
create(serverName, serverOwner, player, Type.SENSITIVE_COMMAND, command);
}
public static void createChat(@NonNull String serverName, SteamwarUser serverOwner, @NonNull SteamwarUser chatter, @NonNull String chat) {
create(serverName, serverOwner, chatter, Type.CHAT, chat);
}
public static void createGuiOpen(@NonNull String serverName, SteamwarUser serverOwner, @NonNull SteamwarUser player, @NonNull String guiName) {
create(serverName, serverOwner, player, Type.GUI_OPEN, guiName);
}
public static void createGuiClick(@NonNull String serverName, SteamwarUser serverOwner, @NonNull SteamwarUser player, @NonNull String guiName, @NonNull String clickType, int slot, @NonNull String itemName) {
create(serverName, serverOwner, player, Type.GUI_CLICK, "Gui: " + guiName + "\nSlot: " + slot + "\nClickType: " + clickType + "\nItemName: " + itemName);
}
public static void createGuiClose(@NonNull String serverName, SteamwarUser serverOwner, @NonNull SteamwarUser player, @NonNull String guiName) {
create(serverName, serverOwner, player, Type.GUI_CLOSE, guiName);
}
public SteamwarUser getServerOwner() {
return SteamwarUser.get(serverOwner);
}
public SteamwarUser getActor() {
return SteamwarUser.get(actor);
}
}

View File

@@ -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.sql
import de.steamwar.sql.internal.useDb
import org.jetbrains.exposed.v1.core.dao.id.EntityID
import org.jetbrains.exposed.v1.core.dao.id.IntIdTable
import org.jetbrains.exposed.v1.dao.IntEntity
import org.jetbrains.exposed.v1.dao.IntEntityClass
import org.jetbrains.exposed.v1.javatime.timestamp
import java.time.Instant
object AuditLogTable: IntIdTable("AuditLog", "AuditLogId") {
val time = timestamp("Time")
val server = varchar("ServerName", 255)
val serverOwner = reference("ServerOwner", SteamwarUserTable).nullable()
val actor = reference("Actor", SteamwarUserTable)
val action = enumerationByName("ActionType", 255, AuditLog.Type::class)
val actionText = text("ActionText")
}
class AuditLog(id: EntityID<Int>): IntEntity(id) {
companion object: IntEntityClass<AuditLog>(AuditLogTable) {
const val SERVER_NAME_VELOCITY: String = "Velocity"
private fun create(
serverName: String,
serverOwner: SteamwarUser?,
actor: SteamwarUser,
actionType: Type,
text: String = ""
) = useDb {
new {
this.time = Instant.now()
this.server = serverName
this.serverOwner = serverOwner?.id
this.actor = actor.id
this.action = actionType
this.actionText = text
}
}
@JvmStatic
fun createJoin(jointServerName: String, serverOwner: SteamwarUser?, joinedPlayer: SteamwarUser) = create(jointServerName, serverOwner, joinedPlayer, Type.JOIN)
@JvmStatic
fun createLeave(leftServerName: String, serverOwner: SteamwarUser?, joinedPlayer: SteamwarUser) = create(leftServerName, serverOwner, joinedPlayer, Type.LEAVE)
@JvmStatic
fun createCommand(serverName: String, serverOwner: SteamwarUser?, player: SteamwarUser?, command: String) = player?.let { create(serverName, serverOwner, it, Type.COMMAND, command) }
@JvmStatic
fun createSensitiveCommand(
serverName: String,
serverOwner: SteamwarUser?,
player: SteamwarUser?,
command: String
) = player?.let { create(serverName, serverOwner, it, Type.SENSITIVE_COMMAND, command) }
@JvmStatic
fun createChat(serverName: String, serverOwner: SteamwarUser?, chatter: SteamwarUser, chat: String) = create(serverName, serverOwner, chatter, Type.CHAT, chat)
@JvmStatic
fun createGuiOpen(serverName: String, serverOwner: SteamwarUser?, player: SteamwarUser, guiName: String) = create(serverName, serverOwner, player, Type.GUI_OPEN, guiName)
@JvmStatic
fun createGuiClick(
serverName: String,
serverOwner: SteamwarUser?,
player: SteamwarUser,
guiName: String,
clickType: String,
slot: Int,
itemName: String
) = create(
serverName,
serverOwner,
player,
Type.GUI_CLICK,
"Gui: $guiName\nSlot: $slot\nClickType: $clickType\nItemName: $itemName"
)
@JvmStatic
fun createGuiClose(serverName: String, serverOwner: SteamwarUser?, player: SteamwarUser, guiName: String) = create(serverName, serverOwner, player, Type.GUI_CLOSE, guiName)
}
var time by AuditLogTable.time
var server by AuditLogTable.server
var serverOwner by AuditLogTable.serverOwner
var actor by AuditLogTable.actor
var action by AuditLogTable.action
var actionText by AuditLogTable.actionText
enum class Type {
JOIN,
LEAVE,
COMMAND,
SENSITIVE_COMMAND,
CHAT,
GUI_OPEN,
GUI_CLOSE,
GUI_CLICK,
}
}

View File

@@ -1,67 +0,0 @@
/*
* 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.sql;
import de.steamwar.sql.internal.Field;
import de.steamwar.sql.internal.SelectStatement;
import de.steamwar.sql.internal.Statement;
import de.steamwar.sql.internal.Table;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.sql.Timestamp;
import java.time.Instant;
import java.util.List;
@AllArgsConstructor
public class BannedUserIPs {
private static final Table<BannedUserIPs> table = new Table<>(BannedUserIPs.class);
private static final SelectStatement<BannedUserIPs> getByID = table.selectFields("UserID");
private static final SelectStatement<BannedUserIPs> getByIP = new SelectStatement<>(table, "SELECT * FROM BannedUserIPs WHERE IP = ? ORDER BY Timestamp DESC");
private static final Statement banIP = table.insertAll();
private static final Statement unbanIPs = table.deleteFields("UserID");
@Getter
@Field(keys = {Table.PRIMARY})
private final int userID;
@Getter
@Field(def = "CURRENT_TIMESTAMP")
private final Timestamp timestamp;
@Field(keys = {Table.PRIMARY})
private final String ip;
public static List<BannedUserIPs> get(int userID) {
return getByID.listSelect(userID);
}
public static List<BannedUserIPs> get(String ip) {
return getByIP.listSelect(ip);
}
public static void banIP(int userID, String ip){
banIP.update(userID, Timestamp.from(Instant.now()), ip);
}
public static void unbanIPs(int userID) {
unbanIPs.update(userID);
}
}

View File

@@ -0,0 +1,78 @@
/*
* 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.sql
import de.steamwar.sql.internal.useDb
import org.jetbrains.exposed.v1.core.dao.id.CompositeID
import org.jetbrains.exposed.v1.core.dao.id.CompositeIdTable
import org.jetbrains.exposed.v1.core.dao.id.EntityID
import org.jetbrains.exposed.v1.core.eq
import org.jetbrains.exposed.v1.dao.CompositeEntity
import org.jetbrains.exposed.v1.dao.CompositeEntityClass
import org.jetbrains.exposed.v1.javatime.timestamp
import org.jetbrains.exposed.v1.jdbc.deleteWhere
import org.jetbrains.exposed.v1.jdbc.insertIgnore
import java.sql.Timestamp
import java.time.Instant
object BannedUserIPsTable: CompositeIdTable("BannedUserIPs") {
val userId = reference("UserID", SteamwarUserTable)
val timestamp = timestamp("Timestamp")
val ip = varchar("IP", 45)
override val primaryKey = PrimaryKey(userId, ip)
}
class BannedUserIPs(id: EntityID<CompositeID>): CompositeEntity(id) {
companion object: CompositeEntityClass<BannedUserIPs>(BannedUserIPsTable) {
@JvmStatic
fun get(userId: Int) = useDb {
find { BannedUserIPsTable.userId eq userId }.toList()
}
@JvmStatic
fun get(ip: String) = useDb {
find { BannedUserIPsTable.ip eq ip }.toList()
}
@JvmStatic
fun banIP(userId: Int, ip: String) = useDb {
BannedUserIPsTable.insertIgnore {
it[BannedUserIPsTable.userId] = userId
it[BannedUserIPsTable.ip] = ip
it[BannedUserIPsTable.timestamp] = Instant.now()
}
}
@JvmStatic
fun unbanIPs(userId: Int) = useDb {
BannedUserIPsTable.deleteWhere { BannedUserIPsTable.userId eq userId }
}
}
val userID by BannedUserIPsTable.userId.transform({ EntityID(it, SteamwarUserTable) }, { it.value })
val timestamp: Timestamp by BannedUserIPsTable.timestamp.transform({ it.toInstant() }, { Timestamp.from(it) })
val ip by BannedUserIPsTable.ip
fun remove() = useDb {
delete()
}
}

View File

@@ -1,123 +0,0 @@
/*
* 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.sql;
import de.steamwar.sql.internal.Field;
import de.steamwar.sql.internal.SelectStatement;
import de.steamwar.sql.internal.Statement;
import de.steamwar.sql.internal.Table;
import lombok.Getter;
import java.util.*;
public class BauweltMember {
private static final Map<Integer, BauweltMember> memberCache = new HashMap<>();
public static void clear() {
memberCache.clear();
}
private static final Table<BauweltMember> table = new Table<>(BauweltMember.class);
private static final SelectStatement<BauweltMember> getMember = table.select(Table.PRIMARY);
private static final SelectStatement<BauweltMember> getMembers = table.selectFields("BauweltID");
private static final Statement update = table.insertAll();
private static final Statement delete = table.delete(Table.PRIMARY);
public static void addMember(UUID ownerID, UUID memberID) {
new BauweltMember(SteamwarUser.get(ownerID).getId(), SteamwarUser.get(memberID).getId(), false, false).updateDB();
}
public static BauweltMember getBauMember(UUID ownerID, UUID memberID){
return getBauMember(SteamwarUser.get(ownerID).getId(), SteamwarUser.get(memberID).getId());
}
public static BauweltMember getBauMember(int ownerID, int memberID){
BauweltMember member = memberCache.get(memberID);
if(member != null && member.bauweltID == ownerID)
return member;
return getMember.select(ownerID, memberID);
}
public static List<BauweltMember> getMembers(UUID bauweltID){
return getMembers(SteamwarUser.get(bauweltID).getId());
}
public static List<BauweltMember> getMembers(int bauweltID){
return getMembers.listSelect(bauweltID);
}
@Getter
@Field(keys = {Table.PRIMARY})
private final int bauweltID;
@Getter
@Field(keys = {Table.PRIMARY})
private final int memberID;
@Getter
@Field(def = "0")
private boolean worldEdit;
@Getter
@Field(def = "0")
private boolean world;
public BauweltMember(int bauweltID, int memberID, boolean worldEdit, boolean world) {
this.bauweltID = bauweltID;
this.memberID = memberID;
this.worldEdit = worldEdit;
this.world = world;
memberCache.put(memberID, this);
}
public void setWorldEdit(boolean worldEdit) {
this.worldEdit = worldEdit;
updateDB();
}
public void setWorld(boolean world) {
this.world = world;
updateDB();
}
private void updateDB(){
update.update(bauweltID, memberID, worldEdit, world);
}
public void remove(){
delete.update(bauweltID, memberID);
memberCache.remove(memberID);
}
public boolean isBuild() {
return worldEdit;
}
public boolean isSupervisor() {
return world;
}
public void setBuild(boolean build) {
this.worldEdit = build;
updateDB();
}
public void setSupervisor(boolean supervisor) {
this.world = supervisor;
updateDB();
}
}

View File

@@ -0,0 +1,130 @@
/*
* 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.sql
import de.steamwar.sql.BauweltMemberTable.bauweltId
import de.steamwar.sql.internal.useDb
import org.jetbrains.exposed.v1.core.and
import org.jetbrains.exposed.v1.core.dao.id.CompositeID
import org.jetbrains.exposed.v1.core.dao.id.CompositeIdTable
import org.jetbrains.exposed.v1.core.dao.id.EntityID
import org.jetbrains.exposed.v1.core.eq
import org.jetbrains.exposed.v1.dao.CompositeEntity
import org.jetbrains.exposed.v1.dao.CompositeEntityClass
import org.jetbrains.exposed.v1.jdbc.insertIgnore
import java.util.*
object BauweltMemberTable: CompositeIdTable("BauweltMember") {
val bauweltId = reference("BauweltID", SteamwarUserTable)
val memberId = reference("MemberID", SteamwarUserTable)
val build = bool("Build")
val worldEdit = bool("WorldEdit")
val world = bool("World")
override val primaryKey = PrimaryKey(bauweltId, memberId)
init {
addIdColumn(bauweltId)
addIdColumn(memberId)
}
}
class BauweltMember(id: EntityID<CompositeID>): CompositeEntity(id) {
companion object: CompositeEntityClass<BauweltMember>(BauweltMemberTable) {
private val cache = mutableMapOf<Int, BauweltMember>()
private fun cache(member: BauweltMember) = cache.put(member.memberID, member)
@JvmStatic
fun clear() = cache.clear()
@JvmStatic
@Deprecated("Use addMember(ownerId: Int, newMemberId: Int)")
fun addMember(ownerId: UUID, newMemberId: UUID) = addMember(SteamwarUser.get(ownerId)!!.id, SteamwarUser.get(newMemberId)!!.id)
@JvmStatic
fun addMember(ownerId: Int, newMemberId: Int) = addMember(EntityID(ownerId, SteamwarUserTable), EntityID(newMemberId, SteamwarUserTable))
fun addMember(ownerId: EntityID<Int>, newMemberId: EntityID<Int>) = useDb {
BauweltMemberTable.insertIgnore {
it[bauweltId] = ownerId
it[memberId] = newMemberId
it[build] = false
it[worldEdit] = false
it[world] = false
}
}
@JvmStatic
@Deprecated("Use getBauMember(bauwelt: Int, member: Int)")
fun getBauMember(bauwelt: UUID, member: UUID) = useDb {
find { (bauweltId eq SteamwarUser.get(bauwelt)!!.id) and (BauweltMemberTable.memberId eq SteamwarUser.get(member)!!.id) }.firstOrNull()?.also { cache(it) }
}
@JvmStatic
fun getBauMember(bauwelt: Int, member: Int) = useDb {
find { (bauweltId eq bauwelt) and (BauweltMemberTable.memberId eq member) }.firstOrNull()?.also { cache(it) }
}
@JvmStatic
@Deprecated("Use getMembers(bauwelt: Int)")
fun getMembers(bauwelt: UUID) = getMembers(SteamwarUser.get(bauwelt)!!.id.value)
@JvmStatic
fun getMembers(bauwelt: Int) = useDb {
find { bauweltId eq bauwelt }.toList().also { it.forEach { cache(it) } }
}
}
val bauweltID by BauweltMemberTable.bauweltId.transform({ EntityID(it, SteamwarUserTable) }, { it.value })
val memberID by BauweltMemberTable.memberId.transform({ EntityID(it, SteamwarUserTable) }, { it.value })
private var worldEditInternal by BauweltMemberTable.worldEdit
var worldEdit: Boolean
get() = worldEditInternal
set(value) = useDb {
worldEditInternal = value
}
private var buildInternal by BauweltMemberTable.build
var build: Boolean
get() = buildInternal
set(value) = useDb {
buildInternal = value
}
private var worldInternal by BauweltMemberTable.world
var world: Boolean
get() = worldInternal
set(value) = useDb {
worldInternal = value
}
var supervisor: Boolean
get() = world
set(value) = useDb {
world = value
}
fun isBuild() = build
fun isSupervisor() = world
fun isWorldEdit() = build
fun isWorld() = world
fun remove() = useDb {
delete()
}
}

View File

@@ -1,101 +0,0 @@
/*
* 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.sql;
import de.steamwar.sql.internal.Field;
import de.steamwar.sql.internal.SelectStatement;
import de.steamwar.sql.internal.Statement;
import de.steamwar.sql.internal.Table;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.sql.Timestamp;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@AllArgsConstructor
public class CheckedSchematic {
private static final Table<CheckedSchematic> table = new Table<>(CheckedSchematic.class);
private static final SelectStatement<CheckedSchematic> statusOfNode = new SelectStatement<>(table, "SELECT * FROM CheckedSchematic WHERE NodeId = ? AND DeclineReason != 'Prüfvorgang abgebrochen' ORDER BY EndTime DESC");
private static final SelectStatement<CheckedSchematic> nodeHistory = new SelectStatement<>(table, "SELECT * FROM CheckedSchematic WHERE NodeId = ? AND DeclineReason != '' AND DeclineReason != 'Prüfvorgang abgebrochen' ORDER BY EndTime DESC");
private static final Statement insert = table.insertAll();
private static final SelectStatement<CheckedSchematic> getUnseen = new SelectStatement<>(table, "SELECT * FROM CheckedSchematic WHERE Seen = 0 AND NodeOwner = ? ORDER BY StartTime DESC");
private static final Statement updateSeen = new Statement("UPDATE CheckedSchematic SET Seen = ? WHERE StartTime = ? AND EndTime = ? AND NodeName = ?");
public static void create(SchematicNode node, int validator, Timestamp startTime, Timestamp endTime, String reason, boolean seen) {
insert.update(node.getId(), node.getOwner(), node.getName(), validator, startTime, endTime, reason, seen, node.getSchemtype().toDB().substring(1));
}
public static List<CheckedSchematic> getLastDeclinedOfNode(int node) {
return statusOfNode.listSelect(node);
}
public static List<CheckedSchematic> previousChecks(SchematicNode node) {
return nodeHistory.listSelect(node.getId());
}
public static List<CheckedSchematic> getUnseen(SteamwarUser owner) {
return getUnseen.listSelect(owner);
}
@Field(nullable = true)
private final Integer nodeId;
@Field
private final int nodeOwner;
@Field
private final String nodeName;
@Getter
@Field
private final int validator;
@Getter
@Field
private final Timestamp startTime;
@Getter
@Field
private final Timestamp endTime;
@Getter
@Field
private final String declineReason;
@Getter
@Field
private boolean seen;
@Getter
@Field
private final String nodeType;
public int getNode() {
return nodeId;
}
public String getSchemName() {
return nodeName;
}
public int getSchemOwner() {
return nodeOwner;
}
public void setSeen(boolean seen) {
this.seen = seen;
updateSeen.update(seen, startTime, endTime, nodeName);
}
}

View File

@@ -0,0 +1,100 @@
/*
* 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.sql
import de.steamwar.sql.internal.useDb
import org.jetbrains.exposed.v1.core.SortOrder
import org.jetbrains.exposed.v1.core.and
import org.jetbrains.exposed.v1.core.dao.id.CompositeID
import org.jetbrains.exposed.v1.core.dao.id.CompositeIdTable
import org.jetbrains.exposed.v1.core.dao.id.EntityID
import org.jetbrains.exposed.v1.core.eq
import org.jetbrains.exposed.v1.core.neq
import org.jetbrains.exposed.v1.dao.CompositeEntity
import org.jetbrains.exposed.v1.dao.CompositeEntityClass
import org.jetbrains.exposed.v1.javatime.timestamp
import org.jetbrains.exposed.v1.jdbc.insertIgnore
import java.sql.Timestamp
object CheckedSchematicTable: CompositeIdTable("CheckedSchematic") {
val nodeId = optReference("NodeId", SchematicNodeTable)
val nodeOwner = reference("NodeOwner", SteamwarUserTable)
val nodeName = varchar("NodeName", 64).entityId()
val validator = reference("Validator", SteamwarUserTable)
val startTime = timestamp("StartTime").entityId()
val endTime = timestamp("EndTime")
val declineReason = text("DeclineReason")
val seen = bool("Seen")
val nodeType = varchar("NodeType", 16)
init {
addIdColumn(nodeOwner)
addIdColumn(nodeName)
}
}
class CheckedSchematic(id: EntityID<CompositeID>): CompositeEntity(id) {
companion object: CompositeEntityClass<CheckedSchematic>(CheckedSchematicTable) {
@JvmStatic
fun create(node: SchematicNode, validator: Int, startTime: Timestamp, endTime: Timestamp, reason: String, seen: Boolean) = useDb {
CheckedSchematicTable.insertIgnore {
it[this.nodeId] = node.id
it[this.nodeOwner] = EntityID(node.owner, SteamwarUserTable)
it[this.nodeName] = node.name
it[this.validator] = EntityID(validator, SteamwarUserTable)
it[this.startTime] = startTime.toInstant()
it[this.endTime] = endTime.toInstant()
it[this.declineReason] = reason
it[this.seen] = seen
it[this.nodeType] = node.schemtype.toDB().substring(1)
}
}
@JvmStatic
fun getLastDeclinedOfNode(node: Int) = useDb {
find { (CheckedSchematicTable.nodeId eq node) and (CheckedSchematicTable.declineReason neq "Prüfvorgang abgebrochen") }.orderBy(CheckedSchematicTable.endTime to SortOrder.DESC).toList()
}
@JvmStatic
fun previousChecks(node: SchematicNode) = useDb {
find { (CheckedSchematicTable.nodeId eq node.id) and (CheckedSchematicTable.declineReason neq "") and (CheckedSchematicTable.declineReason neq "Prüfvorgang abgebrochen") }.orderBy(CheckedSchematicTable.endTime to SortOrder.DESC).toList()
}
@JvmStatic
fun getUnseen(owner: SteamwarUser) = useDb {
find { (CheckedSchematicTable.nodeOwner eq owner.id) and (CheckedSchematicTable.seen eq false) }.orderBy(CheckedSchematicTable.endTime to SortOrder.DESC).toList()
}
}
val node by CheckedSchematicTable.nodeId.transform({ it?.let { EntityID(it, SchematicNodeTable) } }, { it?.value })
val schemOwner by CheckedSchematicTable.nodeOwner.transform({ EntityID(it, SteamwarUserTable) }, { it.value })
val nodeName by CheckedSchematicTable.nodeName
val schemName get() = nodeName.value
val validator by CheckedSchematicTable.validator.transform({ EntityID(it, SteamwarUserTable) }, { it.value })
val startTimeId by CheckedSchematicTable.startTime
val startTime get() = Timestamp.from(startTimeId.value)
val endTime by CheckedSchematicTable.endTime.transform({ it.toInstant() }, { Timestamp.from(it) })
val declineReason by CheckedSchematicTable.declineReason
private var wasSeen by CheckedSchematicTable.seen
var seen: Boolean
get() = wasSeen
set(value) = useDb { wasSeen = value }
val nodeType by CheckedSchematicTable.nodeType
}

View File

@@ -1,125 +0,0 @@
/*
* 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.sql;
import de.steamwar.sql.internal.Field;
import de.steamwar.sql.internal.SelectStatement;
import de.steamwar.sql.internal.Statement;
import de.steamwar.sql.internal.Table;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.sql.Timestamp;
import java.time.Instant;
import java.util.List;
@AllArgsConstructor
public class Event {
static {
SchematicType.Normal.name(); // Ensure SchematicType is loaded.
}
private static final Table<Event> table = new Table<>(Event.class);
private static final SelectStatement<Event> byCurrent = new SelectStatement<>(table, "SELECT * FROM Event WHERE Start < now() AND End > now()");
private static final SelectStatement<Event> byId = table.select(Table.PRIMARY);
private static final SelectStatement<Event> byName = table.select("eventName");
private static final SelectStatement<Event> byComing = new SelectStatement<>(table, "SELECT * FROM Event WHERE Start > now()");
private static final SelectStatement<Event> all = new SelectStatement<>(table, "SELECT * FROM Event");
private static final Statement create = table.insertFields(true, "eventName", "deadline", "start", "end", "maximumTeamMembers", "publicSchemsOnly");
private static final Statement update = table.update(Table.PRIMARY, "eventName", "deadline", "start", "end", "schemType", "maximumTeamMembers", "publicSchemsOnly");
private static final Statement delete = table.delete(Table.PRIMARY);
private static Event current = null;
public static Event get(){
if(current != null && current.now())
return current;
current = byCurrent.select();
return current;
}
public static List<Event> getAll(){
return all.listSelect();
}
public static Event create(String eventName, Timestamp start, Timestamp end){
return get(create.insertGetKey(eventName, start, start, end, 5, false));
}
public static Event get(int eventID){
return byId.select(eventID);
}
public static Event get(String eventName) {
return byName.select(eventName);
}
public static List<Event> getComing() {
return byComing.listSelect();
}
@Getter
@Field(keys = {Table.PRIMARY}, autoincrement = true)
private final int eventID;
@Getter
@Field(keys = {"eventName"})
private final String eventName;
@Getter
@Field
private final Timestamp deadline;
@Getter
@Field
private final Timestamp start;
@Getter
@Field
private final Timestamp end;
@Getter
@Field
private final int maximumTeamMembers;
@Field(nullable = true)
private final SchematicType schemType;
@Field
private final boolean publicSchemsOnly;
public boolean publicSchemsOnly() {
return publicSchemsOnly;
}
public SchematicType getSchematicType() {
return schemType;
}
private boolean now() {
Instant now = Instant.now();
return now.isAfter(start.toInstant()) && now.isBefore(end.toInstant());
}
public void update(String eventName, Timestamp deadline, Timestamp start, Timestamp end, SchematicType schemType, int maximumTeamMembers, boolean publicSchemsOnly) {
update.update(eventName, deadline, start, end, schemType, maximumTeamMembers, publicSchemsOnly, eventID);
}
public void delete() {
delete.update(eventID);
}
}

View File

@@ -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.sql
import de.steamwar.sql.internal.useDb
import org.jetbrains.exposed.v1.core.and
import org.jetbrains.exposed.v1.core.dao.id.EntityID
import org.jetbrains.exposed.v1.core.dao.id.IntIdTable
import org.jetbrains.exposed.v1.core.eq
import org.jetbrains.exposed.v1.core.greater
import org.jetbrains.exposed.v1.core.lessEq
import org.jetbrains.exposed.v1.dao.IntEntity
import org.jetbrains.exposed.v1.dao.IntEntityClass
import org.jetbrains.exposed.v1.javatime.timestamp
import org.jetbrains.exposed.v1.jdbc.insertAndGetId
import java.sql.Timestamp
import java.time.Instant
object EventTable : IntIdTable("Event", "EventId") {
val name = varchar("EventName", 100).uniqueIndex()
val deadline = timestamp("Deadline")
val start = timestamp("Start")
val end = timestamp("End")
val maxPlayers = integer("MaximumTeamMembers")
val schemType = varchar("SchemType", 16).nullable()
val publicsOnly = bool("PublicSchemsOnly")
}
class Event(id: EntityID<Int>) : IntEntity(id) {
companion object : IntEntityClass<Event>(EventTable) {
private var current: Event? = null
@JvmStatic
fun get(): Event? = if (current?.now() == true) {
current
} else useDb {
find { EventTable.start.lessEq(Instant.now()) and EventTable.end.greater(Instant.now()) }.firstOrNull()
?.also { current == it }
}
@JvmStatic
fun getAll() = useDb { all().toList() }
@JvmStatic
fun create(name: String, start: Timestamp, end: Timestamp) = useDb {
EventTable.insertAndGetId {
it[this.name] = name
it[this.deadline] = start.toInstant()
it[this.start] = start.toInstant()
it[this.end] = end.toInstant()
it[this.maxPlayers] = 5
it[this.publicsOnly] = false
}.let { get(it) }
}
@JvmStatic
fun byId(id: Int) = useDb { findById(id) }
@JvmStatic
fun get(name: String) = useDb { find { EventTable.name eq name }.firstOrNull() }
@JvmStatic
fun getComing() = useDb { find { EventTable.start greater Instant.now() }.toList() }
}
val eventID by EventTable.id.transform({ EntityID(it, EventTable) }, { it.value })
var eventName by EventTable.name
private set
var deadline: Timestamp by EventTable.deadline.transform({ it.toInstant() }, { Timestamp.from(it) })
private set
var start: Timestamp by EventTable.start.transform({ it.toInstant() }, { Timestamp.from(it) })
private set
var end: Timestamp by EventTable.end.transform({ it.toInstant() }, { Timestamp.from(it) })
private set
var maximumTeamMembers by EventTable.maxPlayers
private set
var schematicType by EventTable.schemType.transform({ it?.toDB() }, { it?.let { SchematicType.fromDB(it) } })
private set
var publicSchemsOnly by EventTable.publicsOnly
private set
fun publicSchemsOnly() = publicSchemsOnly
fun now() = Instant.now().let { it.isAfter(start.toInstant()) && it.isBefore(end.toInstant()) }
fun update(
name: String,
deadline: Timestamp,
start: Timestamp,
end: Timestamp,
schematicType: SchematicType?,
maxPlayers: Int,
publicSchemsOnly: Boolean
) = useDb {
this@Event.eventName = name
this@Event.deadline = deadline
this@Event.start = start
this@Event.end = end
this@Event.maximumTeamMembers = maxPlayers
this@Event.schematicType = schematicType
this@Event.publicSchemsOnly = publicSchemsOnly
}
override fun delete() = useDb { super.delete() }
}

View File

@@ -1,216 +0,0 @@
/*
* 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.sql;
import de.steamwar.sql.internal.Field;
import de.steamwar.sql.internal.SelectStatement;
import de.steamwar.sql.internal.Statement;
import de.steamwar.sql.internal.Table;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import java.sql.Timestamp;
import java.util.*;
import static java.time.temporal.ChronoUnit.SECONDS;
@AllArgsConstructor
public class EventFight implements Comparable<EventFight> {
private static final Table<EventFight> table = new Table<>(EventFight.class);
private static final SelectStatement<EventFight> byId = table.select(Table.PRIMARY);
private static final SelectStatement<EventFight> byGroup = new SelectStatement<EventFight>(table, "SELECT * FROM EventFight WHERE GroupID = ? ORDER BY StartTime ASC");
private static final SelectStatement<EventFight> byGroupLast = new SelectStatement<EventFight>(table, "SELECT * FROM EventFight WHERE GroupID = ? ORDER BY StartTime DESC LIMIT 1");
private static final SelectStatement<EventFight> allComing = new SelectStatement<>(table, "SELECT * FROM EventFight WHERE StartTime > now() ORDER BY StartTime ASC");
private static final SelectStatement<EventFight> event = new SelectStatement<>(table, "SELECT * FROM EventFight WHERE EventID = ? ORDER BY StartTime ASC");
private static final SelectStatement<EventFight> activeFights = new SelectStatement<>(table, "SELECT * FROM EventFight WHERE EventID IN (SELECT EventID FROM Event WHERE Start < now() and End > now()) AND Fight IS NULL AND StartTime < now()");
private static final Statement reschedule = table.update(Table.PRIMARY, "StartTime");
private static final Statement setResult = table.update(Table.PRIMARY, "Ergebnis");
private static final Statement setFight = table.update(Table.PRIMARY, "Fight");
private static final Statement create = table.insertFields(true, "eventID", "startTime", "spielmodus", "map", "teamBlue", "teamRed", "spectatePort");
private static final Statement update = table.update(Table.PRIMARY, "startTime", "spielModus", "map", "teamBlue", "teamRed", "spectatePort");
private static final Statement setGroup = table.update(Table.PRIMARY, "GroupID");
private static final Statement delete = table.delete(Table.PRIMARY);
@Getter
private static final Queue<EventFight> fights = new PriorityQueue<>();
public static EventFight get(int fightID) {
return byId.select(fightID);
}
public static List<EventFight> get(EventGroup group) {
return byGroup.listSelect(group.getId());
}
public static Optional<EventFight> getLast(EventGroup group) {
return Optional.ofNullable(byGroupLast.select(group.getId()));
}
public static void loadAllComingFights() {
fights.clear();
fights.addAll(allComing.listSelect());
}
public static List<EventFight> getEvent(int eventID) {
return event.listSelect(eventID);
}
private static List<EventFight> activeFightsCache = null;
public static void clearActiveFightsCache() {
activeFightsCache = null;
}
public static List<EventFight> getActiveFights() {
if (activeFightsCache == null) {
activeFightsCache = activeFights.listSelect();
}
return activeFightsCache;
}
public static EventFight create(int event, Timestamp from, String spielmodus, String map, int blueTeam, int redTeam, Integer spectatePort) {
return get(create.insertGetKey(event, from, spielmodus, map, blueTeam, redTeam, spectatePort));
}
@Getter
@Field
private final int eventID;
@Getter
@Field(keys = {Table.PRIMARY}, autoincrement = true)
private final int fightID;
@Getter
@Setter
@Field(nullable = true, def = "null")
private Integer groupId;
@Getter
@Setter
@Field
private Timestamp startTime;
@Getter
@Setter
@Field
private String spielmodus;
@Getter
@Setter
@Field
private String map;
@Getter
@Setter
@Field
private int teamBlue;
@Getter
@Setter
@Field
private int teamRed;
@Getter
@Setter
@Field(nullable = true)
private Integer spectatePort;
@Getter
@Setter
@Field(def = "1")
private int bestOf;
@Getter
@Field(def = "0")
private int ergebnis;
@Field(nullable = true)
private int fight;
public Optional<EventGroup> getGroup() {
return Optional.ofNullable(groupId).flatMap(EventGroup::get);
}
public Optional<Team> getWinner() {
if(ergebnis == 0)
return Optional.empty();
return Optional.ofNullable(ergebnis == 1 ? Team.get(teamBlue) : Team.get(teamRed));
}
public Optional<Team> getLosser() {
if(ergebnis == 0)
return Optional.empty();
return Optional.ofNullable(ergebnis == 1 ? Team.get(teamRed) : Team.get(teamBlue));
}
public List<EventRelation> getDependents() {
return EventRelation.getFightRelations(this);
}
public void setErgebnis(int winner) {
this.ergebnis = winner;
setResult.update(winner, fightID);
}
public void setFight(int fight) {
//Fight.FightID, not EventFight.FightID
this.fight = fight;
setFight.update(fight, fightID);
}
public void setGroup(Integer group) {
setGroup.update(group, fightID);
this.groupId = group;
}
public boolean hasFinished() {
return fight != 0 || ergebnis != 0;
}
public void reschedule() {
startTime = Timestamp.from(new Date().toInstant().plus(30, SECONDS));
reschedule.update(startTime, fightID);
}
@Override
public int hashCode(){
return fightID;
}
@Override
public boolean equals(Object o){
if(o == null)
return false;
if(!(o instanceof EventFight))
return false;
return fightID == ((EventFight) o).fightID;
}
@Override
public int compareTo(EventFight o) {
return startTime.compareTo(o.startTime);
}
public void update(Timestamp startTime, String spielmodus, String map, int teamBlue, int teamRed, Integer spectatePort) {
update.update(startTime, spielmodus, map, teamBlue, teamRed, spectatePort, fightID);
this.startTime = startTime;
this.spielmodus = spielmodus;
this.map = map;
this.teamBlue = teamBlue;
this.teamRed = teamRed;
this.spectatePort = spectatePort;
}
public void delete() {
delete.update(fightID);
}
}

View File

@@ -0,0 +1,188 @@
/*
* 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.sql
import de.steamwar.sql.internal.useDb
import org.jetbrains.exposed.v1.core.*
import org.jetbrains.exposed.v1.core.dao.id.EntityID
import org.jetbrains.exposed.v1.core.dao.id.IntIdTable
import org.jetbrains.exposed.v1.dao.IntEntity
import org.jetbrains.exposed.v1.dao.IntEntityClass
import org.jetbrains.exposed.v1.javatime.timestamp
import org.jetbrains.exposed.v1.jdbc.insertAndGetId
import org.jetbrains.exposed.v1.jdbc.select
import java.sql.Timestamp
import java.time.Instant
import java.util.*
object EventFightTable : IntIdTable("EventFight", "FightID") {
val eventId = reference("EventID", EventTable)
val startTime = timestamp("StartTime")
val gamemode = text("Spielmodus")
val map = text("Map")
val groupId = optReference("GroupId", EventGroupTable)
val teamBlue = reference("TeamBlue", TeamTable)
val teamRed = reference("TeamRed", TeamTable)
val spectatePort = integer("SpectatePort").nullable()
val bestOf = integer("BestOf")
val ergebnis = integer("Ergebnis")
val fight = optReference("Fight", FightTable)
}
class EventFight(id: EntityID<Int>) : IntEntity(id), Comparable<EventFight> {
companion object : IntEntityClass<EventFight>(EventFightTable) {
val fights: Queue<EventFight> = PriorityQueue()
@JvmStatic get
@JvmStatic
fun byId(fightId: Int) = useDb { findById(fightId) }
@JvmStatic
fun byId(group: EventGroup) = useDb {
find { EventFightTable.groupId eq group.id }.orderBy(EventFightTable.startTime to SortOrder.DESC).toList()
}
@JvmStatic
fun getLast(group: EventGroup) = useDb {
Optional.ofNullable(
find { EventFightTable.groupId eq group.id }.orderBy(EventFightTable.startTime to SortOrder.DESC)
.firstOrNull()
)
}
@JvmStatic
fun loadAllComingFights() = useDb {
fights.clear()
fights.addAll(find { EventFightTable.startTime greaterEq Instant.now() }.orderBy(EventFightTable.startTime to SortOrder.ASC))
}
@JvmStatic
fun getEvent(eventId: Int) = useDb {
find { EventFightTable.eventId eq eventId }.orderBy(EventFightTable.startTime to SortOrder.ASC).toList()
}
private var activeFightsCache: List<EventFight>? = null
@JvmStatic
fun clearActiveFightsCache() {
activeFightsCache = null
}
@JvmStatic
fun getActiveFights(): List<EventFight> {
if (activeFightsCache == null) {
activeFightsCache = useDb {
find {
EventFightTable.fight.isNull() and (EventFightTable.startTime less Instant.now()) and (EventFightTable.eventId.inSubQuery(
EventTable.select(
EventTable.id
)
.where { (EventTable.start less Instant.now()) and (EventTable.end greater Instant.now()) }))
}.orderBy(EventFightTable.startTime to SortOrder.ASC).toList()
}
}
return activeFightsCache!!
}
@JvmStatic
fun create(
event: Int,
from: Timestamp,
spielmodus: String,
map: String,
blueTeam: Int,
redTeam: Int,
spectatePort: Int?
) = useDb {
get(
EventFightTable.insertAndGetId {
it[eventId] = EntityID(event, EventTable)
it[startTime] = from.toInstant()
it[gamemode] = spielmodus
it[EventFightTable.map] = map
it[teamBlue] = EntityID(blueTeam, TeamTable)
it[teamRed] = EntityID(redTeam, TeamTable)
it[EventFightTable.spectatePort] = spectatePort
}
)
}
}
val fightID by EventFightTable.id.transform({ EntityID(it, EventFightTable) }, { it.value })
var teamBlue by EventFightTable.teamBlue.transform({ EntityID(it, TeamTable) }, { it.value })
var teamRed by EventFightTable.teamRed.transform({ EntityID(it, TeamTable) }, { it.value })
private var fightErgebnis by EventFightTable.ergebnis
var ergebnis: Int
get() = fightErgebnis
set(value) = useDb {
fightErgebnis = value
}
var eventID by EventFightTable.eventId.transform({ EntityID(it, EventTable) }, { it.value })
var startTime by EventFightTable.startTime.transform({ it.toInstant() }, { Timestamp.from(it) })
var spielmodus by EventFightTable.gamemode
var map by EventFightTable.map
var groupId by EventFightTable.groupId
val group by lazy { useDb { Optional.ofNullable(groupId).map { EventGroup[it] } } }
var spectatePort by EventFightTable.spectatePort
private var fightStat by EventFightTable.fight.transform({ it?.let { EntityID(it, EventFightTable) } }, { it?.value })
var fight: Int?
get() = fightStat
set(value) = useDb {
fightStat = value
}
val dependents by lazy { useDb { EventRelation.getFightRelations(this@EventFight) } }
val winner: Team?
get() = if (ergebnis == 1) Team[teamBlue] else if (ergebnis == 2) Team[teamRed] else null
val losser: Team?
get() = if (ergebnis == 1) Team[teamRed] else if (ergebnis == 2) Team[teamBlue] else null
fun setGroup(group: Int?) = useDb { groupId = group?.let { EntityID(it, EventGroupTable) } }
fun hasFinished() = fight != null || ergebnis != 0
fun reschedule() = useDb {
startTime = Timestamp.from(Instant.now().plusSeconds(30))
}
override fun hashCode() = fightID
override fun equals(other: Any?) = other is EventFight && other.fightID == fightID
override fun compareTo(other: EventFight): Int = startTime.compareTo(other.startTime)
fun update(
startTime: Timestamp,
spielmodus: String,
map: String,
teamBlue: Int,
teamRed: Int,
spectatePort: Int?
) = useDb {
this@EventFight.startTime = startTime
this@EventFight.spielmodus = spielmodus
this@EventFight.map = map
this@EventFight.teamBlue = teamBlue
this@EventFight.teamRed = teamRed
this@EventFight.spectatePort = spectatePort
}
override fun delete() = useDb {
super.delete()
}
}

View File

@@ -1,173 +0,0 @@
/*
* 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.sql;
import de.steamwar.sql.internal.*;
import lombok.Getter;
import lombok.Setter;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Getter
@Setter
public class EventGroup {
static {
SqlTypeMapper.ordinalEnumMapper(EventGroupType.class);
}
private static final Table<EventGroup> table = new Table<>(EventGroup.class);
private static final SelectStatement<EventGroup> get = table.select(Table.PRIMARY);
private static final SelectStatement<EventGroup> byEvent = new SelectStatement<>(table, "SELECT * FROM EventGroup WHERE EventID = ?");
private static final Statement insert = table.insertFields(true, "EventID", "Name", "Type");
private static final Statement update = table.update(Table.PRIMARY, "Name", "Type", "PointsPerWin", "PointsPerLoss", "PointsPerDraw");
private static final Statement delete = table.delete(Table.PRIMARY);
public static List<EventGroup> get(Event eventID) {
return byEvent.listSelect(eventID.getEventID());
}
public static EventGroup create(Event event, String name, EventGroupType type) {
int key = insert.insertGetKey(event.getEventID(), name, type);
return EventGroup.get(key).get();
}
public static Optional<EventGroup> get(int id) {
return Optional.ofNullable(get.select(id));
}
@Field(keys = Table.PRIMARY)
private final int id;
@Field(keys = "EVENT_NAME")
private int eventID;
@Field(keys = "EVENT_NAME")
private String name;
@Field
private EventGroupType type;
@Field
private int pointsPerWin;
@Field
private int pointsPerLoss;
@Field
private int pointsPerDraw;
public EventGroup(int id, int eventID, String name, EventGroupType type, int pointsPerWin, int pointsPerLoss, int pointsPerDraw) {
this.id = id;
this.eventID = eventID;
this.name = name;
this.type = type;
this.pointsPerWin = pointsPerWin;
this.pointsPerLoss = pointsPerLoss;
this.pointsPerDraw = pointsPerDraw;
}
private Map<Team, Integer> points;
public List<EventFight> getFights() {
return EventFight.get(this);
}
public Set<Integer> getTeamsId() {
return getFights().stream().flatMap(fight -> Stream.of(fight.getTeamBlue(), fight.getTeamRed()))
.collect(Collectors.toSet());
}
public Set<Team> getTeams() {
return getTeamsId().stream().map(Team::get).collect(Collectors.toSet());
}
public Optional<EventFight> getLastFight() {
return EventFight.getLast(this);
}
public List<EventRelation> getDependents() {
return EventRelation.getGroupRelations(this);
}
public Map<Team, Integer> calculatePoints() {
if (points == null) {
Map<Integer, Integer> p = getTeamsId().stream().collect(Collectors.toMap(team -> team, team -> 0));
for (EventFight fight : getFights()) {
int blueTeamAdd = 0;
int redTeamAdd = 0;
if (!fight.hasFinished()) {
continue;
}
switch (fight.getErgebnis()) {
case 1:
blueTeamAdd += pointsPerWin;
redTeamAdd += pointsPerLoss;
break;
case 2:
blueTeamAdd += pointsPerLoss;
redTeamAdd += pointsPerWin;
break;
case 0:
if (fight.getFightID() != 0) {
blueTeamAdd += pointsPerDraw;
redTeamAdd += pointsPerDraw;
}
break;
}
p.put(fight.getTeamBlue(), p.get(fight.getTeamBlue()) + blueTeamAdd);
p.put(fight.getTeamRed(), p.get(fight.getTeamRed()) + redTeamAdd);
}
points = p.entrySet().stream().collect(Collectors.toMap(integerIntegerEntry -> Team.get(integerIntegerEntry.getKey()), Map.Entry::getValue));
}
return points;
}
public void update(String name, EventGroupType type, int pointsPerWin, int pointsPerLoss, int pointsPerDraw) {
update.update(name, type, pointsPerWin, pointsPerLoss, pointsPerDraw, id);
this.name = name;
this.type = type;
this.pointsPerWin = pointsPerWin;
this.pointsPerLoss = pointsPerLoss;
this.pointsPerDraw = pointsPerDraw;
}
public boolean needsTieBreak() {
return calculatePoints().values().stream().sorted().limit(2).distinct().count() < 2;
}
public void delete() {
delete.update(id);
}
public static enum EventGroupType {
GROUP_STAGE,
ELIMINATION_STAGE
}
}

View File

@@ -0,0 +1,153 @@
/*
* 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.sql
import de.steamwar.sql.internal.useDb
import org.jetbrains.exposed.v1.core.dao.id.EntityID
import org.jetbrains.exposed.v1.core.dao.id.IntIdTable
import org.jetbrains.exposed.v1.core.eq
import org.jetbrains.exposed.v1.dao.IntEntity
import org.jetbrains.exposed.v1.dao.IntEntityClass
import java.util.*
object EventGroupTable : IntIdTable("EventGroup", "Id") {
val event = reference("EventID", EventTable)
val name = varchar("Name", 64)
val type = enumeration("Type", EventGroup.EventGroupType::class)
val pointsPerWin = integer("PointsPerWin").default(3)
val pointsPerLoss = integer("PointsPerLoss").default(0)
val pointsPerDraw = integer("PointsPerDraw").default(1)
}
class EventGroup(id: EntityID<Int>) : IntEntity(id) {
companion object : IntEntityClass<EventGroup>(EventGroupTable) {
@JvmStatic
fun get(event: Event) = useDb { find { EventGroupTable.event eq event.id }.toList() }
@JvmStatic
fun byId(groupId: Int) = useDb { Optional.ofNullable(findById(groupId)) }
@JvmStatic
fun create(event: Event, name: String, type: EventGroupType) = useDb {
new {
this.eventID = event.id.value
this.groupName = name
this.groupType = type
}
}
}
var eventID by EventGroupTable.event.transform({ EntityID(it, EventTable) }, { it.value })
private set
private var groupName by EventGroupTable.name
private var groupType by EventGroupTable.type
private var groupPointsPerWin by EventGroupTable.pointsPerWin
private var groupPointsPerLoss by EventGroupTable.pointsPerLoss
private var groupPointsPerDraw by EventGroupTable.pointsPerDraw
val fights by lazy { useDb { EventFight.find { EventFightTable.groupId eq id }.toList() } }
val teamsId by lazy { fights.flatMap { listOf(it.teamBlue, it.teamRed) }.toSet() }
var name: String
get() = groupName
set(value) {
groupName = value
}
var type: EventGroupType
get() = groupType
set(value) {
groupType = value
}
var pointsPerWin: Int
get() = groupPointsPerWin
set(value) {
groupPointsPerWin = value
}
var pointsPerLoss: Int
get() = groupPointsPerLoss
set(value) {
groupPointsPerLoss = value
}
var pointsPerDraw: Int
get() = groupPointsPerDraw
set(value) {
groupPointsPerDraw = value
}
val dependents by lazy { EventRelation.getGroupRelations(this) }
val lastFight by lazy { Optional.ofNullable(fights.maxByOrNull { it.startTime }) }
fun getId() = id.value
private var points: Map<Team, Int>? = null
fun calculatePoints(): Map<Team, Int> {
if (points == null) {
val p: MutableMap<Int, Int> = teamsId.associateWith { 0 }.toMutableMap()
for (fight in fights) {
var blueTeamAdd = 0
var redTeamAdd = 0
if (!fight.hasFinished()) {
continue
}
when (fight.ergebnis) {
1 -> {
blueTeamAdd += pointsPerWin
redTeamAdd += pointsPerLoss
}
2 -> {
blueTeamAdd += pointsPerLoss
redTeamAdd += pointsPerWin
}
0 -> if (fight.fight != null) {
blueTeamAdd += pointsPerDraw
redTeamAdd += pointsPerDraw
}
}
p[fight.teamBlue] = p[fight.teamBlue]?.plus(blueTeamAdd) ?: blueTeamAdd
p[fight.teamRed] = p[fight.teamRed]?.plus(redTeamAdd) ?: redTeamAdd
}
return p.mapKeys { Team.byId(it.key) }.also { points = it }
} else {
return points!!
}
}
fun needsTieBreak() = calculatePoints().values.let { it.size == it.toSet().size }
fun update(name: String, type: EventGroupType, pointsPerWin: Int, pointsPerLoss: Int, pointsPerDraw: Int) = useDb {
this@EventGroup.name = name
this@EventGroup.type = type
this@EventGroup.pointsPerWin = pointsPerWin
this@EventGroup.pointsPerLoss = pointsPerLoss
this@EventGroup.pointsPerDraw = pointsPerDraw
}
override fun delete() = useDb { super.delete() }
enum class EventGroupType {
GROUP_STAGE,
ELIMINATION_STAGE
}
}

View File

@@ -1,192 +0,0 @@
/*
* 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.sql;
import de.steamwar.sql.internal.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@AllArgsConstructor
@Getter
@Setter
public class EventRelation {
static {
SqlTypeMapper.ordinalEnumMapper(FightTeam.class);
SqlTypeMapper.ordinalEnumMapper(FromType.class);
}
private static final Table<EventRelation> table = new Table<>(EventRelation.class);
private static final SelectStatement<EventRelation> get = new SelectStatement<>(table, "SELECT * FROM EventRelation WHERE FromType = ? AND FromId = ?");
private static final SelectStatement<EventRelation> byId = new SelectStatement<>(table, "SELECT * FROM EventRelation WHERE id = ?");
private static final SelectStatement<EventRelation> byEvent = new SelectStatement<>(table, "SELECT ER.* FROM EventRelation ER JOIN EventFight EF ON EF.fightId = ER.fightId WHERE EF.EventID = ?");
private static final Statement insert = table.insertFields(true, "fightId", "fightTeam", "fromType", "fromId", "fromPlace");
private static final Statement update = table.update(Table.PRIMARY, "fromType", "fromId", "fromPlace");
private static final Statement updateTeam = table.update(Table.PRIMARY, "fightTeam");
private static final Statement delete = table.delete(Table.PRIMARY);
public static List<EventRelation> get(Event event) {
return byEvent.listSelect(event.getEventID());
}
public static EventRelation get(int id) {
return byId.select(id);
}
public static List<EventRelation> getFightRelations(EventFight fight) {
return get.listSelect(FromType.FIGHT, fight.getFightID());
}
public static List<EventRelation> getGroupRelations(EventGroup group) {
return get.listSelect(FromType.GROUP, group.getId());
}
public static EventRelation create(EventFight fight, FightTeam fightTeam, FromType fromType, int fromId, int fromPlace) {
int id = insert.insertGetKey(fight.getFightID(), fightTeam, fromType, fromId, fromPlace);
return get(id);
}
@Field(keys = Table.PRIMARY)
private final int id;
@Field
private int fightId;
@Field
private FightTeam fightTeam;
@Field
private FromType fromType;
@Field
private int fromId;
@Field
private int fromPlace;
public EventFight getFight() {
return EventFight.get(fightId);
}
public Optional<EventFight> getFromFight() {
if(fromType == FromType.FIGHT) {
return Optional.of(EventFight.get(fromId));
} else {
return Optional.empty();
}
}
public Optional<EventGroup> getFromGroup() {
if(fromType == FromType.GROUP) {
return EventGroup.get(fromId);
} else {
return Optional.empty();
}
}
public void delete() {
delete.update(id);
}
public void setUpdateTeam(FightTeam team) {
updateTeam.update(id, team);
this.fightTeam = team;
}
public void setFromFight(EventFight fight, int place) {
setFrom(fight.getFightID(), place, FromType.FIGHT);
}
public void setFromGroup(EventGroup group, int place) {
setFrom(group.getId(), place, FromType.GROUP);
}
private void setFrom(int fightId, int place, FromType type) {
update.update(type, fightId, place, id);
this.fromType = type;
this.fromId = fightId;
this.fromPlace = place;
}
public Optional<Team> getAdvancingTeam() {
if (fromType == FromType.FIGHT) {
if (fromPlace == 0) {
return getFromFight().flatMap(EventFight::getWinner);
} else {
return getFromFight().flatMap(EventFight::getLosser);
}
} else if (fromType == FromType.GROUP) {
return getFromGroup().map(EventGroup::calculatePoints)
.flatMap(points -> points.entrySet().stream()
.sorted(Map.Entry.<Team, Integer>comparingByValue().reversed())
.skip(fromPlace)
.findFirst()
.map(Map.Entry::getKey));
} else {
return Optional.empty();
}
}
public boolean apply() {
Optional<Integer> team = getAdvancingTeam().map(Team::getTeamId);
if(!team.isPresent())
return false;
EventFight fight = getFight();
if(fightTeam == FightTeam.RED) {
fight.update(
fight.getStartTime(),
fight.getSpielmodus(),
fight.getMap(),
fight.getTeamBlue(),
team.get(),
fight.getSpectatePort()
);
} else {
fight.update(
fight.getStartTime(),
fight.getSpielmodus(),
fight.getMap(),
team.get(),
fight.getTeamRed(),
fight.getSpectatePort()
);
}
return true;
}
public static enum FightTeam {
BLUE,
RED
}
public static enum FromType {
FIGHT,
GROUP
}
}

View File

@@ -0,0 +1,149 @@
/*
* 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.sql
import de.steamwar.sql.internal.useDb
import org.jetbrains.exposed.v1.core.and
import org.jetbrains.exposed.v1.core.dao.id.EntityID
import org.jetbrains.exposed.v1.core.dao.id.IntIdTable
import org.jetbrains.exposed.v1.core.eq
import org.jetbrains.exposed.v1.dao.IntEntity
import org.jetbrains.exposed.v1.dao.IntEntityClass
import org.jetbrains.exposed.v1.jdbc.select
object EventRelationTable : IntIdTable("EventRelation") {
val fightId = reference("FightId", EventFightTable)
val fightTeam = enumeration("FightTeam", EventRelation.FightTeam::class)
val fromType = enumeration("FromType", EventRelation.FromType::class)
val fromId = integer("FromId")
val fromPlace = integer("FromPlace")
}
class EventRelation(id: EntityID<Int>) : IntEntity(id) {
companion object : IntEntityClass<EventRelation>(EventRelationTable) {
@JvmStatic
fun get(event: Event) = useDb {
EventRelationTable.innerJoin(EventFightTable)
.select(EventRelationTable.columns)
.where { EventFightTable.eventId eq event.id }
.map { wrapRow(it) }
}
@JvmStatic
fun byId(id: Int) = useDb { findById(id) }
@JvmStatic
fun getFightRelations(fight: EventFight) =
useDb { find { (EventRelationTable.fromId eq fight.id.value) and (EventRelationTable.fromType eq FromType.FIGHT) } }
@JvmStatic
fun getGroupRelations(group: EventGroup) =
useDb { find { (EventRelationTable.fromId eq group.id.value) and (EventRelationTable.fromType eq FromType.GROUP) } }
@JvmStatic
fun create(fight: EventFight, fightTeam: FightTeam, fromType: FromType, fromId: Int, fromPlace: Int) = useDb {
new {
this.fightEntityId = fight.id
this.fightTeam = fightTeam
this.fromType = fromType
this.fromId = fromId
this.fromPlace = fromPlace
}
}
}
var fightEntityId by EventRelationTable.fightId
var fightId: Int
get() = fightEntityId.value
set(value) = useDb { fightEntityId = EntityID(value, EventFightTable) }
val fight by lazy { useDb { EventFight[fightEntityId] } }
var fightTeam by EventRelationTable.fightTeam
private set
var fromType by EventRelationTable.fromType
private set
var fromId by EventRelationTable.fromId
private set
var fromFightId: Int?
get() = if (fromType == FromType.FIGHT) fromId else null
set(value) = useDb {
fromType = FromType.FIGHT
fromId = value!!
}
val fromFight: EventFight?
get() = fromFightId?.let { useDb { EventFight[it] } }
var fromGroupId: Int?
get() = if (fromType == FromType.GROUP) fromId else null
set(value) = useDb {
fromType = FromType.GROUP
fromId = value!!
}
val fromGroup: EventGroup?
get() = fromGroupId?.let { useDb { EventGroup[it] } }
var fromPlace by EventRelationTable.fromPlace
private set
fun getId() = id.value
fun setUpdateTeam(team: FightTeam) = useDb {
fightTeam = team
}
fun setFromFight(fight: EventFight, place: Int) = useDb {
fromType = FromType.FIGHT
fromId = fight.id.value
fromPlace = place
}
fun setFromGroup(group: EventGroup, place: Int) = useDb {
fromType = FromType.GROUP
fromId = group.id.value
fromPlace = place
}
fun getAdvancingTeam(): Team? = when(fromType) {
FromType.FIGHT -> if (fromPlace == 0) fromFight?.winner else fromFight?.losser
FromType.GROUP -> fromGroup?.calculatePoints()?.toList()?.sortedBy { (_, v) -> v }?.reversed()?.elementAt(fromPlace)?.first
}
fun apply(): Boolean {
val team = getAdvancingTeam() ?: return false
useDb {
when(fightTeam) {
FightTeam.BLUE -> fight.teamBlue = team.teamId
FightTeam.RED -> fight.teamRed = team.teamId
}
}
return true
}
override fun delete() = useDb {
super.delete()
}
enum class FightTeam {
BLUE, RED
}
enum class FromType {
FIGHT, GROUP
}
}

View File

@@ -1,134 +0,0 @@
/*
* 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.sql;
import de.steamwar.sql.internal.Field;
import de.steamwar.sql.internal.SelectStatement;
import de.steamwar.sql.internal.Statement;
import de.steamwar.sql.internal.Table;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@AllArgsConstructor
public class Fight {
private static final Table<Fight> table = new Table<>(Fight.class);
private static final SelectStatement<Fight> getPage = new SelectStatement<>(table, "SELECT f.*, (b.NodeId IS NULL OR b.Config & 2) AND (r.NodeId IS NULL OR r.Config & 2) AS ReplayAllowed FROM Fight f LEFT OUTER JOIN SchematicNode b ON f.BlueSchem = b.NodeId LEFT OUTER JOIN SchematicNode r ON f.RedSchem = r.NodeId ORDER BY FightID DESC LIMIT ?, ?");
private static final SelectStatement<Fight> getById = new SelectStatement<>(table, "SELECT f.*, (b.NodeId IS NULL OR b.Config & 2) AND (r.NodeId IS NULL OR r.Config & 2) AS ReplayAllowed FROM Fight f LEFT OUTER JOIN SchematicNode b ON f.BlueSchem = b.NodeId LEFT OUTER JOIN SchematicNode r ON f.RedSchem = r.NodeId WHERE FightId = ?");
private static final Statement insert = table.insertFields(true, "GameMode", "Server", "StartTime", "Duration", "BlueLeader", "RedLeader", "BlueSchem", "RedSchem", "Win", "WinCondition");
private static final Statement updateReplayAvailable = table.update(Table.PRIMARY, "ReplayAvailable");
public static List<Fight> getPage(int page, int elementsPerPage) {
List<Fight> fights = getPage.listSelect(page * elementsPerPage, elementsPerPage);
List<FightPlayer> fightPlayers = FightPlayer.batchGet(fights.stream().map(f -> f.fightID));
for(Fight fight : fights) {
fight.initPlayers(fightPlayers);
}
SteamwarUser.batchCache(fightPlayers.stream().map(FightPlayer::getUserID).collect(Collectors.toSet()));
return fights;
}
public static Fight getById(int fightID) {
return getById.select(fightID);
}
public static int create(String gamemode, String server, Timestamp starttime, int duration, int blueleader, int redleader, Integer blueschem, Integer redschem, int win, String wincondition){
return insert.insertGetKey(gamemode, server, starttime, duration, blueleader, redleader, blueschem, redschem, win, wincondition);
}
public static void markReplayAvailable(int fightID) {
updateReplayAvailable.update(true, fightID);
}
@Getter
@Field(keys = {Table.PRIMARY}, autoincrement = true)
private final int fightID;
@Field
private final String gameMode;
@Getter
@Field
private final String server;
@Getter
@Field
private final Timestamp startTime;
@Field
private final int duration;
@Field
private final int blueLeader;
@Field
private final int redLeader;
@Field(nullable = true)
private final Integer blueSchem;
@Field(nullable = true)
private final Integer redSchem;
@Getter
@Field
private final int win;
@Field
private final String wincondition;
@Field
private final boolean replayAvailable;
@Field // Virtual field for easy select
private final boolean replayAllowed;
@Getter
private final List<FightPlayer> bluePlayers = new ArrayList<>();
@Getter
private final List<FightPlayer> redPlayers = new ArrayList<>();
public SchematicType getSchemType() {
return SchematicType.fromDB(gameMode);
}
public SteamwarUser getBlueLeader() {
return SteamwarUser.get(blueLeader);
}
public SteamwarUser getRedLeader() {
return SteamwarUser.get(redLeader);
}
public boolean replayAllowed() {
return replayExists() && replayAllowed;
}
public boolean replayExists() {
return getSchemType() != null && replayAvailable;
}
private void initPlayers(List<FightPlayer> fightPlayers) {
for(FightPlayer fp : fightPlayers) {
if(fp.getFightID() != fightID)
continue;
if(fp.getTeam() == 1)
bluePlayers.add(fp);
else
redPlayers.add(fp);
}
}
}

View File

@@ -0,0 +1,162 @@
/*
* 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.sql
import de.steamwar.sql.internal.useDb
import org.jetbrains.exposed.v1.core.IntegerColumnType
import org.jetbrains.exposed.v1.core.ReferenceOption
import org.jetbrains.exposed.v1.core.SortOrder
import org.jetbrains.exposed.v1.core.dao.id.EntityID
import org.jetbrains.exposed.v1.core.dao.id.IntIdTable
import org.jetbrains.exposed.v1.core.eq
import org.jetbrains.exposed.v1.dao.IntEntity
import org.jetbrains.exposed.v1.dao.IntEntityClass
import org.jetbrains.exposed.v1.javatime.timestamp
import org.jetbrains.exposed.v1.jdbc.insertAndGetId
import org.jetbrains.exposed.v1.jdbc.update
import java.sql.Timestamp
object FightTable : IntIdTable("Fight", "FightId") {
val gamemode = varchar("Gamemode", 30)
val server = text("Server")
val startTime = timestamp("StartTime")
val duration = integer("Duration")
val blueLeader = reference("BlueLeader", SteamwarUserTable)
val redLeader = reference("RedLeader", SteamwarUserTable)
val blueSchem = optReference("BlueSchem", SchematicNodeTable, onDelete = ReferenceOption.SET_NULL)
val redSchem = optReference("RedSchem", SchematicNodeTable, onDelete = ReferenceOption.SET_NULL)
val win = enumeration("Win", Fight.WinningTeam::class)
val winCondition = varchar("WinCondition", 100)
val replayAvailable = bool("ReplayAvailable")
}
class Fight(id: EntityID<Int>) : IntEntity(id) {
companion object : IntEntityClass<Fight>(FightTable) {
@JvmStatic
fun getById(id: Int) = useDb { get(id) }
@JvmStatic
fun create(
gamemode: String,
server: String,
starttime: Timestamp,
duration: Int,
blueleader: Int,
redleader: Int,
blueschem: Int?,
redschem: Int?,
win: Int,
wincondition: String
): Int = useDb {
FightTable.insertAndGetId {
it[FightTable.gamemode] = gamemode
it[FightTable.server] = server
it[FightTable.startTime] = starttime.toInstant()
it[FightTable.duration] = duration
it[FightTable.blueLeader] = EntityID(blueleader, SteamwarUserTable)
it[FightTable.redLeader] = EntityID(redleader, SteamwarUserTable)
it[FightTable.blueSchem] = blueschem?.let { EntityID(it, SchematicNodeTable) }
it[FightTable.redSchem] = redschem?.let { EntityID(it, SchematicNodeTable) }
it[FightTable.win] = WinningTeam.entries[win]
it[FightTable.winCondition] = wincondition
}.value
}
@JvmStatic
fun getPage(page: Int, pageSize: Int): List<Fight> = useDb {
val fights = all().orderBy(FightTable.startTime to SortOrder.DESC).limit(pageSize).offset((pageSize * page).toLong())
val fightPlayer = FightPlayer.batchGet(fights.map { it.id.value })
for (fight in fights) {
fight.initPlayers(fightPlayer)
}
SteamwarUser.batchCache(fightPlayer.map { it.userID }.toMutableSet())
fights.toList()
}
@JvmStatic
fun markReplayAvailable(id: Int) = useDb {
FightTable.update({ FightTable.id eq id }) {
it[replayAvailable] = true
}
}
}
val fightID by FightTable.id.transform({ EntityID(it, FightTable) }, { it.value })
val gameMode by FightTable.gamemode
val server by FightTable.server
val startTime by FightTable.startTime.transform({ it.toInstant() }, { Timestamp.from(it) })
val duration by FightTable.duration
val blueLeaderId by FightTable.blueLeader
val blueLeader by lazy { useDb { SteamwarUser[blueLeaderId] } }
val redLeaderId by FightTable.redLeader
val redLeader by lazy { useDb { SteamwarUser[redLeaderId] } }
val blueSchem by FightTable.blueSchem
val redSchem by FightTable.redSchem
val winner by FightTable.win
val win: Int
get() = winner.ordinal
val winCondition by FightTable.winCondition
val replayAvailable by FightTable.replayAvailable
val schemType: SchematicType?
get() = SchematicType.fromDB(gameMode)
val replayAllowed by lazy {
replayExists() && useDb {
exec(
"SELECT (b.NodeId IS NULL OR b.Config & 2) AND (r.NodeId IS NULL OR r.Config & 2) AS ReplayAllowed FROM Fight f LEFT OUTER JOIN SchematicNode b ON f.BlueSchem = b.NodeId LEFT OUTER JOIN SchematicNode r ON f.RedSchem = r.NodeId WHERE FightId = ?",
args = listOf(IntegerColumnType() to this@Fight.id.value)
) {
if (it.next()) {
it.getBoolean("ReplayAllowed")
} else {
false
}
} ?: false
}
}
fun replayExists() = schemType != null && replayAvailable
fun replayAllowed() = replayAllowed
lateinit var bluePlayers: List<FightPlayer>
lateinit var redPlayers: List<FightPlayer>
private fun initPlayers(fightPlayers: List<FightPlayer>) {
val blue = mutableListOf<FightPlayer>()
val red = mutableListOf<FightPlayer>()
for (player in fightPlayers.filter { it.fightID == id.value }) {
if (player.team == 1)
blue.add(player)
else
red.add(player)
}
bluePlayers = blue
redPlayers = red
}
enum class WinningTeam {
NONE, BLUE, RED;
}
}

View File

@@ -1,65 +0,0 @@
/*
* 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.sql;
import de.steamwar.sql.internal.Field;
import de.steamwar.sql.internal.SelectStatement;
import de.steamwar.sql.internal.Statement;
import de.steamwar.sql.internal.Table;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@AllArgsConstructor
public class FightPlayer {
private static final Table<FightPlayer> table = new Table<>(FightPlayer.class);
private static final Statement create = table.insertAll();
private static final SelectStatement<FightPlayer> batchGet = new SelectStatement<>(table, "SELECT * FROM FightPlayer WHERE FightID IN ?");
@Getter
@Field(keys = {Table.PRIMARY})
private final int fightID;
@Getter
@Field(keys = {Table.PRIMARY})
private final int userID;
@Getter
@Field
private final int team;
@Field
private final String kit;
@Field
private final int kills;
@Field
private final boolean isOut;
public static void create(int fightID, int userID, boolean blue, String kit, int kills, boolean isOut) {
create.update(fightID, userID, blue ? 1 : 2, kit, kills, isOut);
}
public static List<FightPlayer> batchGet(Stream<Integer> fightIds) {
try (SelectStatement<FightPlayer> batch = new SelectStatement<>(table, "SELECT * FROM FightPlayer WHERE FightID IN (" + fightIds.map(Object::toString).collect(Collectors.joining(", ")) + ")")) {
return batch.listSelect();
}
}
}

View File

@@ -0,0 +1,80 @@
/*
* 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.sql
import de.steamwar.sql.internal.useDb
import org.jetbrains.exposed.v1.core.dao.id.CompositeID
import org.jetbrains.exposed.v1.core.dao.id.CompositeIdTable
import org.jetbrains.exposed.v1.core.dao.id.EntityID
import org.jetbrains.exposed.v1.core.inList
import org.jetbrains.exposed.v1.dao.CompositeEntity
import org.jetbrains.exposed.v1.dao.CompositeEntityClass
import org.jetbrains.exposed.v1.jdbc.insertIgnore
object FightPlayerTable : CompositeIdTable("FightPlayer") {
val fightId = reference("FightId", FightTable)
val userId = reference("UserId", SteamwarUserTable)
val team = integer("Team")
val kit = varchar("Kit", 64)
val kills = integer("Kills")
val out = bool("IsOut")
init {
addIdColumn(fightId)
addIdColumn(userId)
}
}
class FightPlayer(id: EntityID<CompositeID>) : CompositeEntity(id) {
companion object : CompositeEntityClass<FightPlayer>(FightPlayerTable) {
@JvmStatic
fun create(
fightId: Int,
userId: Int,
blue: Boolean,
kit: String,
kills: Int,
out: Boolean
) = useDb {
FightPlayerTable.insertIgnore {
it[this.fightId] = fightId
it[this.userId] = userId
it[this.team] = if (blue) 1 else 2
it[this.kit] = kit
it[this.kills] = kills
it[this.out] = out
}
}
@JvmStatic
fun batchGet(fightIds: List<Int>) = useDb {
find { FightPlayerTable.fightId inList fightIds.toList() }.toList()
}
}
val fightID by FightPlayerTable.fightId.transform({ EntityID(it, FightTable) }, { it.value })
val userID by FightPlayerTable.userId.transform({ EntityID(it, SteamwarUserTable) }, { it.value })
val team by FightPlayerTable.team
val kit by FightPlayerTable.kit
val kills by FightPlayerTable.kills
val out by FightPlayerTable.out
fun isOut() = out
}

View File

@@ -35,11 +35,19 @@ import java.util.stream.Collectors;
public final class GameModeConfig<M, W> { public final class GameModeConfig<M, W> {
public static final Function<String, String> ToString = Function.identity(); public static final Function<String, String> ToString = Function.identity();
public static final Function<File, String> ToStaticWarGear = __ -> "WarGear"; public static final Function<File, String> ToStaticWarGear = GameModeConfig::constWarGear;
public static final Function<File, String> ToInternalName = file -> file != null ? file.getName().replace(".yml", "") : "WarGear"; public static final Function<File, String> ToInternalName = GameModeConfig::internalName;
public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("dd.MM.yyyy HH:mm"); public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("dd.MM.yyyy HH:mm");
private static final Random random = new Random(); private static final Random random = new Random();
private static String constWarGear(File f) {
return "WarGear";
}
private static String internalName(File f) {
return f != null ? f.getName().replace(".yml", "") : constWarGear(null);
}
private static final Map<String, GameModeConfig<?, String>> byFileName; private static final Map<String, GameModeConfig<?, String>> byFileName;
private static final Map<String, GameModeConfig<?, String>> byGameName; private static final Map<String, GameModeConfig<?, String>> byGameName;
private static final Map<SchematicType, GameModeConfig<?, String>> bySchematicType; private static final Map<SchematicType, GameModeConfig<?, String>> bySchematicType;
@@ -63,11 +71,15 @@ public final class GameModeConfig<M, W> {
} }
private static final Field Schematic_TypeField; private static final Field Schematic_TypeField;
private static final Field Schematic_SubTypesField;
static { static {
try { try {
Schematic_TypeField = SchematicConfig.class.getDeclaredField("Type"); Schematic_TypeField = SchematicConfig.class.getDeclaredField("Type");
Schematic_TypeField.setAccessible(true); Schematic_TypeField.setAccessible(true);
Schematic_SubTypesField = SchematicConfig.class.getDeclaredField("SubTypes");
Schematic_SubTypesField.setAccessible(true);
} catch (NoSuchFieldException e) { } catch (NoSuchFieldException e) {
throw new SecurityException(e.getMessage(), e); throw new SecurityException(e.getMessage(), e);
} }
@@ -77,6 +89,18 @@ public final class GameModeConfig<M, W> {
bySchematicType = new HashMap<>(); bySchematicType = new HashMap<>();
SchematicType.values(); SchematicType.values();
DEFAULTS = SQLWrapper.impl.loadGameModeConfig(null); DEFAULTS = SQLWrapper.impl.loadGameModeConfig(null);
byFileName.values().forEach(gameModeConfig -> {
List<SchematicType> subTypes = Collections.unmodifiableList(gameModeConfig.Schematic.SubTypesStrings.stream()
.map(SchematicType::fromDB)
.filter(Objects::nonNull)
.collect(Collectors.toList()));
try {
Schematic_SubTypesField.set(gameModeConfig.Schematic, subTypes);
} catch (IllegalAccessException e) {
throw new SecurityException(e.getMessage(), e);
}
});
} }
public final boolean loaded; public final boolean loaded;
@@ -516,6 +540,8 @@ public final class GameModeConfig<M, W> {
*/ */
public final SchematicType Type; public final SchematicType Type;
private final List<String> SubTypesStrings;
/** /**
* The schematic types that are also allowed to be chosen in this arena * The schematic types that are also allowed to be chosen in this arena
*/ */
@@ -605,6 +631,13 @@ public final class GameModeConfig<M, W> {
*/ */
public final int MaxDispenserItems; public final int MaxDispenserItems;
/**
* Maximal blast resistance for the blocks
*
* @implSpec {@code Double.MAX_VALUE} by default
*/
public final double MaxBlastResistance;
/** /**
* Maximal blast resistance for the design blocks * Maximal blast resistance for the design blocks
* *
@@ -623,6 +656,7 @@ public final class GameModeConfig<M, W> {
Size = new SizeConfig(loader.with("Size")); Size = new SizeConfig(loader.with("Size"));
Inset = new InsetConfig(loader.with("Inset")); Inset = new InsetConfig(loader.with("Inset"));
Type = loader.getSchematicType("Type", "Normal"); Type = loader.getSchematicType("Type", "Normal");
SubTypesStrings = loader.getStringList("SubTypes");
SubTypes = loader.getSchematicTypeList("SubTypes"); SubTypes = loader.getSchematicTypeList("SubTypes");
Shortcut = loader.getString("Shortcut", ""); Shortcut = loader.getString("Shortcut", "");
Material = loader.getMaterial("Material", "STONE_BUTTON"); Material = loader.getMaterial("Material", "STONE_BUTTON");
@@ -636,6 +670,7 @@ public final class GameModeConfig<M, W> {
UnlimitedPrepare = loader.getBoolean("UnlimitedPrepare", false); UnlimitedPrepare = loader.getBoolean("UnlimitedPrepare", false);
MaxBlocks = loader.getInt("MaxBlocks", 0); MaxBlocks = loader.getInt("MaxBlocks", 0);
MaxDispenserItems = loader.getInt("MaxDispenserItems", 128); MaxDispenserItems = loader.getInt("MaxDispenserItems", 128);
MaxBlastResistance = loader.getDouble("MaxBlastResistance", Double.MAX_VALUE);
MaxDesignBlastResistance = loader.getDouble("MaxDesignBlastResistance", Double.MAX_VALUE); MaxDesignBlastResistance = loader.getDouble("MaxDesignBlastResistance", Double.MAX_VALUE);
Map<Set<M>, Integer> Limited = new HashMap<>(); Map<Set<M>, Integer> Limited = new HashMap<>();
@@ -650,6 +685,10 @@ public final class GameModeConfig<M, W> {
Limited.put(Collections.unmodifiableSet(materials.stream().map(String::toUpperCase).map(loader.materialMapper).collect(Collectors.toSet())), amount); Limited.put(Collections.unmodifiableSet(materials.stream().map(String::toUpperCase).map(loader.materialMapper).collect(Collectors.toSet())), amount);
} }
} }
SQLWrapper.impl.getMaterialWithGreaterBlastResistance(MaxBlastResistance).forEach(material -> {
if (Limited.entrySet().stream().anyMatch(entry -> entry.getKey().contains(material))) return;
Limited.put(Collections.singleton((M) material), 0);
});
this.Limited = Collections.unmodifiableMap(Limited); this.Limited = Collections.unmodifiableMap(Limited);
} }

View File

@@ -1,59 +0,0 @@
/*
* 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.sql;
import de.steamwar.sql.internal.Field;
import de.steamwar.sql.internal.SelectStatement;
import de.steamwar.sql.internal.Statement;
import de.steamwar.sql.internal.Table;
import lombok.AllArgsConstructor;
import java.sql.ResultSet;
import java.util.UUID;
@AllArgsConstructor
public class IgnoreSystem {
private static final Table<IgnoreSystem> table = new Table<>(IgnoreSystem.class, "IgnoredPlayers");
private static final SelectStatement<IgnoreSystem> select = table.select(Table.PRIMARY);
private static final Statement insert = table.insertAll();
private static final Statement delete = table.delete(Table.PRIMARY);
@Field(keys = {Table.PRIMARY})
private final int ignorer;
@Field(keys = {Table.PRIMARY})
private final int ignored;
public static boolean isIgnored(UUID ignorer, UUID ignored){
return isIgnored(SteamwarUser.get(ignorer), SteamwarUser.get(ignored));
}
public static boolean isIgnored(SteamwarUser ignorer, SteamwarUser ignored) {
return select.select(ResultSet::next, ignorer.getId(), ignored.getId());
}
public static void ignore(SteamwarUser ignorer, SteamwarUser ignored) {
insert.update(ignorer.getId(), ignored.getId());
}
public static void unIgnore(SteamwarUser ignorer, SteamwarUser ignored) {
delete.update(ignorer.getId(), ignored.getId());
}
}

View File

@@ -0,0 +1,74 @@
/*
* 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.sql
import de.steamwar.sql.internal.useDb
import org.jetbrains.exposed.v1.core.and
import org.jetbrains.exposed.v1.core.dao.id.CompositeID
import org.jetbrains.exposed.v1.core.dao.id.CompositeIdTable
import org.jetbrains.exposed.v1.core.dao.id.EntityID
import org.jetbrains.exposed.v1.core.eq
import org.jetbrains.exposed.v1.dao.CompositeEntity
import org.jetbrains.exposed.v1.dao.CompositeEntityClass
import java.util.*
object IgnoreSystemTable: CompositeIdTable("IgnoredPlayers") {
val ignorer = reference("Ignorer", SteamwarUserTable)
val ignored = reference("Ignored", SteamwarUserTable)
override val primaryKey = PrimaryKey(ignorer, ignored)
init {
addIdColumn(ignorer)
addIdColumn(ignored)
}
}
class IgnoreSystem(id: EntityID<CompositeID>) : CompositeEntity(id) {
var ignorer by IgnoreSystemTable.ignorer
var ignored by IgnoreSystemTable.ignored
companion object : CompositeEntityClass<IgnoreSystem>(IgnoreSystemTable) {
@JvmStatic
fun isIgnored(ignorer: UUID, ignored: UUID) = useDb { isIgnored(SteamwarUser.get(ignorer)!!, SteamwarUser.get(ignored)!!) }
@JvmStatic
fun isIgnored(ignorer: SteamwarUser, ignored: SteamwarUser) = useDb {
find {
(IgnoreSystemTable.ignorer eq ignorer.id) and (IgnoreSystemTable.ignored eq ignored.id)
}.firstOrNull() != null
}
@JvmStatic
fun ignore(ignorer: SteamwarUser, ignored: SteamwarUser) = useDb {
new {
this.ignorer = ignorer.id
this.ignored = ignored.id
}
}
@JvmStatic
fun unIgnore(ignorer: SteamwarUser, ignored: SteamwarUser) = useDb {
find {
(IgnoreSystemTable.ignorer eq ignorer.id) and (IgnoreSystemTable.ignored eq ignored.id)
}.firstOrNull()?.delete()
}
}
}

View File

@@ -1,101 +0,0 @@
/*
* 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.sql;
import de.steamwar.sql.internal.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.List;
@AllArgsConstructor
public class Mod {
static {
SqlTypeMapper.ordinalEnumMapper(Platform.class);
SqlTypeMapper.ordinalEnumMapper(ModType.class);
}
private static final Table<Mod> table = new Table<>(Mod.class, "Mods");
private static final SelectStatement<Mod> get = table.select(Table.PRIMARY);
private static final SelectStatement<Mod> findFirst = new SelectStatement<>(table, "SELECT * FROM Mods WHERE ModType = 0 LIMIT 1");
private static final SelectStatement<Mod> getPageOfType = new SelectStatement<>(table, "SELECT * FROM Mods WHERE ModType = ? ORDER BY ModName DESC LIMIT ?, ?");
private static final Statement insert = table.insert(Table.PRIMARY);
private static final Statement set = table.update(Table.PRIMARY, "ModType");
public static Mod get(String name, Platform platform) {
return get.select(platform, name);
}
public static Mod getOrCreate(String name, Platform platform) {
Mod mod = get(name, platform);
if(mod != null)
return mod;
insert.update(platform, name);
return new Mod(platform, name, ModType.UNKLASSIFIED);
}
public static List<Mod> getAllModsFiltered(int page, int elementsPerPage, ModType filter) {
return Mod.getPageOfType.listSelect(filter, page * elementsPerPage, elementsPerPage);
}
public static Mod findFirstMod() {
return findFirst.select();
}
@Getter
@Field(keys = {Table.PRIMARY})
private final Platform platform;
@Getter
@Field(keys = {Table.PRIMARY})
private final String modName;
@Getter
@Field(def = "0")
private ModType modType;
public void setModType(ModType modType) {
set.update(modType, platform, modName);
this.modType = modType;
}
public enum Platform {
FORGE,
LABYMOD,
FABRIC
}
public enum ModType {
UNKLASSIFIED("7"),
GREEN("a"),
YELLOW("e"),
RED("c"),
YOUTUBER_ONLY("6");
ModType(String colorcode) {
this.colorcode = colorcode;
}
private final String colorcode;
public String getColorCode() {
return colorcode;
}
}
}

View File

@@ -0,0 +1,88 @@
/*
* 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.sql
import de.steamwar.sql.internal.useDb
import org.jetbrains.exposed.v1.core.SortOrder
import org.jetbrains.exposed.v1.core.and
import org.jetbrains.exposed.v1.core.dao.id.CompositeID
import org.jetbrains.exposed.v1.core.dao.id.CompositeIdTable
import org.jetbrains.exposed.v1.core.dao.id.EntityID
import org.jetbrains.exposed.v1.core.eq
import org.jetbrains.exposed.v1.dao.CompositeEntity
import org.jetbrains.exposed.v1.dao.CompositeEntityClass
object ModTable : CompositeIdTable("Mods") {
val platform = enumeration("Platform", Mod.Platform::class)
val modName = varchar("ModName", 100)
val modeType = enumerationByName("ModType", 10, Mod.ModType::class)
}
class Mod(id: EntityID<CompositeID>) : CompositeEntity(id) {
companion object : CompositeEntityClass<Mod>(ModTable) {
@JvmStatic
fun get(modName: String, platform: Platform) = useDb {
find { ModTable.platform eq platform and (ModTable.modName eq modName) }.firstOrNull()
}
@JvmStatic
fun getOrCreate(modName: String, platform: Platform) = useDb {
get(modName, platform) ?: new {
this.platform = platform
this.modName = modName
this.type = ModType.UNKLASSIFIED
}
}
@JvmStatic
fun getAllModsFiltered(page: Int, elementsPerPage: Int, filter: ModType) = useDb {
find { ModTable.modeType eq filter }.limit(elementsPerPage).offset((elementsPerPage * page).toLong())
.orderBy(
ModTable.modName to SortOrder.DESC
).toList()
}
@JvmStatic
fun findFirstMod() = useDb {
find { ModTable.modeType eq ModType.UNKLASSIFIED }.limit(1).firstOrNull()
}
}
var platform by ModTable.platform
var modName by ModTable.modName
private var type by ModTable.modeType
var modType: ModType
get() = type
set(value) = useDb { type = value }
enum class Platform {
FORGE,
LABYMOD,
FABRIC
}
enum class ModType(val colorCode: String) {
UNKLASSIFIED("7"),
GREEN("a"),
YELLOW("e"),
RED("c"),
YOUTUBER_ONLY("6");
}
}

View File

@@ -1,137 +0,0 @@
/*
* 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.sql;
import de.steamwar.sql.internal.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import javax.swing.plaf.nimbus.State;
import java.io.*;
import java.sql.PreparedStatement;
import java.sql.Timestamp;
import java.time.Instant;
import java.util.List;
import java.util.Optional;
import java.util.zip.GZIPInputStream;
@AllArgsConstructor
@Getter
public class NodeData {
static {
new SqlTypeMapper<>(PipedInputStream.class, "BLOB", (rs, identifier) -> { throw new SecurityException("PipedInputStream is write only datatype"); }, PreparedStatement::setBinaryStream);
new SqlTypeMapper<>(ByteArrayInputStream.class, "BLOB", (rs, identifier) -> { throw new SecurityException("ByteArrayInputStream is write only datatype"); }, PreparedStatement::setBinaryStream);
new SqlTypeMapper<>(BufferedInputStream.class, "BLOB", (rs, identifier) -> { throw new SecurityException("BufferedInputStream is write only datatype"); }, PreparedStatement::setBinaryStream);
SqlTypeMapper.ordinalEnumMapper(SchematicFormat.class);
}
private static final Table<NodeData> table = new Table<>(NodeData.class);
private static final Statement updateDatabase = new Statement("INSERT INTO NodeData(NodeId, NodeFormat, SchemData) VALUES (?, ?, ?)", true);
private static final Statement selSchemData = new Statement("SELECT SchemData FROM NodeData WHERE NodeId = ? AND CreatedAt = ?");
private static final Statement delete = table.delete(Table.PRIMARY);
private static final SelectStatement<NodeData> get = new SelectStatement<>(table, "SELECT NodeId, CreatedAt, NodeFormat FROM NodeData WHERE NodeId = ? ORDER BY CreatedAt ");
private static final Statement getRevisions = new Statement("SELECT COUNT(DISTINCT CreatedAt) as CNT FROM NodeData WHERE NodeId = ?");
private static final SelectStatement<NodeData> getLatest = new SelectStatement<>(table, "SELECT NodeId, CreatedAt, NodeFormat FROM NodeData WHERE NodeId = ? ORDER BY CreatedAt DESC LIMIT 1");
public static NodeData getLatest(SchematicNode node) {
if (node.isDir()) throw new IllegalArgumentException("Node is dir");
return Optional.ofNullable(getLatest.select(node)).orElseGet(() -> new NodeData(node.getId(), Timestamp.from(Instant.now()), SchematicFormat.MCEDIT));
}
public static List<NodeData> get(SchematicNode node) {
return get.listSelect(node);
}
public static NodeData get(SchematicNode node, int revision) {
return get.listSelect(node).get(revision - 1);
}
public static int getRevisions(SchematicNode node) {
return getRevisions.select(rs -> {
if (rs.next()) {
return rs.getInt("CNT");
} else {
return 0;
}
}, node);
}
public static void saveFromStream(SchematicNode node, InputStream blob, SchematicFormat format) {
updateDatabase.update(node.getId(), format, blob);
}
@Field(keys = {Table.PRIMARY})
private final int nodeId;
@Field(keys = {Table.PRIMARY})
private Timestamp createdAt;
@Field
private SchematicFormat nodeFormat;
public InputStream schemData() throws IOException {
return schemData(true);
}
public InputStream schemData(boolean decompress) throws IOException {
try {
return selSchemData.select(rs -> {
rs.next();
InputStream schemData = rs.getBinaryStream("SchemData");
try {
if(rs.wasNull() || schemData.available() == 0) {
throw new SecurityException("SchemData is null");
}
if (decompress) {
return new GZIPInputStream(schemData);
} else {
return schemData;
}
} catch (IOException e) {
throw new SecurityException("SchemData is wrong", e);
}
}, nodeId, createdAt);
} catch (Exception e) {
throw new IOException(e);
}
}
@Deprecated
public void saveFromStream(InputStream blob, SchematicFormat newFormat) {
saveFromStream(SchematicNode.getSchematicNode(nodeId), blob, newFormat);
}
public void delete() {
delete.update(nodeId, createdAt);
}
@AllArgsConstructor
@Getter
public enum SchematicFormat {
MCEDIT(".schematic"),
SPONGE_V2(".schem"),
SPONGE_V3(".schem");
private final String fileEnding;
}
}

View File

@@ -0,0 +1,100 @@
/*
* 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.sql
import de.steamwar.sql.internal.useDb
import org.jetbrains.exposed.v1.core.SortOrder
import org.jetbrains.exposed.v1.core.dao.id.CompositeID
import org.jetbrains.exposed.v1.core.dao.id.CompositeIdTable
import org.jetbrains.exposed.v1.core.dao.id.EntityID
import org.jetbrains.exposed.v1.core.eq
import org.jetbrains.exposed.v1.core.statements.api.ExposedBlob
import org.jetbrains.exposed.v1.dao.CompositeEntity
import org.jetbrains.exposed.v1.dao.CompositeEntityClass
import org.jetbrains.exposed.v1.javatime.CurrentTimestamp
import org.jetbrains.exposed.v1.javatime.timestamp
import org.jetbrains.exposed.v1.jdbc.insert
import java.io.InputStream
import java.util.zip.GZIPInputStream
object NodeDataTable: CompositeIdTable("NodeData") {
val nodeId = reference("NodeId", SchematicNodeTable)
val createdAt = timestamp("CreatedAt").defaultExpression(CurrentTimestamp).entityId()
val nodeFormat = enumeration("NodeFormat", NodeData.SchematicFormat::class)
val schemData = blob("SchemData")
override val primaryKey = PrimaryKey(nodeId, createdAt)
init {
addIdColumn(nodeId)
}
}
class NodeData(id: EntityID<CompositeID>): CompositeEntity(id) {
val nodeId by NodeDataTable.nodeId
val createdAt by NodeDataTable.createdAt
val nodeFormat by NodeDataTable.nodeFormat
val schemData by NodeDataTable.schemData
companion object: CompositeEntityClass<NodeData>(NodeDataTable) {
@JvmStatic
fun getLatest(node: SchematicNode) = useDb {
find { (NodeDataTable.nodeId eq node.nodeId) }.orderBy(NodeDataTable.createdAt to SortOrder.DESC).firstOrNull()
}
@JvmStatic
fun get(node: SchematicNode) = useDb {
find { (NodeDataTable.nodeId eq node.nodeId) }.orderBy(NodeDataTable.createdAt to SortOrder.ASC).toList()
}
@JvmStatic
fun get(node: SchematicNode, revision: Int) = useDb {
find { NodeDataTable.nodeId eq node.nodeId }.orderBy(NodeDataTable.createdAt to SortOrder.ASC).toList().get(revision - 1)
}
@JvmStatic
fun getRevisions(node: SchematicNode) = useDb {
count(NodeDataTable.nodeId eq node.nodeId).toInt()
}
@JvmStatic
fun saveFromStream(node: SchematicNode, blob: InputStream, format: SchematicFormat) = useDb {
NodeDataTable.insert {
it[NodeDataTable.nodeId] = EntityID(node.getId(), SchematicNodeTable)
it[NodeDataTable.nodeFormat] = format
it[NodeDataTable.schemData] = ExposedBlob(blob.readBytes())
}
}
}
fun schemData(decompress: Boolean) = useDb {
schemData.inputStream.let { if(decompress) GZIPInputStream(it) else it }
}
fun schemData() = schemData(true)
override fun delete() = useDb { super.delete() }
enum class SchematicFormat(val fileEnding: String) {
MCEDIT(".schematic"),
SPONGE_V2(".schem"),
SPONGE_V3(".schem");
}
}

View File

@@ -1,86 +0,0 @@
/*
* 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.sql;
import de.steamwar.sql.internal.Field;
import de.steamwar.sql.internal.SelectStatement;
import de.steamwar.sql.internal.Statement;
import de.steamwar.sql.internal.Table;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.Timestamp;
import java.time.Instant;
@AllArgsConstructor
public class NodeDownload {
private static final char[] HEX = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
private static final String LINK_BASE = "https://api.steamwar.de/download/";
private static final Table<NodeDownload> table = new Table<>(NodeDownload.class);
private static final Statement insert = table.insertFields("NodeId", "Link");
private static final SelectStatement<NodeDownload> select = table.selectFields("link");
private static final Statement delete = table.delete(Table.PRIMARY);
public static NodeDownload get(String link) {
return select.select(link);
}
@Getter
@Field(keys = {Table.PRIMARY})
private final int nodeId;
@Field
private final String link;
@Field(def = "CURRENT_TIMESTAMP")
@Getter
private final Timestamp timestamp;
public static String getLink(SchematicNode schem){
if(schem.isDir())
throw new SecurityException("Can not Download Directorys");
MessageDigest digest;
try {
digest = MessageDigest.getInstance("SHA-1");
} catch (NoSuchAlgorithmException e) {
throw new SecurityException(e);
}
digest.reset();
digest.update((Instant.now().toString() + schem.getOwner() + schem.getId()).getBytes());
String hash = base16encode(digest.digest());
insert.update(schem.getId(), hash);
return LINK_BASE + hash;
}
public static String base16encode(byte[] byteArray) {
StringBuilder hexBuffer = new StringBuilder(byteArray.length * 2);
for (byte b : byteArray)
hexBuffer.append(HEX[(b >>> 4) & 0xF]).append(HEX[b & 0xF]);
return hexBuffer.toString();
}
public void delete() {
delete.update(nodeId);
}
}

View File

@@ -0,0 +1,76 @@
/*
* 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.sql
import de.steamwar.sql.internal.useDb
import org.jetbrains.exposed.v1.core.dao.id.EntityID
import org.jetbrains.exposed.v1.core.dao.id.IdTable
import org.jetbrains.exposed.v1.core.eq
import org.jetbrains.exposed.v1.dao.IntEntity
import org.jetbrains.exposed.v1.dao.IntEntityClass
import org.jetbrains.exposed.v1.javatime.CurrentTimestamp
import org.jetbrains.exposed.v1.javatime.timestamp
import java.security.MessageDigest
import java.sql.Timestamp
import java.time.Instant
object NodeDownloadTable: IdTable<Int>("NodeDownload") {
override val id = reference("NodeId", SchematicNodeTable).uniqueIndex()
val link = varchar("Link", 255)
val timestamp = timestamp("Timestamp").defaultExpression(CurrentTimestamp)
}
class NodeDownload(id: EntityID<Int>) : IntEntity(id) {
companion object : IntEntityClass<NodeDownload>(NodeDownloadTable) {
const val LINK_BASE = "https://api.steamwar.de/download/"
@JvmStatic
fun getLink(schem: SchematicNode): String {
if (schem.isDir())
throw IllegalArgumentException("Cannot get link for directory")
val digest = MessageDigest.getInstance("SHA-1")
digest.update("${Instant.now()}${schem.owner}${schem.nodeId}".toByteArray())
val hash = digest.digest().joinToString("") { "%02x".format(it) }
useDb {
findByIdAndUpdate(schem.id.value) {
it.link = hash
} ?: new {
nodeId = schem.id.value
link = hash
}
}
return "${LINK_BASE}${hash}"
}
@JvmStatic
fun get(link: String) = useDb {
find { NodeDownloadTable.link eq link }.firstOrNull()
}
}
var nodeId by NodeDownloadTable.id.transform({ EntityID(it, SchematicNodeTable) }, { it.value })
var link by NodeDownloadTable.link
var timestamp by NodeDownloadTable.timestamp.transform({ it.toInstant() }, { Timestamp.from(it) })
override fun delete() = useDb {
super.delete()
}
}

View File

@@ -1,95 +0,0 @@
/*
* 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.sql;
import de.steamwar.sql.internal.Field;
import de.steamwar.sql.internal.SelectStatement;
import de.steamwar.sql.internal.Statement;
import de.steamwar.sql.internal.Table;
import lombok.AllArgsConstructor;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
@AllArgsConstructor
public class NodeMember {
public static void init() {
// enforce class initialization
}
private static final Table<NodeMember> table = new Table<>(NodeMember.class);
private static final SelectStatement<NodeMember> getNodeMember = table.select(Table.PRIMARY);
private static final SelectStatement<NodeMember> getNodeMembers = table.selectFields("NodeId");
private static final SelectStatement<NodeMember> getSchematics = table.selectFields("UserId");
private static final Statement create = table.insert(Table.PRIMARY);
private static final Statement delete = table.delete(Table.PRIMARY);
private static final Statement updateParent = table.update(Table.PRIMARY, "ParentId");
@Field(keys = {Table.PRIMARY})
private final int nodeId;
@Field(keys = {Table.PRIMARY})
private final int userId;
@Field(nullable = true, def = "null")
private Integer parentId;
public int getNode() {
return nodeId;
}
public int getMember() {
return userId;
}
public Optional<Integer> getParent() {
return Optional.ofNullable(parentId);
}
public void delete() {
delete.update(nodeId, userId);
}
public static NodeMember createNodeMember(int node, int member) {
create.update(node, member);
return new NodeMember(node, member, null);
}
public static NodeMember getNodeMember(int node, SteamwarUser member) {
return getNodeMember(node, member.getId());
}
public static NodeMember getNodeMember(int node, int member) {
return getNodeMember.select(node, member);
}
public static Set<NodeMember> getNodeMembers(int node) {
return new HashSet<>(getNodeMembers.listSelect(node));
}
public static Set<NodeMember> getSchematics(int member) {
return new HashSet<>(getSchematics.listSelect(member));
}
public void setParentId(Integer parentId) {
this.parentId = parentId;
updateParent.update(this.parentId, nodeId, userId);
}
}

View File

@@ -0,0 +1,92 @@
/*
* 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.sql
import de.steamwar.sql.internal.useDb
import org.jetbrains.exposed.v1.core.and
import org.jetbrains.exposed.v1.core.dao.id.CompositeID
import org.jetbrains.exposed.v1.core.dao.id.CompositeIdTable
import org.jetbrains.exposed.v1.core.dao.id.EntityID
import org.jetbrains.exposed.v1.core.eq
import org.jetbrains.exposed.v1.dao.CompositeEntity
import org.jetbrains.exposed.v1.dao.CompositeEntityClass
import org.jetbrains.exposed.v1.jdbc.insertIgnore
import java.util.*
import kotlin.jvm.optionals.getOrNull
object NodeMemberTable : CompositeIdTable("NodeMember") {
val node = reference("NodeId", SchematicNodeTable)
val userId = reference("UserId", SteamwarUserTable)
val parentNode = optReference("ParentId", SchematicNodeTable)
override val primaryKey = PrimaryKey(node, userId)
init {
addIdColumn(node)
addIdColumn(userId)
}
}
class NodeMember(id: EntityID<CompositeID>) : CompositeEntity(id) {
companion object : CompositeEntityClass<NodeMember>(NodeMemberTable) {
@JvmStatic
fun createNodeMember(node: Int, member: Int): NodeMember = useDb {
NodeMemberTable.insertIgnore {
it[this.node] = EntityID(node, SchematicNodeTable)
it[this.userId] = EntityID(member, SteamwarUserTable)
}
getNodeMember(node, member) ?: throw IllegalStateException("NodeMember not created")
}
@JvmStatic
fun createNodeMember(node: Int, member: SteamwarUser) = createNodeMember(node, member.id.value)
@JvmStatic
fun getNodeMember(node: Int, member: Int) = useDb {
find { (NodeMemberTable.node eq node) and (NodeMemberTable.userId eq member) }.firstOrNull()
}
@JvmStatic
fun getNodeMember(node: Int, member: SteamwarUser) = getNodeMember(node, member.id.value)
@JvmStatic
fun getNodeMembers(node: Int) = useDb { find { NodeMemberTable.node eq node }.toSet() }
@JvmStatic
fun getSchematics(member: Int) = useDb { find { NodeMemberTable.userId eq member }.toSet() }
@JvmStatic
fun init() = Unit
}
val node by NodeMemberTable.node.transform({ EntityID(it, SchematicNodeTable) }, { it.value })
val member by NodeMemberTable.userId.transform({ EntityID(it, SteamwarUserTable) }, { it.value })
var parent by NodeMemberTable.parentNode.transform(
{ it.map { EntityID(it, SchematicNodeTable) }.getOrNull() },
{ Optional.ofNullable(it?.value) })
fun setParentId(id: Int?) {
parent = Optional.ofNullable(id)
}
override fun delete() = useDb {
super.delete()
}
}

View File

@@ -0,0 +1,117 @@
/*
* 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.sql
import de.steamwar.sql.internal.useDb
import org.jetbrains.exposed.v1.core.and
import org.jetbrains.exposed.v1.core.dao.id.CompositeID
import org.jetbrains.exposed.v1.core.dao.id.CompositeIdTable
import org.jetbrains.exposed.v1.core.dao.id.EntityID
import org.jetbrains.exposed.v1.core.eq
import org.jetbrains.exposed.v1.dao.CompositeEntity
import org.jetbrains.exposed.v1.dao.CompositeEntityClass
import org.jetbrains.exposed.v1.jdbc.insert
object PersonalKitTable: CompositeIdTable("PersonalKit") {
val userId = reference("UserId", SteamwarUserTable)
val gamemode = varchar("Gamemode", 64).entityId()
val kitName = varchar("Name", 64).entityId()
val inventory = text("Inventory")
val armor = text("Armor")
val inUse = bool("InUse")
override val primaryKey = PrimaryKey(userId, gamemode, kitName)
init {
addIdColumn(userId)
}
}
class InternalKit(id: EntityID<CompositeID>): CompositeEntity(id) {
companion object: CompositeEntityClass<InternalKit>(PersonalKitTable) {
@JvmStatic
fun get(userId: Int, gamemode: String) = useDb {
find { PersonalKitTable.userId eq userId and (PersonalKitTable.gamemode eq gamemode) and (PersonalKitTable.inUse eq true) }
.toList()
}
@JvmStatic
fun get(userId: Int, gamemode: String, kitName: String) = useDb {
find { PersonalKitTable.userId eq userId and (PersonalKitTable.gamemode eq gamemode) and (PersonalKitTable.kitName eq kitName) and (PersonalKitTable.inUse eq true) }
.firstOrNull()
}
@JvmStatic
fun create(userId: Int, gamemode: String, kitName: String, rawInventory: String, rawArmor: String) = useDb {
new(
CompositeID {
it[PersonalKitTable.userId] = EntityID(userId, SteamwarUserTable)
it[PersonalKitTable.gamemode] = gamemode
it[PersonalKitTable.kitName] = kitName
}
) {
this.inventory = rawInventory
this.armor = rawArmor
this.inUse = true
}
}
@JvmStatic
fun getKitInUse(userId: Int, gamemode: String) = useDb {
find { PersonalKitTable.userId eq userId and (PersonalKitTable.gamemode eq gamemode) and (PersonalKitTable.inUse eq true) }
.firstOrNull()
}
}
var userID by PersonalKitTable.userId.transform({ EntityID(it, SteamwarUserTable) }, { it.value })
private set
private var gameMode by PersonalKitTable.gamemode
val gamemode: String
get() = gameMode.value
var kitName by PersonalKitTable.kitName
private set
val name: String
get() = kitName.value
var rawInventory by PersonalKitTable.inventory
private set
var rawArmor by PersonalKitTable.armor
private set
var inUse by PersonalKitTable.inUse
private set
var inventory: String
get() = rawInventory
set(value) = useDb { rawInventory = value }
var armor: String
get() = rawArmor
set(value) = useDb { rawArmor = value }
fun setDefault() = useDb {
find { PersonalKitTable.userId eq userID and (PersonalKitTable.gamemode eq gameMode) and (PersonalKitTable.inUse eq true) }
.forEach { it.inUse = false }
inUse = true
}
override fun delete() = useDb {
super.delete()
}
}

View File

@@ -1,77 +0,0 @@
/*
* 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.sql;
import de.steamwar.sql.internal.Field;
import de.steamwar.sql.internal.SelectStatement;
import de.steamwar.sql.internal.Statement;
import de.steamwar.sql.internal.Table;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import java.util.HashMap;
import java.util.Map;
@AllArgsConstructor
public class PollAnswer {
@Getter
@Setter
private static String currentPoll;
private static final Table<PollAnswer> table = new Table<>(PollAnswer.class);
private static final SelectStatement<PollAnswer> get = table.select(Table.PRIMARY);
private static final Statement getResults = new Statement("SELECT Count(UserID) AS Times, Answer FROM PollAnswer WHERE Question = ? GROUP BY Answer ORDER BY Times ASC");
private static final Statement insert = table.insertAll();
@Field(keys = {Table.PRIMARY})
private final int userID;
@Field(keys = {Table.PRIMARY})
private final String question;
@Field(def = "0")
private int answer;
public static PollAnswer get(int userID) {
PollAnswer answer = get.select(userID, currentPoll);
if(answer == null)
return new PollAnswer(userID, currentPoll, 0);
return answer;
}
public static Map<Integer, Integer> getCurrentResults() {
return getResults.select(rs -> {
Map<Integer, Integer> retMap = new HashMap<>();
while (rs.next())
retMap.put(rs.getInt("Answer")-1, rs.getInt("Times"));
return retMap;
}, currentPoll);
}
public boolean hasAnswered(){
return answer != 0;
}
public void setAnswer(int answer){
this.answer = answer;
insert.update(userID, question, answer);
}
}

View File

@@ -0,0 +1,78 @@
/*
* 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.sql
import de.steamwar.sql.internal.useDb
import org.jetbrains.exposed.v1.core.VarCharColumnType
import org.jetbrains.exposed.v1.core.and
import org.jetbrains.exposed.v1.core.dao.id.CompositeID
import org.jetbrains.exposed.v1.core.dao.id.CompositeIdTable
import org.jetbrains.exposed.v1.core.dao.id.EntityID
import org.jetbrains.exposed.v1.core.eq
import org.jetbrains.exposed.v1.dao.CompositeEntity
import org.jetbrains.exposed.v1.dao.CompositeEntityClass
object PollAnswerTable: CompositeIdTable("PollAnswer") {
val userId = reference("UserID", SteamwarUserTable)
val question = varchar("Question", 150)
val answer = integer("Answer")
}
class PollAnswer(id: EntityID<CompositeID>): CompositeEntity(id) {
var userId by PollAnswerTable.userId
private set
var question by PollAnswerTable.question
private set
private var answerId by PollAnswerTable.answer
var answer: Int
get() = answerId
set(value) = useDb {
answerId = value
}
companion object: CompositeEntityClass<PollAnswer>(PollAnswerTable) {
@JvmStatic
var currentPoll: String? = null
@JvmStatic
fun get(userId: Int) = useDb {
find { (PollAnswerTable.userId eq userId) and (PollAnswerTable.question eq currentPoll!!) }.firstOrNull()
?: new {
this.userId = EntityID(userId, SteamwarUserTable)
this.question = currentPoll!!
this.answerId = 0
}
}
@JvmStatic
fun getCurrentResults(): Map<Int, Int> = useDb {
exec("SELECT Count(UserID) AS Times, Answer FROM PollAnswer WHERE Question = ? GROUP BY Answer ORDER BY Times ASC",
args = listOf(VarCharColumnType() to currentPoll!!)) {
val result = mutableMapOf<Int, Int>()
while (it.next()) {
result[it.getInt("Answer")] = it.getInt("Times")
}
result
} ?: emptyMap()
}
}
fun hasAnswered() = answerId != 0
}

View File

@@ -1,140 +0,0 @@
/*
* 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.sql;
import de.steamwar.sql.internal.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import java.sql.Timestamp;
import java.time.Instant;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Collectors;
@AllArgsConstructor
public class Punishment {
static {
SqlTypeMapper.nameEnumMapper(PunishmentType.class);
}
public static final Timestamp PERMA_TIME = Timestamp.from(Instant.ofEpochSecond(946674800));
private static final Table<Punishment> table = new Table<>(Punishment.class, "Punishments");
private static final SelectStatement<Punishment> getPunishments = new SelectStatement<>(table, "SELECT * FROM Punishments WHERE PunishmentId IN (SELECT MAX(PunishmentId) FROM Punishments WHERE UserId = ? GROUP BY Type)");
private static final SelectStatement<Punishment> getPunishment = new SelectStatement<>(table, "SELECT * FROM Punishments WHERE UserId = ? AND Type = ? ORDER BY PunishmentId DESC LIMIT 1");
private static final SelectStatement<Punishment> getAllPunishments = new SelectStatement<>(table, "SELECT * FROM Punishments WHERE UserId = ? ORDER BY `PunishmentId` DESC");
private static final Statement insert = table.insertFields(true, "UserId", "Punisher", "Type", "EndTime", "Perma", "Reason");
public static Punishment getPunishmentOfPlayer(int user, PunishmentType type) {
return getPunishment.select(user, type);
}
public static Map<PunishmentType, Punishment> getPunishmentsOfPlayer(int user) {
return getPunishments.listSelect(user).stream().collect(Collectors.toMap(Punishment::getType, punishment -> punishment));
}
public static List<Punishment> getAllPunishmentsOfPlayer(int user) {
return getAllPunishments.listSelect(user);
}
public static boolean isPunished(SteamwarUser user, PunishmentType type, Consumer<Punishment> callback) {
Punishment punishment = Punishment.getPunishmentOfPlayer(user.getId(), type);
if(punishment == null || !punishment.isCurrent()) {
return false;
} else {
callback.accept(punishment);
return true;
}
}
public static Punishment createPunishment(int user, int executor, PunishmentType type, String reason, Timestamp endTime, boolean perma) {
if(perma && !endTime.equals(PERMA_TIME)) {
throw new IllegalArgumentException("Permanent punishments must have an end time of `Punishment.PERMA_TIME`");
}
int punishmentId = insert.insertGetKey(user, executor, type.name(), endTime, perma, reason);
return new Punishment(punishmentId, user, executor, type, Timestamp.from(Instant.now()), endTime, perma, reason);
}
@Field(keys = {Table.PRIMARY}, autoincrement = true)
private final int punishmentId;
@Field
@Getter
private final int userId;
@Field
@Getter
private final int punisher;
@Field
@Getter
private final PunishmentType type;
@Field
@Getter
private final Timestamp startTime;
@Field
@Getter
private final Timestamp endTime;
@Field
@Getter
private final boolean perma;
@Field
@Getter
private final String reason;
@Deprecated // Not multiling, misleading title
public String getBantime(Timestamp endTime, boolean perma) {
if (perma) {
return "permanent";
} else {
return endTime.toLocalDateTime().format(DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm"));
}
}
public boolean isCurrent() {
return isPerma() || getEndTime().after(new Date());
}
@AllArgsConstructor
@RequiredArgsConstructor
@Getter
public enum PunishmentType {
Ban(UserPerm.TEAM, "BAN_TEAM", "BAN_PERMA", "BAN_UNTIL", "UNBAN_ERROR", "UNBAN"),
Mute( UserPerm.TEAM, "MUTE_TEAM", "MUTE_PERMA", "MUTE_UNTIL", "UNMUTE_ERROR", "UNMUTE"),
NoSchemReceiving(UserPerm.MODERATION, "NOSCHEMRECEIVING_TEAM", "NOSCHEMRECEIVING_PERMA", "NOSCHEMRECEIVING_UNTIL", "UNNOSCHEMRECEIVING_ERROR", "UNNOSCHEMRECEIVING"),
NoSchemSharing(UserPerm.MODERATION, "NOSCHEMSHARING_TEAM", "NOSCHEMSHARING_PERMA", "NOSCHEMSHARING_UNTIL", "UNNOSCHEMSHARING_ERROR", "UNNOSCHEMSHARING"),
NoSchemSubmitting(UserPerm.TEAM, "NOSCHEMSUBMITTING_TEAM", "NOSCHEMSUBMITTING_PERMA", "NOSCHEMSUBMITTING_UNTIL", "UNNOSCHEMSUBMITTING_ERROR", "UNNOSCHEMSUBMITTING"),
NoDevServer(UserPerm.PREFIX_DEVELOPER, "NODEVSERVER_TEAM", "NODEVSERVER_PERMA", "NODEVSERVER_UNTIL", "UNNODEVSERVER_ERROR", "UNNODEVSERVER"),
NoFightServer(UserPerm.MODERATION, "NOFIGHTSERVER_TEAM", "NOFIGHTSERVER_PERMA", "NOFIGHTSERVER_UNTIL", "UNNOFIGHTSERVER_ERROR", "UNNOFIGHTSERVER"),
NoTeamServer(UserPerm.MODERATION, "NOTEAMSERVER_TEAM", "NOTEAMSERVER_PERMA", "NOTEAMSERVER_UNTIL", "UNNOTEAMSERVER_ERROR", "UNNOTEAMSERVER"),
Note(UserPerm.TEAM, "NOTE_TEAM", null, null, null, null, true);
private final UserPerm userPerm;
private final String teamMessage;
private final String playerMessagePerma;
private final String playerMessageUntil;
private final String usageNotPunished;
private final String unpunishmentMessage;
private boolean multi = false;
}
}

View File

@@ -0,0 +1,186 @@
/*
* 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.sql
import de.steamwar.sql.internal.useDb
import org.jetbrains.exposed.v1.core.*
import org.jetbrains.exposed.v1.core.dao.id.EntityID
import org.jetbrains.exposed.v1.core.dao.id.IntIdTable
import org.jetbrains.exposed.v1.dao.IntEntity
import org.jetbrains.exposed.v1.dao.IntEntityClass
import org.jetbrains.exposed.v1.javatime.timestamp
import org.jetbrains.exposed.v1.jdbc.select
import java.sql.Timestamp
import java.time.Instant
import java.util.*
import java.util.function.Consumer
object PunishmentTable : IntIdTable("Punishments", "PunishmentId") {
val userId = reference("UserId", SteamwarUserTable)
val punisher = reference("Punisher", SteamwarUserTable)
val type = enumerationByName("Type", 32, Punishment.PunishmentType::class)
val startTime = timestamp("StartTime")
val endTime = timestamp("EndTime")
val perma = bool("Perma")
val reason = text("Reason")
}
class Punishment(id: EntityID<Int>) : IntEntity(id) {
companion object : IntEntityClass<Punishment>(PunishmentTable) {
@JvmField
val PERMA_TIME: Timestamp = Timestamp.from(Instant.ofEpochSecond(946674800))
@JvmStatic
fun getPunsihmentOfPlayer(user: Int, type: PunishmentType) = useDb {
find { (PunishmentTable.userId eq user) and (PunishmentTable.type eq type) }.orderBy(PunishmentTable.id to SortOrder.DESC)
.firstOrNull()
}
@JvmStatic
fun getPunishmentsOfPlayer(user: Int) = useDb {
find {
PunishmentTable.id inSubQuery PunishmentTable.select(PunishmentTable.id.max())
.where { PunishmentTable.userId eq user }.groupBy(
PunishmentTable.type
)
}.associateBy { it.type }.toMutableMap()
}
@JvmStatic
fun getAllPunishmentsOfPlayer(user: Int) = useDb {
find { PunishmentTable.userId eq user }.orderBy(PunishmentTable.id to SortOrder.DESC).toList()
}
@JvmStatic
fun isPunished(user: SteamwarUser, type: PunishmentType, callback: Consumer<Punishment>): Boolean = useDb {
val punishment = getPunsihmentOfPlayer(user.id.value, type) ?: return@useDb false
if (punishment.isCurrent()) {
callback.accept(punishment)
return@useDb true
}
return@useDb false
}
@JvmStatic
fun createPunishment(
user: Int,
executor: Int,
type: PunishmentType,
reason: String,
endTime: Timestamp,
perma: Boolean
) = useDb {
new {
this.userId = user
this.punisher = executor
this.type = type
this.startTime = Timestamp.from(Instant.now())
this.endTime = endTime
this.perma = perma
this.reason = reason
}
}
}
var userId by PunishmentTable.userId.transform({ EntityID(it, SteamwarUserTable) }, { it.value })
private set
var punisher by PunishmentTable.punisher.transform({ EntityID(it, SteamwarUserTable) }, { it.value })
private set
var type by PunishmentTable.type
private set
var startTime by PunishmentTable.startTime.transform({ it.toInstant() }, { Timestamp.from(it) })
private set
var endTime by PunishmentTable.endTime.transform({ it.toInstant() }, { Timestamp.from(it) })
private set
var perma by PunishmentTable.perma
private set
var reason by PunishmentTable.reason
private set
fun isPerma() = perma
fun isCurrent() = perma || endTime.after(Date())
enum class PunishmentType(
val teamMessage: String?,
val playerMessagePerma: String?,
val playerMessageUntil: String?,
val usageNotPunished: String?,
val unpunishmentMessage: String?,
val userPerm: UserPerm,
val multi: Boolean = false
) {
Ban("BAN_TEAM", "BAN_PERMA", "BAN_UNTIL", "UNBAN_ERROR", "UNBAN", UserPerm.TEAM),
Mute("MUTE_TEAM", "MUTE_PERMA", "MUTE_UNTIL", "UNMUTE_ERROR", "UNMUTE", UserPerm.TEAM),
NoSchemReceiving(
"NOSCHEMRECEIVING_TEAM",
"NOSCHEMRECEIVING_PERMA",
"NOSCHEMRECEIVING_UNTIL",
"UNNOSCHEMRECEIVING_ERROR",
"UNNOSCHEMRECEIVING",
UserPerm.MODERATION
),
NoSchemSharing(
"NOSCHEMSHARING_TEAM",
"NOSCHEMSHARING_PERMA",
"NOSCHEMSHARING_UNTIL",
"UNNOSCHEMSHARING_ERROR",
"UNNOSCHEMSHARING",
UserPerm.MODERATION
),
NoSchemSubmitting(
"NOSCHEMSUBMITTING_TEAM",
"NOSCHEMSUBMITTING_PERMA",
"NOSCHEMSUBMITTING_UNTIL",
"UNNOSCHEMSUBMITTING_ERROR",
"UNNOSCHEMSUBMITTING",
UserPerm.TEAM
),
NoDevServer(
"NODEVSERVER_TEAM",
"NODEVSERVER_PERMA",
"NODEVSERVER_UNTIL",
"UNNODEVSERVER_ERROR",
"UNNODEVSERVER",
UserPerm.PREFIX_DEVELOPER
),
NoFightServer(
"NOFIGHTSERVER_TEAM",
"NOFIGHTSERVER_PERMA",
"NOFIGHTSERVER_UNTIL",
"UNNOFIGHTSERVER_ERROR",
"UNNOFIGHTSERVER",
UserPerm.MODERATION
),
NoTeamServer(
"NOTEAMSERVER_TEAM",
"NOTEAMSERVER_PERMA",
"NOTEAMSERVER_UNTIL",
"UNNOTEAMSERVER_ERROR",
"UNNOTEAMSERVER",
UserPerm.MODERATION
),
Note("NOTE_TEAM", null, null, null, null, UserPerm.TEAM, true);
fun isMulti() = multi
}
}

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