Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
59de3e81ae
|
|||
| 8ade5180cb | |||
| d0535d0c47 | |||
| 79fa09e39b | |||
|
4010c2125c
|
|||
| 32de0077de | |||
| bd53e016c5 | |||
| 5b1ed644d1 | |||
| a41787d89d | |||
| 8e392b56c3 | |||
| 42feadcd2d | |||
| 15f0344416 | |||
| c90a977ab2 | |||
| b186228f4e | |||
| 5f38474809 | |||
| 4f27320548 | |||
| ba7bd1f1dd | |||
|
a37321d3b8
|
+10
@@ -198,6 +198,16 @@ public abstract class ViewFlag {
|
||||
}
|
||||
};
|
||||
|
||||
public static ViewFlag HIGHLIGHT = new ViewFlag(true, false, "highlight", "h") {
|
||||
@Override
|
||||
public void modify(REntityServer server, List<TraceEntity> entities) {
|
||||
for (TraceEntity entity : entities) {
|
||||
entity.setGlowing(true);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Name of the flag
|
||||
*/
|
||||
|
||||
@@ -90,7 +90,7 @@ class EventGroup(id: EntityID<Int>) : IntEntity(id) {
|
||||
set(value) {
|
||||
groupPointsPerDraw = value
|
||||
}
|
||||
val dependents by lazy { EventRelation.getGroupRelations(this).toList() }
|
||||
val dependents by lazy { EventRelation.getGroupRelations(this) }
|
||||
val lastFight by lazy { Optional.ofNullable(fights.maxByOrNull { it.startTime }) }
|
||||
|
||||
fun getId() = id.value
|
||||
|
||||
@@ -51,11 +51,11 @@ class EventRelation(id: EntityID<Int>) : IntEntity(id) {
|
||||
|
||||
@JvmStatic
|
||||
fun getFightRelations(fight: EventFight) =
|
||||
useDb { find { (EventRelationTable.fromId eq fight.id.value) and (EventRelationTable.fromType eq FromType.FIGHT) } }
|
||||
useDb { find { (EventRelationTable.fromId eq fight.id.value) and (EventRelationTable.fromType eq FromType.FIGHT) }.toList() }
|
||||
|
||||
@JvmStatic
|
||||
fun getGroupRelations(group: EventGroup) =
|
||||
useDb { find { (EventRelationTable.fromId eq group.id.value) and (EventRelationTable.fromType eq FromType.GROUP) } }
|
||||
useDb { find { (EventRelationTable.fromId eq group.id.value) and (EventRelationTable.fromType eq FromType.GROUP) }.toList() }
|
||||
|
||||
@JvmStatic
|
||||
fun create(fight: EventFight, fightTeam: FightTeam, fromType: FromType, fromId: Int, fromPlace: Int) = useDb {
|
||||
|
||||
@@ -687,9 +687,6 @@ public final class GameModeConfig<M, W> {
|
||||
*/
|
||||
public final Map<Set<M>, Integer> Limited;
|
||||
|
||||
/** */
|
||||
public final List<AllowedItemsConfig<M>> AllowedItems;
|
||||
|
||||
private SchematicConfig(YMLWrapper<M, ?> loader) {
|
||||
loaded = loader.canLoad();
|
||||
Size = new SizeConfig(loader.with("Size"));
|
||||
@@ -709,7 +706,6 @@ public final class GameModeConfig<M, W> {
|
||||
MaxDispenserItems = loader.getInt("MaxDispenserItems", 128);
|
||||
MaxBlastResistance = loader.getDouble("MaxBlastResistance", Double.MAX_VALUE);
|
||||
MaxDesignBlastResistance = loader.getDouble("MaxDesignBlastResistance", MaxBlastResistance);
|
||||
AllowedItems = loader.withEvery("AllowedItems").stream().map(AllowedItemsConfig::new).collect(Collectors.toList());
|
||||
|
||||
Map<Set<M>, Integer> Limited = new HashMap<>();
|
||||
for (Map<?, ?> entry : loader.getMapList("Limited")) {
|
||||
@@ -794,32 +790,6 @@ public final class GameModeConfig<M, W> {
|
||||
bottom = loader.getInt("bottom", 0);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class AllowedItemsConfig<M> {
|
||||
/**
|
||||
* The materials of the items that may be included in inventories
|
||||
*/
|
||||
public final List<M> AllowedMaterials;
|
||||
/**
|
||||
* The materials of inventory blocks that may contain the listed items
|
||||
*/
|
||||
public final List<M> AllowedIn;
|
||||
/**
|
||||
* The maximum amount of items of the listed items contained per inventory
|
||||
*/
|
||||
public final Integer MaxPerInventory;
|
||||
/**
|
||||
* The maximum amount of items of the listed items contained in total within all inventories
|
||||
*/
|
||||
public final Integer TotalMax;
|
||||
|
||||
private AllowedItemsConfig(YMLWrapper<M, ?> loader) {
|
||||
AllowedMaterials = loader.getMaterialList("AllowedMaterials");
|
||||
AllowedIn = loader.getMaterialList("AllowedIn");
|
||||
MaxPerInventory = loader.getInt("MaxPerInventory", Integer.MAX_VALUE);
|
||||
TotalMax = loader.getInt("TotalMax", Integer.MAX_VALUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ToString
|
||||
|
||||
@@ -76,20 +76,6 @@ final class YMLWrapper<M, W> {
|
||||
return new YMLWrapper<>(false, Collections.emptyMap(), materialMapper, winconditionMapper);
|
||||
}
|
||||
|
||||
public List<YMLWrapper<M, W>> withEvery(String path) {
|
||||
if (document.containsKey(path)) {
|
||||
Object value = document.get(path);
|
||||
if(value instanceof List<?>) {
|
||||
List<Object> list = (List<Object>) value;
|
||||
return list.stream().map(o -> new YMLWrapper<>(true, Collections.singletonMap("value", o), materialMapper, winconditionMapper)).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public <T> T get(String path, T defaultValue, Function<Object, T> mapper) {
|
||||
Object value = this.document.get(path);
|
||||
if (value == null) return defaultValue;
|
||||
|
||||
+1
-5
@@ -24,10 +24,6 @@ import org.bukkit.inventory.ItemStack;
|
||||
public class FlatteningWrapper21 extends FlatteningWrapper14 {
|
||||
@Override
|
||||
public boolean hasAttributeModifier(ItemStack stack) {
|
||||
if (!stack.getDataTypes().isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.hasAttributeModifier(stack);
|
||||
return stack.hasItemMeta() && stack.getItemMeta() != null && stack.getItemMeta().hasAttributeModifiers();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,27 @@ public class ReflectionWrapper21 implements ReflectionWrapper {
|
||||
FORBIDDEN_TYPES.add(DataComponentTypes.BLOCKS_ATTACKS);
|
||||
FORBIDDEN_TYPES.add(DataComponentTypes.BUNDLE_CONTENTS);
|
||||
FORBIDDEN_TYPES.add(DataComponentTypes.CUSTOM_MODEL_DATA);
|
||||
|
||||
FORBIDDEN_TYPES.add(DataComponentTypes.ATTRIBUTE_MODIFIERS);
|
||||
FORBIDDEN_TYPES.add(DataComponentTypes.TOOL);
|
||||
FORBIDDEN_TYPES.add(DataComponentTypes.WEAPON);
|
||||
FORBIDDEN_TYPES.add(DataComponentTypes.FOOD);
|
||||
FORBIDDEN_TYPES.add(DataComponentTypes.CONSUMABLE);
|
||||
FORBIDDEN_TYPES.add(DataComponentTypes.POTION_CONTENTS);
|
||||
FORBIDDEN_TYPES.add(DataComponentTypes.STORED_ENCHANTMENTS);
|
||||
FORBIDDEN_TYPES.add(DataComponentTypes.CAN_BREAK);
|
||||
FORBIDDEN_TYPES.add(DataComponentTypes.CAN_PLACE_ON);
|
||||
FORBIDDEN_TYPES.add(DataComponentTypes.MAX_DAMAGE);
|
||||
FORBIDDEN_TYPES.add(DataComponentTypes.USE_REMAINDER);
|
||||
FORBIDDEN_TYPES.add(DataComponentTypes.USE_COOLDOWN);
|
||||
FORBIDDEN_TYPES.add(DataComponentTypes.SUSPICIOUS_STEW_EFFECTS);
|
||||
FORBIDDEN_TYPES.add(DataComponentTypes.CHARGED_PROJECTILES);
|
||||
FORBIDDEN_TYPES.add(DataComponentTypes.INTANGIBLE_PROJECTILE);
|
||||
FORBIDDEN_TYPES.add(DataComponentTypes.FIREWORKS);
|
||||
FORBIDDEN_TYPES.add(DataComponentTypes.FIREWORK_EXPLOSION);
|
||||
FORBIDDEN_TYPES.add(DataComponentTypes.EQUIPPABLE);
|
||||
FORBIDDEN_TYPES.add(DataComponentTypes.REPAIR_COST);
|
||||
FORBIDDEN_TYPES.add(DataComponentTypes.ENCHANTABLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -98,10 +98,12 @@ public class FightSystem extends JavaPlugin {
|
||||
new StateDependentListener(ArenaMode.All, FightState.All, BountifulWrapper.impl.newDenyArrowPickupListener());
|
||||
new OneShotStateDependent(ArenaMode.All, FightState.PreSchemSetup, () -> Fight.playSound(SWSound.BLOCK_NOTE_PLING.getSound(), 100.0f, 2.0f));
|
||||
new OneShotStateDependent(ArenaMode.Test, FightState.All, WorldEditRendererCUIEditor::new);
|
||||
try {
|
||||
Bukkit.getWorlds().get(0).setGameRule(GameRule.REDUCED_DEBUG_INFO, ArenaMode.AntiTest.contains(Config.mode));
|
||||
} catch (Exception e) {
|
||||
// Ignore if failed!
|
||||
if (Core.getVersion() >= 19) {
|
||||
try {
|
||||
Bukkit.getWorlds().get(0).setGameRule(GameRule.REDUCED_DEBUG_INFO, ArenaMode.AntiTest.contains(Config.mode));
|
||||
} catch (Exception e) {
|
||||
// Ignore if failed!
|
||||
}
|
||||
}
|
||||
|
||||
techHider = new TechHiderWrapper();
|
||||
|
||||
+9
-24
@@ -35,10 +35,7 @@ import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.InventoryAction;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||
import org.bukkit.event.inventory.InventoryOpenEvent;
|
||||
import org.bukkit.event.inventory.*;
|
||||
import org.bukkit.event.player.PlayerMoveEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
@@ -81,25 +78,8 @@ public class PersonalKitCreator implements Listener {
|
||||
if(!openKitCreators.containsKey(e.getWhoClicked()))
|
||||
return;
|
||||
|
||||
Player player = (Player) e.getWhoClicked();
|
||||
//Deny bad items
|
||||
if(Kit.isBadItem(e.getCursor()))
|
||||
e.setCancelled(true);
|
||||
|
||||
/* Should the inventory reset? */
|
||||
if(e.getAction() != InventoryAction.PLACE_ALL)
|
||||
return;
|
||||
|
||||
ItemStack[] items = e.getWhoClicked().getInventory().getContents();
|
||||
for(int i = 0; i < items.length; i++){
|
||||
ItemStack stack = items[i];
|
||||
if(stack != null && i != e.getSlot())
|
||||
return;
|
||||
}
|
||||
|
||||
FightPlayer fightPlayer = Fight.getFightPlayer(player);
|
||||
assert fightPlayer != null;
|
||||
Bukkit.getScheduler().runTaskLater(FightSystem.getPlugin(), () -> fightPlayer.getKit().loadToPlayer(player), 1);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
@@ -117,7 +97,10 @@ public class PersonalKitCreator implements Listener {
|
||||
if(backup == null)
|
||||
return;
|
||||
|
||||
backup.close();
|
||||
InventoryType type = e.getInventory().getType();
|
||||
if(type != InventoryType.PLAYER && type != InventoryType.CREATIVE) {
|
||||
backup.close();
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
@@ -126,7 +109,7 @@ public class PersonalKitCreator implements Listener {
|
||||
if(backup == null)
|
||||
return;
|
||||
|
||||
backup.close();
|
||||
Bukkit.getScheduler().runTaskLater(FightSystem.getPlugin(), backup::close, 1);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
@@ -151,9 +134,11 @@ public class PersonalKitCreator implements Listener {
|
||||
}
|
||||
|
||||
private void close(){
|
||||
openKitCreators.remove(player);
|
||||
Kit kit1 = new Kit(kit.getName(), player);
|
||||
kit1.removeBadItems();
|
||||
|
||||
|
||||
openKitCreators.remove(player);
|
||||
kit1.toPersonalKit(kit);
|
||||
backup.loadToPlayer(player);
|
||||
player.setGameMode(GameMode.SURVIVAL);
|
||||
|
||||
@@ -67,9 +67,10 @@ tasks.register<FightServer>("WarGear21") {
|
||||
description = "Run a WarGear 1.21 Fight Server"
|
||||
dependsOn(":SpigotCore:shadowJar")
|
||||
dependsOn(":FightSystem:shadowJar")
|
||||
dependsOn(":KotlinCore:shadowJar")
|
||||
template = "WarGear21"
|
||||
worldName = "arenas/Pentraki"
|
||||
config = "WarGear20.yml"
|
||||
worldName = "arenas/Colosso"
|
||||
config = "WarGear21.yml"
|
||||
jar = "/jars/paper-1.21.6.jar"
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2026 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
steamwar.kotlin
|
||||
alias(libs.plugins.shadow)
|
||||
}
|
||||
|
||||
java {
|
||||
targetCompatibility = JavaVersion.VERSION_21
|
||||
sourceCompatibility = JavaVersion.VERSION_21
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(project(":ModularFightSystem:GameCore"))
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2026 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.fightsystem
|
||||
|
||||
import de.steamwar.fightsystem.state.FightState
|
||||
|
||||
class FightSystem {
|
||||
}
|
||||
|
||||
fun test() {
|
||||
FightState.register()
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2026 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.fightsystem.state
|
||||
|
||||
import de.steamwar.modularfightsystem.complement
|
||||
import de.steamwar.modularfightsystem.enumSetAll
|
||||
import de.steamwar.modularfightsystem.enumSetOf
|
||||
import de.steamwar.modularfightsystem.state.FightStateMachine
|
||||
|
||||
enum class FightState {
|
||||
PRE_LEADER_SETUP,
|
||||
PRE_SCHEM_SETUP,
|
||||
POST_SCHEM_SETUP,
|
||||
PRE_RUNNING,
|
||||
RUNNING,
|
||||
SPECTATE;
|
||||
|
||||
companion object : FightStateMachine<FightState>(PRE_LEADER_SETUP) {
|
||||
val All = enumSetAll<FightState>()
|
||||
|
||||
val PreLeaderSetup = enumSetOf(PRE_LEADER_SETUP)
|
||||
val PreSchemSetup = enumSetOf(PRE_SCHEM_SETUP)
|
||||
val PostSchemSetup = enumSetOf(POST_SCHEM_SETUP)
|
||||
val PreRunning = enumSetOf(PRE_RUNNING)
|
||||
val Running = enumSetOf(RUNNING)
|
||||
val Spectate = enumSetOf(SPECTATE)
|
||||
|
||||
val Setup = enumSetOf(PRE_LEADER_SETUP, PRE_SCHEM_SETUP, POST_SCHEM_SETUP)
|
||||
val Ingame = enumSetOf(PRE_RUNNING, RUNNING)
|
||||
val TeamFix = enumSetOf(PRE_RUNNING, RUNNING, SPECTATE)
|
||||
val Schem = enumSetOf(PRE_LEADER_SETUP, PRE_SCHEM_SETUP).complement()
|
||||
val Recording = enumSetOf(PRE_LEADER_SETUP, PRE_SCHEM_SETUP, SPECTATE).complement()
|
||||
val AntiRunning = enumSetOf(RUNNING).complement()
|
||||
val AntiIngame = enumSetOf(PRE_RUNNING, RUNNING).complement()
|
||||
val AntiSpectate = enumSetOf(SPECTATE).complement()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2026 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
steamwar.kotlin
|
||||
}
|
||||
|
||||
java {
|
||||
targetCompatibility = JavaVersion.VERSION_21
|
||||
sourceCompatibility = JavaVersion.VERSION_21
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(libs.paperapi21)
|
||||
compileOnly(libs.nms21)
|
||||
compileOnly(project(":SpigotCore", "default"))
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2026 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.modularfightsystem
|
||||
|
||||
enum class ArenaMode {
|
||||
NORMAL,
|
||||
EVENT,
|
||||
TEST,
|
||||
CHECK,
|
||||
PREPARE,
|
||||
REPLAY;
|
||||
|
||||
companion object {
|
||||
val All = enumSetAll<ArenaMode>()
|
||||
|
||||
val Normal = enumSetOf(NORMAL)
|
||||
val Event = enumSetOf(EVENT)
|
||||
val Test = enumSetOf(TEST)
|
||||
val Check = enumSetOf(CHECK)
|
||||
val Prepare = enumSetOf(PREPARE)
|
||||
val Replay = enumSetOf(REPLAY)
|
||||
|
||||
val AntiReplay = Replay.complement()
|
||||
val AntiTest = Test.complement()
|
||||
val AntiEvent = Event.complement()
|
||||
val AntiTestCheckPrepare = enumSetOf(TEST, CHECK, PREPARE).complement()
|
||||
val AntiPrepare = Prepare.complement()
|
||||
val VariableTeams = enumSetOf(EVENT, REPLAY, CHECK).complement()
|
||||
val ManualTeams = enumSetOf(EVENT, REPLAY).complement()
|
||||
val RankedEvent = enumSetOf(EVENT, REPLAY)
|
||||
val Restartable = enumSetOf(NORMAL, TEST)
|
||||
val NotRestartable = enumSetOf(EVENT, REPLAY)
|
||||
val SoloLeader = enumSetOf(TEST, CHECK, PREPARE)
|
||||
val NotOnBau = enumSetOf(TEST, CHECK, PREPARE, REPLAY).complement()
|
||||
val SeriousFight = enumSetOf(TEST, CHECK, REPLAY).complement()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2026 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.modularfightsystem
|
||||
|
||||
import de.steamwar.message.Message
|
||||
import org.bukkit.plugin.Plugin
|
||||
|
||||
object Config {
|
||||
lateinit var plugin: Plugin
|
||||
|
||||
val mode = ArenaMode.TEST
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2026 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.modularfightsystem
|
||||
|
||||
import java.util.Collections
|
||||
import java.util.EnumSet
|
||||
|
||||
typealias KEnumSet<T> = Set<T>
|
||||
|
||||
inline fun <reified T> enumSetOf(): KEnumSet<T> where T : Enum<T> = Collections.unmodifiableSet(EnumSet.noneOf(T::class.java))
|
||||
|
||||
inline fun <reified T> enumSetAll(): KEnumSet<T> where T : Enum<T> = Collections.unmodifiableSet(EnumSet.allOf(T::class.java))
|
||||
|
||||
inline fun <reified T> enumSetOf(vararg elements: T): KEnumSet<T> where T : Enum<T> = Collections.unmodifiableSet(EnumSet.copyOf(elements.toSet()))
|
||||
|
||||
fun <T> KEnumSet<T>.complement(): KEnumSet<T> where T: Enum<T> = Collections.unmodifiableSet(EnumSet.complementOf(EnumSet.copyOf(this)))
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2026 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.modularfightsystem.countdown
|
||||
|
||||
import de.steamwar.modularfightsystem.Config
|
||||
import net.kyori.adventure.text.Component
|
||||
import net.kyori.adventure.text.ComponentLike
|
||||
import org.bukkit.Bukkit
|
||||
import org.bukkit.Sound
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.scheduler.BukkitTask
|
||||
|
||||
abstract class Countdown(val totalTime: Int, val appendix: ComponentLike, val sound: Sound?, val level: Boolean) {
|
||||
var time = totalTime
|
||||
private var task: BukkitTask? = null
|
||||
|
||||
abstract fun countdownFinished()
|
||||
|
||||
fun enable() {
|
||||
time = totalTime
|
||||
task = Bukkit.getScheduler().runTaskTimer(Config.plugin, this::count, 0, 20)
|
||||
countdowns.add(this)
|
||||
show()
|
||||
}
|
||||
|
||||
fun disable() {
|
||||
if (task != null) {
|
||||
task!!.cancel()
|
||||
countdowns.remove(this)
|
||||
task = null
|
||||
}
|
||||
}
|
||||
|
||||
private fun show() {
|
||||
when(time) {
|
||||
900, 600, 300, 180, 120 -> broadcast("COUNTDOWN_MINUTES", 60)
|
||||
60, 30, 20, 15, 10, 5, 4, 3, 2 -> broadcast("COUNTDOWN_SECONDS", 1)
|
||||
1 -> broadcast("COUNTDOWN_SECOND", 1)
|
||||
0 -> {
|
||||
playSound()
|
||||
|
||||
disable()
|
||||
countdownFinished()
|
||||
}
|
||||
}
|
||||
|
||||
if (level) {
|
||||
Bukkit.getOnlinePlayers().forEach { it.level = time }
|
||||
}
|
||||
}
|
||||
|
||||
private fun count() {
|
||||
time--
|
||||
show()
|
||||
}
|
||||
|
||||
protected fun broadcast(message: String, divisor: Int) {
|
||||
playSound()
|
||||
|
||||
Bukkit.getOnlinePlayers().forEach { sendCountdownMessage(it, message, totalTime / divisor, appendix) }
|
||||
}
|
||||
|
||||
fun playSound() = sound?.let { Bukkit.getOnlinePlayers().forEach { it.playSound(it.location, sound, 100f, 1f) } }
|
||||
|
||||
fun sendCountdownMessage(p: Player, message: String, displayTime: Int, appendix: ComponentLike) =
|
||||
p.sendMessage(Component.translatable(message, Component.text(displayTime), appendix))
|
||||
|
||||
companion object {
|
||||
private val countdowns = mutableListOf<Countdown>()
|
||||
|
||||
fun skip() {
|
||||
if (countdowns.isEmpty()) return
|
||||
|
||||
val smallestTime = countdowns.minOf { it.time }
|
||||
|
||||
countdowns.forEach { it.also { it.time -= smallestTime }.show() }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2026 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.modularfightsystem.fight
|
||||
|
||||
class FightPlayer {
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2026 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.modularfightsystem.fight
|
||||
|
||||
class FightTeam()
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2026 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.modularfightsystem.state
|
||||
|
||||
abstract class FightStateMachine<T: Enum<*>>(initialState: T) {
|
||||
init {
|
||||
instance = this
|
||||
}
|
||||
|
||||
var state: T = initialState
|
||||
set(value) {
|
||||
field = value
|
||||
|
||||
stateDependents.forEach { dependent -> dependent.enabled = value in dependent.states }
|
||||
}
|
||||
|
||||
private val stateDependents = mutableListOf<StateDependent>()
|
||||
|
||||
fun register(stateDependent: StateDependent) {
|
||||
if (stateDependent.states.isEmpty() or !stateDependent.active) return
|
||||
stateDependents.add(stateDependent)
|
||||
stateDependent.enabled = state in stateDependent.states
|
||||
}
|
||||
|
||||
companion object {
|
||||
lateinit var instance: FightStateMachine<*>
|
||||
private set
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2026 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.modularfightsystem.state
|
||||
|
||||
import de.steamwar.modularfightsystem.ArenaMode
|
||||
import de.steamwar.modularfightsystem.Config
|
||||
import de.steamwar.modularfightsystem.KEnumSet
|
||||
|
||||
class OneShotStateDependent(active: Boolean, states: KEnumSet<*>, val runnable: () -> Unit): StateDependent(active, states) {
|
||||
constructor(modes: KEnumSet<ArenaMode>, states: KEnumSet<*>, runnable: () -> Unit) : this(Config.mode in modes, states, runnable)
|
||||
|
||||
init {
|
||||
register()
|
||||
}
|
||||
|
||||
override fun enable() = runnable()
|
||||
override fun disable() = Unit
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2026 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.modularfightsystem.state
|
||||
|
||||
import de.steamwar.modularfightsystem.ArenaMode
|
||||
import de.steamwar.modularfightsystem.Config
|
||||
import de.steamwar.modularfightsystem.KEnumSet
|
||||
|
||||
abstract class StateDependent(val active: Boolean, val states: KEnumSet<*>) {
|
||||
constructor(modes: KEnumSet<ArenaMode>, states: KEnumSet<*>) : this(Config.mode in modes, states)
|
||||
|
||||
var enabled = false
|
||||
set(value) {
|
||||
if (value != field) if (value) enable() else disable()
|
||||
field = value
|
||||
}
|
||||
|
||||
fun register() {
|
||||
FightStateMachine.instance.register(this)
|
||||
}
|
||||
|
||||
abstract fun enable()
|
||||
abstract fun disable()
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2026 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.modularfightsystem.state
|
||||
|
||||
import de.steamwar.command.SWCommand
|
||||
import de.steamwar.modularfightsystem.ArenaMode
|
||||
import de.steamwar.modularfightsystem.KEnumSet
|
||||
|
||||
class StateDependentCommand(mode: KEnumSet<ArenaMode>, states: KEnumSet<*>, val command: SWCommand): StateDependent(mode, states) {
|
||||
init {
|
||||
register()
|
||||
}
|
||||
|
||||
override fun enable() = command.register()
|
||||
override fun disable() = command.unregister()
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2026 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.modularfightsystem.state
|
||||
|
||||
import de.steamwar.modularfightsystem.ArenaMode
|
||||
import de.steamwar.modularfightsystem.Config
|
||||
import de.steamwar.modularfightsystem.KEnumSet
|
||||
import org.bukkit.Bukkit
|
||||
import org.bukkit.scheduler.BukkitTask
|
||||
|
||||
class StateDependentTask(active: Boolean, states: KEnumSet<*>, val runnable: () -> Unit, val delay: Long, val period: Long): StateDependent(active, states) {
|
||||
constructor(modes: KEnumSet<ArenaMode>, states: KEnumSet<*>, runnable: () -> Unit, delay: Long, period: Long) : this(
|
||||
Config.mode in modes, states, runnable, delay, period)
|
||||
|
||||
init {
|
||||
register()
|
||||
}
|
||||
|
||||
var task: BukkitTask? = null
|
||||
|
||||
override fun enable() {
|
||||
task = Bukkit.getScheduler().runTaskTimer(Config.plugin, runnable, delay, period)
|
||||
}
|
||||
|
||||
override fun disable() {
|
||||
task?.cancel()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2026 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
`java-library`
|
||||
}
|
||||
+29
-16
@@ -25,7 +25,6 @@ import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
import de.steamwar.core.Core;
|
||||
import de.steamwar.schematicsystem.autocheck.AutoChecker.InventoryScanResult;
|
||||
import de.steamwar.sql.GameModeConfig;
|
||||
import de.steamwar.sql.SchematicType;
|
||||
import org.bukkit.Material;
|
||||
@@ -51,8 +50,7 @@ public class AutoChecker15 implements AutoChecker.IAutoChecker {
|
||||
result.getBlockCounts().merge(material, 1, Integer::sum);
|
||||
|
||||
if(AutoCheckerItems.impl.getInventoryMaterials().contains(material)) {
|
||||
InventoryScanResult inventoryResult = checkInventory(result, block, material, new BlockPos(x, y, z));
|
||||
result.getInventoryScans().put(new BlockPos(x, y, z), inventoryResult);
|
||||
checkInventory(result, block, material, new BlockPos(x, y, z));
|
||||
}
|
||||
|
||||
if(x == min.getBlockX() || x == max.getBlockX() || y == max.getBlockY() || z == min.getBlockZ() || z == max.getBlockZ()) {
|
||||
@@ -64,24 +62,41 @@ public class AutoChecker15 implements AutoChecker.IAutoChecker {
|
||||
return result;
|
||||
}
|
||||
|
||||
private InventoryScanResult checkInventory(AutoChecker.BlockScanResult result, BaseBlock block, Material material, BlockPos pos) {
|
||||
private static final Map<Material, Set<Material>> itemsInInv = new EnumMap<>(Material.class);
|
||||
|
||||
static {
|
||||
itemsInInv.put(Material.BUCKET, EnumSet.of(Material.DISPENSER));
|
||||
itemsInInv.put(Material.TNT, EnumSet.of(
|
||||
Material.CHEST, Material.BARREL, Material.SHULKER_BOX, Material.BLACK_SHULKER_BOX,
|
||||
Material.BLUE_SHULKER_BOX, Material.BROWN_SHULKER_BOX, Material.CYAN_SHULKER_BOX,
|
||||
Material.GRAY_SHULKER_BOX, Material.GREEN_SHULKER_BOX, Material.LIGHT_BLUE_SHULKER_BOX,
|
||||
Material.LIGHT_GRAY_SHULKER_BOX, Material.LIME_SHULKER_BOX, Material.MAGENTA_SHULKER_BOX,
|
||||
Material.ORANGE_SHULKER_BOX, Material.PINK_SHULKER_BOX, Material.PURPLE_SHULKER_BOX,
|
||||
Material.RED_SHULKER_BOX, Material.WHITE_SHULKER_BOX, Material.YELLOW_SHULKER_BOX
|
||||
));
|
||||
itemsInInv.put(Material.FIRE_CHARGE, EnumSet.of(Material.DISPENSER));
|
||||
itemsInInv.put(Material.ARROW, EnumSet.of(Material.DISPENSER));
|
||||
AutoCheckerItems.impl.getAllowedMaterialsInInventory().forEach(material -> itemsInInv.put(material, AutoCheckerItems.impl.getInventoryMaterials()));
|
||||
}
|
||||
|
||||
private void checkInventory(AutoChecker.BlockScanResult result, BaseBlock block, Material material, BlockPos pos) {
|
||||
CompoundTag nbt = block.getNbtData();
|
||||
if(nbt == null) {
|
||||
result.getDefunctNbt().add(pos);
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if(material == Material.JUKEBOX && nbt.getValue().containsKey("RecordItem")){
|
||||
result.getRecords().add(pos);
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
|
||||
List<CompoundTag> items = nbt.getList("Items", CompoundTag.class);
|
||||
if(items.isEmpty())
|
||||
return null; //Leeres Inventar
|
||||
return; //Leeres Inventar
|
||||
|
||||
Map<Material, Integer> inventoryItemCounts = new HashMap<>();
|
||||
int counter = 0;
|
||||
for(CompoundTag item : items){
|
||||
if(!item.containsKey("id")){
|
||||
result.getDefunctNbt().add(pos);
|
||||
@@ -92,18 +107,16 @@ public class AutoChecker15 implements AutoChecker.IAutoChecker {
|
||||
if(itemType == null) //Leere Slots
|
||||
continue;
|
||||
|
||||
|
||||
|
||||
|
||||
if (!itemsInInv.getOrDefault(itemType, EnumSet.noneOf(Material.class)).contains(material)) {
|
||||
result.getForbiddenItems().computeIfAbsent(pos, blockVector3 -> new HashSet<>()).add(itemType);
|
||||
} else if(material == Material.DISPENSER && (itemType == Material.ARROW || itemType == Material.FIRE_CHARGE)) {
|
||||
counter += Core.getVersion() >= 21 ? item.getInt("count") : item.getByte("Count");
|
||||
}
|
||||
if (item.containsKey("tag")) {
|
||||
result.getForbiddenNbt().computeIfAbsent(pos, blockVector3 -> new HashSet<>()).add(itemType);
|
||||
}
|
||||
else {
|
||||
int count = Core.getVersion() >= 21 ? item.getInt("count") : item.getByte("Count");
|
||||
inventoryItemCounts.merge(itemType, count, Integer::sum);
|
||||
}
|
||||
}
|
||||
return new InventoryScanResult(material, inventoryItemCounts);
|
||||
result.getDispenserItems().put(pos, counter);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
steamwar.java
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(project(":SpigotCore", "default"))
|
||||
compileOnly(project(":SchematicSystem:SchematicSystem_Core", "default"))
|
||||
|
||||
compileOnly(libs.paperapi21) {
|
||||
attributes {
|
||||
// Very Hacky, but it works
|
||||
attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 21)
|
||||
}
|
||||
}
|
||||
|
||||
compileOnly(libs.nms21)
|
||||
compileOnly(libs.fawe21)
|
||||
}
|
||||
+137
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2026 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.schematicsystem.autocheck;
|
||||
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.entity.Entity;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
import de.steamwar.core.Core;
|
||||
import de.steamwar.sql.GameModeConfig;
|
||||
import org.bukkit.Material;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class AutoChecker21 implements AutoChecker.IAutoChecker {
|
||||
|
||||
public AutoChecker.BlockScanResult scan(Clipboard clipboard, GameModeConfig<Material, String> type) {
|
||||
AutoChecker.BlockScanResult result = new AutoChecker.BlockScanResult();
|
||||
BlockVector3 min = clipboard.getMinimumPoint();
|
||||
BlockVector3 max = clipboard.getMaximumPoint();
|
||||
for (int x = min.getBlockX(); x <= max.getBlockX(); x++) {
|
||||
for (int y = min.getBlockY(); y <= max.getBlockY(); y++) {
|
||||
for (int z = min.getBlockZ(); z <= max.getBlockZ(); z++) {
|
||||
final BaseBlock block = clipboard.getFullBlock(BlockVector3.at(x, y, z));
|
||||
final Material material = Material.matchMaterial(block.getBlockType().getId());
|
||||
if (material == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
result.getBlockCounts().merge(material, 1, Integer::sum);
|
||||
|
||||
if (AutoCheckerItems.impl.getInventoryMaterials().contains(material)) {
|
||||
checkInventory(result, block, material, new BlockPos(x, y, z), type);
|
||||
}
|
||||
|
||||
if (x == min.getBlockX() || x == max.getBlockX() || y == max.getBlockY() || z == min.getBlockZ() || z == max.getBlockZ()) {
|
||||
result.getDesignBlocks().computeIfAbsent(material, m -> new ArrayList<>()).add(new BlockPos(x, y, z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static final Map<Material, Set<Material>> itemsInInv = new EnumMap<>(Material.class);
|
||||
|
||||
static {
|
||||
itemsInInv.put(Material.BUCKET, EnumSet.of(Material.DISPENSER));
|
||||
itemsInInv.put(Material.TNT, EnumSet.of(Material.CHEST, Material.BARREL, Material.SHULKER_BOX, Material.BLACK_SHULKER_BOX, Material.BLUE_SHULKER_BOX,
|
||||
Material.BROWN_SHULKER_BOX, Material.CYAN_SHULKER_BOX, Material.GRAY_SHULKER_BOX, Material.GREEN_SHULKER_BOX, Material.LIGHT_BLUE_SHULKER_BOX,
|
||||
Material.LIGHT_GRAY_SHULKER_BOX, Material.LIME_SHULKER_BOX, Material.MAGENTA_SHULKER_BOX, Material.ORANGE_SHULKER_BOX,
|
||||
Material.PINK_SHULKER_BOX, Material.PURPLE_SHULKER_BOX, Material.RED_SHULKER_BOX, Material.WHITE_SHULKER_BOX, Material.YELLOW_SHULKER_BOX));
|
||||
itemsInInv.put(Material.FIRE_CHARGE, EnumSet.of(Material.DISPENSER));
|
||||
itemsInInv.put(Material.ARROW, EnumSet.of(Material.DISPENSER));
|
||||
AutoCheckerItems.impl.getAllowedMaterialsInInventory().forEach(material -> itemsInInv.put(material, AutoCheckerItems.impl.getInventoryMaterials()));
|
||||
}
|
||||
|
||||
private void checkInventory(AutoChecker.BlockScanResult result, BaseBlock block, Material material, BlockPos pos, GameModeConfig<Material, String> type) {
|
||||
CompoundTag nbt = block.getNbtData();
|
||||
if (nbt == null) {
|
||||
result.getDefunctNbt().add(pos);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (material == Material.JUKEBOX && nbt.getValue().containsKey("RecordItem")) {
|
||||
result.getRecords().add(pos);
|
||||
return;
|
||||
}
|
||||
|
||||
List<CompoundTag> items = nbt.getList("Items", CompoundTag.class);
|
||||
if (items.isEmpty())
|
||||
return; // Leeres Inventar
|
||||
|
||||
int counter = 0;
|
||||
int windChargeCount = 0;
|
||||
for (CompoundTag item : items) {
|
||||
if (!item.containsKey("id")) {
|
||||
result.getDefunctNbt().add(pos);
|
||||
continue;
|
||||
}
|
||||
|
||||
Material itemType = Material.matchMaterial(item.getString("id"));
|
||||
if (itemType == null) // Leere Slots
|
||||
continue;
|
||||
|
||||
if(type.Schematic.Type.getName().equals("wargearseason26") && material == Material.DISPENSER && itemType == Material.WIND_CHARGE) {
|
||||
windChargeCount += item.getInt("count");
|
||||
}
|
||||
else if (!itemsInInv.getOrDefault(itemType, EnumSet.noneOf(Material.class)).contains(material)) {
|
||||
result.getForbiddenItems().computeIfAbsent(pos, blockVector3 -> new HashSet<>()).add(itemType);
|
||||
} else if (material == Material.DISPENSER && (itemType == Material.ARROW || itemType == Material.FIRE_CHARGE)) {
|
||||
counter += Core.getVersion() >= 21 ? item.getInt("count") : item.getByte("Count");
|
||||
}
|
||||
if (item.containsKey("tag")) {
|
||||
result.getForbiddenNbt().computeIfAbsent(pos, blockVector3 -> new HashSet<>()).add(itemType);
|
||||
}
|
||||
}
|
||||
result.getDispenserItems().put(pos, counter);
|
||||
result.getWindChargeCount().put(pos, windChargeCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AutoCheckerResult check(Clipboard clipboard, GameModeConfig<Material, String> type) {
|
||||
return AutoCheckerResult.builder().type(type).height(clipboard.getDimensions().getBlockY()).width(clipboard.getDimensions().getBlockX())
|
||||
.depth(clipboard.getDimensions().getBlockZ()).blockScanResult(scan(clipboard, type))
|
||||
.entities(clipboard.getEntities().stream().map(Entity::getLocation)
|
||||
.map(blockVector3 -> new BlockPos(blockVector3.getBlockX(), blockVector3.getBlockY(), blockVector3.getBlockZ()))
|
||||
.collect(Collectors.toList()))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AutoCheckerResult sizeCheck(Clipboard clipboard, GameModeConfig<Material, String> type) {
|
||||
return AutoCheckerResult.builder().type(type).height(clipboard.getDimensions().getBlockY()).width(clipboard.getDimensions().getBlockX())
|
||||
.depth(clipboard.getDimensions().getBlockZ()).build();
|
||||
}
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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.schematicsystem.autocheck;
|
||||
|
||||
import org.bukkit.Material;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class AutoCheckerItems21 implements AutoCheckerItems {
|
||||
|
||||
private static final Set<Material> INVENTORY = EnumSet.of(Material.BARREL, Material.BLAST_FURNACE, Material.BREWING_STAND, Material.CAMPFIRE,
|
||||
Material.CHEST, Material.DISPENSER, Material.DROPPER, Material.FURNACE, Material.HOPPER, Material.JUKEBOX, Material.SHULKER_BOX,
|
||||
Material.WHITE_SHULKER_BOX, Material.ORANGE_SHULKER_BOX, Material.MAGENTA_SHULKER_BOX, Material.LIGHT_BLUE_SHULKER_BOX, Material.YELLOW_SHULKER_BOX,
|
||||
Material.LIME_SHULKER_BOX, Material.PINK_SHULKER_BOX, Material.GRAY_SHULKER_BOX, Material.LIGHT_GRAY_SHULKER_BOX, Material.CYAN_SHULKER_BOX,
|
||||
Material.PURPLE_SHULKER_BOX, Material.BLUE_SHULKER_BOX, Material.BROWN_SHULKER_BOX, Material.GREEN_SHULKER_BOX, Material.RED_SHULKER_BOX,
|
||||
Material.BLACK_SHULKER_BOX, Material.SMOKER, Material.TRAPPED_CHEST);
|
||||
|
||||
private static final Set<Material> FLOWERS = EnumSet.of(Material.CORNFLOWER, Material.POPPY, Material.FERN, Material.DANDELION, Material.BLUE_ORCHID,
|
||||
Material.ALLIUM, Material.AZURE_BLUET, Material.RED_TULIP, Material.ORANGE_TULIP, Material.WHITE_TULIP, Material.PINK_TULIP, Material.OXEYE_DAISY,
|
||||
Material.LILY_OF_THE_VALLEY, Material.WITHER_ROSE, Material.SUNFLOWER, Material.DIAMOND_HORSE_ARMOR, Material.IRON_HORSE_ARMOR,
|
||||
Material.GOLDEN_HORSE_ARMOR, Material.LEATHER_HORSE_ARMOR, Material.HONEY_BOTTLE, Material.LILAC, Material.ROSE_BUSH, Material.PEONY,
|
||||
Material.TALL_GRASS, Material.LARGE_FERN);
|
||||
|
||||
@Override
|
||||
public Set<Material> getInventoryMaterials() {
|
||||
return INVENTORY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Material> getAllowedMaterialsInInventory() {
|
||||
return FLOWERS;
|
||||
}
|
||||
}
|
||||
@@ -262,6 +262,8 @@ AUTO_CHECKER_RESULT_BLOCKS=§7Blocks: §c{0}§7, Max: §e{1}
|
||||
AUTO_CHECKER_RESULT_UNKNOWN_MATERIAL=§7Unknown block: §c{0}
|
||||
AUTO_CHECKER_RESULT_TOO_MANY_BLOCK=§7{0}: §c{1}§7, Max: §e{2}
|
||||
AUTO_CHECKER_RESULT_FORBIDDEN_BLOCK=§7Forbidden block: §c{0}
|
||||
AUTO_CHECKER_RESULT_WIND_CHARGES=§7Windcharges: §c{0}§7, Max: §e2048
|
||||
AUTO_CHECKER_RESULT_WIND_CHARGES_DISPENSER=§7Dispenser: §c[{0}, {1}, {2}]§7, Windcharges: §c{3}§7
|
||||
AUTO_CHECKER_RESULT_FORBIDDEN_ITEM=§7Forbidden Item: [{0}, {1}, {2}] -> §c{3}
|
||||
AUTO_CHECKER_RESULT_DEFUNCT_NBT=§7Defunct NBT: §7[{0}, {1}, {2}]
|
||||
AUTO_CHECKER_RESULT_DESIGN_BLOCK=§7{0} in Design: [{1}, {2}, {3}]
|
||||
|
||||
@@ -242,6 +242,8 @@ AUTO_CHECKER_RESULT_BLOCKS=§7Blöcke: §c{0}§7, Max: §e{1}
|
||||
AUTO_CHECKER_RESULT_UNKNOWN_MATERIAL=§7Unbekannter Block: §c{0}
|
||||
AUTO_CHECKER_RESULT_TOO_MANY_BLOCK=§7{0}: §c{1}§7, Max: §e{2}
|
||||
AUTO_CHECKER_RESULT_FORBIDDEN_BLOCK=§7Verbotener Block: §c{0}
|
||||
AUTO_CHECKER_RESULT_WIND_CHARGES=§7Windcharges: §c{0}§7, Max: §e2048
|
||||
AUTO_CHECKER_RESULT_WIND_CHARGES_DISPENSER=§7Werfer: §c[{0}, {1}, {2}]§7, Windcharges: §c{3}§7
|
||||
AUTO_CHECKER_RESULT_FORBIDDEN_ITEM=§7Verbotener gegenstand: [{0}, {1}, {2}] -> §c{3}
|
||||
AUTO_CHECKER_RESULT_DEFUNCT_NBT=§7Keine NBT-Daten: §c[{0}, {1}, {2}]
|
||||
AUTO_CHECKER_RESULT_DESIGN_BLOCK=§7{0} im Design: [{1}, {2}, {3}]
|
||||
|
||||
+3
-17
@@ -24,13 +24,11 @@ import de.steamwar.core.VersionDependent;
|
||||
import de.steamwar.sql.GameModeConfig;
|
||||
import de.steamwar.schematicsystem.SchematicSystem;
|
||||
import de.steamwar.sql.SchematicType;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
import org.bukkit.Material;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class AutoChecker {
|
||||
|
||||
@@ -49,14 +47,6 @@ public class AutoChecker {
|
||||
AutoCheckerResult sizeCheck(Clipboard clipboard, GameModeConfig<Material, String> type);
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
@ToString
|
||||
public static class InventoryScanResult {
|
||||
private final Material inventoryMaterial;
|
||||
private final Map<Material, Integer> itemCounts;
|
||||
}
|
||||
|
||||
@Getter
|
||||
@ToString
|
||||
public static class BlockScanResult {
|
||||
@@ -64,13 +54,9 @@ public class AutoChecker {
|
||||
private final List<BlockPos> defunctNbt = new ArrayList<>();
|
||||
private final List<BlockPos> records = new ArrayList<>();
|
||||
private final Map<Material, List<BlockPos>> designBlocks = new EnumMap<>(Material.class);
|
||||
private final Map<BlockPos, InventoryScanResult> inventoryScans = new HashMap<>();
|
||||
private final Map<BlockPos, Integer> dispenserItems = new HashMap<>();
|
||||
private final Map<BlockPos, Integer> windChargeCount = new HashMap<>();
|
||||
private final Map<BlockPos, Set<Material>> forbiddenItems = new HashMap<>();
|
||||
private final Map<BlockPos, Set<Material>> forbiddenNbt = new HashMap<>();
|
||||
|
||||
public Map<Material, Integer> getItemCounts() {
|
||||
return inventoryScans.values().stream()
|
||||
.flatMap(i -> i.getItemCounts().entrySet().stream())
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, Integer::sum));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+26
-3
@@ -52,6 +52,7 @@ public class AutoCheckerResult {
|
||||
isBlockCountOk() &&
|
||||
isLimitedBlocksOK() &&
|
||||
isDispenserItemsOK() &&
|
||||
isWindchargeCountOK() &&
|
||||
!type.isAfterDeadline() &&
|
||||
entities.isEmpty() &&
|
||||
isDesignBlastResistanceOK();
|
||||
@@ -62,11 +63,19 @@ public class AutoCheckerResult {
|
||||
!type.isAfterDeadline();
|
||||
}
|
||||
|
||||
|
||||
public boolean doInventoriesOnlyContainAllowedItems() {
|
||||
public boolean isWindchargeCountOK() {
|
||||
if( type.Schematic.Type.getName().equals("wargearseason26")) {
|
||||
int windChargesCount = blockScanResult.getWindChargeCount().values().stream().reduce(Integer::sum).orElse(0);
|
||||
return windChargesCount <= 2048;
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean isDispenserItemsOK() {
|
||||
return blockScanResult.getDispenserItems().values().stream().allMatch(i -> i <= type.Schematic.MaxDispenserItems);
|
||||
}
|
||||
|
||||
public boolean hasWarnings() {
|
||||
return blockScanResult.getDefunctNbt().isEmpty();
|
||||
@@ -129,6 +138,19 @@ public class AutoCheckerResult {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if(!isWindchargeCountOK()) {
|
||||
int windChargesCount = blockScanResult.getWindChargeCount().values().stream().reduce(Integer::sum).orElse(0);
|
||||
SchematicSystem.MESSAGE.sendPrefixless("AUTO_CHECKER_RESULT_WIND_CHARGES", p, windChargesCount, 2048);
|
||||
blockScanResult.getWindChargeCount().entrySet().stream().filter(blockVector3IntegerEntry -> blockVector3IntegerEntry.getValue() > 0).forEach(blockVector3IntegerEntry -> {
|
||||
SchematicSystem.MESSAGE.sendPrefixless("AUTO_CHECKER_RESULT_WIND_CHARGES_DISPENSER", p, SchematicSystem.MESSAGE.parse("AUTO_CHECKER_RESULT_TELEPORT_HERE", p), tpCommandTo(blockVector3IntegerEntry.getKey()),
|
||||
blockVector3IntegerEntry.getKey().getBlockX(),
|
||||
blockVector3IntegerEntry.getKey().getBlockY(),
|
||||
blockVector3IntegerEntry.getKey().getBlockZ(),
|
||||
blockVector3IntegerEntry.getValue());
|
||||
});
|
||||
}
|
||||
|
||||
blockScanResult.getDispenserItems().entrySet().stream().filter(blockVector3IntegerEntry -> blockVector3IntegerEntry.getValue() > type.Schematic.MaxDispenserItems).forEach(blockVector3IntegerEntry -> {
|
||||
SchematicSystem.MESSAGE.sendPrefixless("AUTO_CHECKER_RESULT_TOO_MANY_DISPENSER_ITEMS", p, SchematicSystem.MESSAGE.parse("AUTO_CHECKER_RESULT_TELEPORT_HERE", p), tpCommandTo(blockVector3IntegerEntry.getKey()),
|
||||
blockVector3IntegerEntry.getKey().getBlockX(),
|
||||
@@ -137,6 +159,7 @@ public class AutoCheckerResult {
|
||||
blockVector3IntegerEntry.getValue(),
|
||||
type.Schematic.MaxDispenserItems);
|
||||
});
|
||||
|
||||
blockScanResult.getRecords().forEach(blockVector3 -> {
|
||||
SchematicSystem.MESSAGE.sendPrefixless("AUTO_CHECKER_RESULT_RECORD", p, SchematicSystem.MESSAGE.parse("AUTO_CHECKER_RESULT_TELEPORT_HERE", p), tpCommandTo(blockVector3), blockVector3.getBlockX(), blockVector3.getBlockY(), blockVector3.getBlockZ());
|
||||
});
|
||||
|
||||
@@ -32,4 +32,5 @@ dependencies {
|
||||
implementation(project(":SchematicSystem:SchematicSystem_15"))
|
||||
implementation(project(":SchematicSystem:SchematicSystem_19"))
|
||||
implementation(project(":SchematicSystem:SchematicSystem_20"))
|
||||
implementation(project(":SchematicSystem:SchematicSystem_21"))
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
*/
|
||||
|
||||
plugins {
|
||||
steamwar.java
|
||||
steamwar.kotlin
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@@ -29,4 +29,5 @@ dependencies {
|
||||
|
||||
compileOnly(libs.nms14)
|
||||
compileOnly(libs.worldedit15)
|
||||
compileOnly("org.jetbrains.kotlin:kotlin-stdlib:2.2.21")
|
||||
}
|
||||
|
||||
@@ -101,6 +101,7 @@ dependencyResolutionManagement {
|
||||
library("hamcrest", "org.hamcrest:hamcrest:2.2")
|
||||
library("classindex", "org.atteo.classindex:classindex:3.13")
|
||||
|
||||
|
||||
library("spigotapi", "org.spigotmc:spigot-api:1.20-R0.1-SNAPSHOT")
|
||||
library("spigotannotations", "org.spigotmc:plugin-annotations:1.2.3-SNAPSHOT")
|
||||
library("paperapi", "io.papermc.paper:paper-api:1.19.2-R0.1-SNAPSHOT")
|
||||
@@ -222,6 +223,7 @@ include(
|
||||
"SchematicSystem:SchematicSystem_15",
|
||||
"SchematicSystem:SchematicSystem_19",
|
||||
"SchematicSystem:SchematicSystem_20",
|
||||
"SchematicSystem:SchematicSystem_21",
|
||||
"SchematicSystem:SchematicSystem_Core"
|
||||
)
|
||||
|
||||
@@ -255,3 +257,9 @@ include(
|
||||
|
||||
include("TNTLeague")
|
||||
include("WebsiteBackend")
|
||||
|
||||
include(
|
||||
"ModularFightSystem",
|
||||
"ModularFightSystem:GameCore",
|
||||
"ModularFightSystem:FightSystem"
|
||||
)
|
||||
Reference in New Issue
Block a user