Compare commits
127 Commits
BauSystem/
...
26a45fabb1
| Author | SHA1 | Date | |
|---|---|---|---|
| 26a45fabb1 | |||
| f8bb69e829 | |||
| b74b73b871 | |||
| 464d7c85bd | |||
| 285882be70 | |||
| 50780ad9bd | |||
| 45646b6ba3 | |||
| 8d1b15b019 | |||
| 2e91a5a582 | |||
| 018b9a971f | |||
| 70d0f179cc | |||
| 2166096ba5 | |||
| 3a13fc7bb9 | |||
| 01f55c4309 | |||
| d968187750 | |||
| 9e629d09a8 | |||
| d14022e69e | |||
| 6623e9d808 | |||
| 9279d9cd8e | |||
| b7963f2fe6 | |||
| 3f88ea1e57 | |||
| 8076f31a19 | |||
| 33e9b3409f | |||
| e7803dcf82 | |||
| cf52b50333 | |||
| 297aa6151d | |||
| 14be3a8e3b | |||
| 1c1e2e2efe | |||
| e30eb35792 | |||
| e94f273e21 | |||
| c76648e630 | |||
| a943dd6014 | |||
| 0d7776ec6f | |||
| 7db1d80988 | |||
| 50bd18bae7 | |||
| 89a55996fc | |||
| f494729b89 | |||
| bcabce8b23 | |||
| 376da2028b | |||
| b6cfaf8135 | |||
| 5daee0f589 | |||
| 43663ea099 | |||
| 9d1b0063b9 | |||
| e706044f44 | |||
| 332daec716 | |||
| 2daca017c2 | |||
| 7edd72ac27 | |||
| 1355b57a93 | |||
| e04f0d4ad1 | |||
| 79a6c93f8f | |||
| e36bbfd2a7 | |||
| 65cb544b64 | |||
| 8a22afab63 | |||
| caae9542f4 | |||
| 4104c60f6b | |||
| 69260a9b73 | |||
| 4fb6505aef | |||
| bb2f7cf0c1 | |||
| 8516c8e536 | |||
| 066f06a6e3 | |||
| 78e176b55e | |||
| 86a10b3e97 | |||
| d01efffb6a | |||
| fd57ba43e9 | |||
| eac0390dd3 | |||
| 03005adcd8 | |||
| 933e2119ef | |||
| 679d373a1e | |||
| 828084a3d6 | |||
| 2b782585b1 | |||
| b43965be91 | |||
| d82f306094 | |||
| 30cdbe072e | |||
| db7e1a5fc9 | |||
| 3e5055c246 | |||
| 44c06314c6 | |||
| e06742d6d2 | |||
| 62e674ed42 | |||
| 0464442b83 | |||
| c682333771 | |||
| 58ab619144 | |||
| 00de852575 | |||
| 948cf5e8db | |||
| 7aba8da5a0 | |||
| 5a77854752 | |||
| cf1422f532 | |||
| 6260e65b33 | |||
| 6db404c1e6 | |||
| b086fcaa32 | |||
| f33b3521b8 | |||
| dc72ec1b93 | |||
| 0e9c9bd4dc | |||
| 291b6b1804 | |||
| 104f0cf02d | |||
| f7662cdcba | |||
| 167b36b10c | |||
| b9b541957b | |||
| e9d107f0ed | |||
| 1e264a63a2 | |||
| 868ba4073b | |||
| 3410dd5a4b | |||
| b86a26a709 | |||
| 71238a0167 | |||
| 30ac947ebb | |||
| a7d64b5887 | |||
| d7908c8255 | |||
| 12f26b982e | |||
| 2be4118399 | |||
| 9d6981ee0c | |||
| 97a4d47aa7 | |||
| d657f9871d | |||
| a572b84016 | |||
| f1c6b4b453 | |||
| d0414c71f3 | |||
| 3530aec5e2 | |||
| cccd090357 | |||
| 3ae9a41b31 | |||
| b8b38cf777 | |||
| c1eca74dd0 | |||
| 8c23bf5bd4 | |||
| 556c8f7db1 | |||
| 5c7c982175 | |||
| d5ca1e14e1 | |||
| 4bd5d9eb0b | |||
| 60a70dfc40 | |||
| 4c98ce4aff | |||
| 617bae5a5c |
@ -0,0 +1,140 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2020 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.bausystem.utils;
|
||||
|
||||
import de.steamwar.bausystem.region.GlobalRegion;
|
||||
import de.steamwar.bausystem.utils.bossbar.BossBarService;
|
||||
import de.steamwar.bausystem.utils.tps.TPSFreezeUtils;
|
||||
import de.steamwar.bausystem.utils.tps.TPSLimitUtils;
|
||||
import de.steamwar.core.TPSWarpUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
public class TickManager15 implements TickManager, Listener {
|
||||
|
||||
private static float currentTPSLimit = 20;
|
||||
private boolean currentlyStepping = false;
|
||||
private float currentLimit;
|
||||
private int stepsTotal;
|
||||
private int stepsLeft;
|
||||
|
||||
@Override
|
||||
public boolean canFreeze() {
|
||||
return TPSFreezeUtils.isCanFreeze();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTickRate(float tickRate) {
|
||||
if (currentlyStepping) {
|
||||
currentlyStepping = false;
|
||||
Bukkit.getOnlinePlayers().forEach(player -> {
|
||||
BossBarService.instance.remove(player, GlobalRegion.getInstance(), "TickStep");
|
||||
});
|
||||
}
|
||||
TPSWarpUtils.warp(tickRate);
|
||||
if (currentTPSLimit == 0 && tickRate != 0) {
|
||||
TPSFreezeUtils.unfreeze();
|
||||
}
|
||||
currentTPSLimit = tickRate;
|
||||
if (tickRate == 0) {
|
||||
TPSLimitUtils.unlimit();
|
||||
TPSFreezeUtils.freeze();
|
||||
} else if (tickRate < 20.0) {
|
||||
TPSLimitUtils.limit(tickRate);
|
||||
} else if (tickRate >= 20) {
|
||||
TPSLimitUtils.unlimit();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFrozen() {
|
||||
return TPSFreezeUtils.frozen();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFreeze(boolean freeze) {
|
||||
if (freeze) {
|
||||
setTickRate(0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stepTicks(int ticks) {
|
||||
currentLimit = 0;
|
||||
setTickRate(20);
|
||||
stepsLeft = ticks;
|
||||
stepsTotal = ticks;
|
||||
currentlyStepping = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sprintTicks(int ticks) {
|
||||
currentLimit = currentTPSLimit;
|
||||
setTickRate(4000);
|
||||
stepsLeft = ticks;
|
||||
stepsTotal = ticks;
|
||||
currentlyStepping = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSprinting() {
|
||||
return currentlyStepping && currentTPSLimit > 20;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStepping() {
|
||||
return currentlyStepping && currentTPSLimit <= 20;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getTickRate() {
|
||||
return currentTPSLimit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlockTpsPacket(boolean block) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTotalTicks() {
|
||||
return stepsTotal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDoneTicks() {
|
||||
return stepsTotal - stepsLeft;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getRemainingTicks() {
|
||||
return stepsLeft;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onTickEnd(TickEndEvent event) {
|
||||
if (!currentlyStepping) return;
|
||||
stepsLeft--;
|
||||
if (stepsLeft <= 0) {
|
||||
setTickRate(currentLimit);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2023 SteamWar.de-Serverteam
|
||||
* Copyright (C) 2020 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
@ -17,7 +17,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.bausystem.features.tpslimit;
|
||||
package de.steamwar.bausystem.utils.tps;
|
||||
|
||||
import de.steamwar.Reflection;
|
||||
import com.comphenix.tinyprotocol.TinyProtocol;
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2023 SteamWar.de-Serverteam
|
||||
* Copyright (C) 2020 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
@ -17,7 +17,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.bausystem.features.tpslimit;
|
||||
package de.steamwar.bausystem.utils.tps;
|
||||
|
||||
import de.steamwar.Reflection;
|
||||
import lombok.Getter;
|
||||
@ -17,7 +17,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.bausystem.features.tpslimit;
|
||||
package de.steamwar.bausystem.utils.tps;
|
||||
|
||||
import de.steamwar.Reflection;
|
||||
import com.comphenix.tinyprotocol.TinyProtocol;
|
||||
@ -22,7 +22,6 @@ package de.steamwar.bausystem.utils;
|
||||
import com.destroystokyo.paper.event.server.ServerTickEndEvent;
|
||||
import com.destroystokyo.paper.event.server.ServerTickStartEvent;
|
||||
import de.steamwar.bausystem.BauSystem;
|
||||
import de.steamwar.bausystem.features.tpslimit.TPSFreezeUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
@ -37,7 +36,7 @@ public class TickListener19 implements TickListener, Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onServerTickStart(ServerTickStartEvent event) {
|
||||
if (TPSFreezeUtils.isFrozen()) return;
|
||||
if (TickManager.impl.isFrozen()) return;
|
||||
Bukkit.getPluginManager().callEvent(new TickStartEvent());
|
||||
tickStartRan = true;
|
||||
}
|
||||
|
||||
@ -94,7 +94,7 @@ public class NMSWrapper21 implements NMSWrapper {
|
||||
return false;
|
||||
}
|
||||
|
||||
return drillDown(data.contents(), 0, 0) <= threshold;
|
||||
return drillDown(data.contents(), 0, 0) > threshold;
|
||||
}
|
||||
|
||||
private int drillDown(List<ItemStack> items, int layer, int start) {
|
||||
|
||||
@ -0,0 +1,150 @@
|
||||
/*
|
||||
* 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 com.comphenix.tinyprotocol.TinyProtocol;
|
||||
import de.steamwar.Reflection;
|
||||
import de.steamwar.bausystem.BauSystem;
|
||||
import net.minecraft.network.protocol.game.ClientboundTickingStatePacket;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.ServerTickRateManager;
|
||||
import net.minecraft.world.TickRateManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class TickManager21 implements TickManager {
|
||||
private static final ServerTickRateManager manager = MinecraftServer.getServer().tickRateManager();
|
||||
private static final Reflection.Field<Integer> frozenTicksToRun = Reflection.getField(TickRateManager.class, int.class, 0);
|
||||
private static final Reflection.Field<Long> remainingSprintTicks = Reflection.getField(ServerTickRateManager.class, long.class, 0);
|
||||
|
||||
private boolean blockTpsPacket = true;
|
||||
private int totalSteps;
|
||||
|
||||
public TickManager21() {
|
||||
TinyProtocol.instance.addFilter(ClientboundTickingStatePacket.class, this::blockPacket);
|
||||
}
|
||||
|
||||
private Object blockPacket(Player player, Object packet) {
|
||||
if (blockTpsPacket) {
|
||||
return new ClientboundTickingStatePacket(20, manager.isFrozen());
|
||||
} else {
|
||||
return packet;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canFreeze() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlockTpsPacket(boolean block) {
|
||||
blockTpsPacket = block;
|
||||
if (blockTpsPacket) {
|
||||
ClientboundTickingStatePacket packet = new ClientboundTickingStatePacket(20, manager.isFrozen());
|
||||
Bukkit.getOnlinePlayers().forEach(player -> TinyProtocol.instance.sendPacket(player, packet));
|
||||
} else {
|
||||
ClientboundTickingStatePacket packet = new ClientboundTickingStatePacket(manager.tickrate(), manager.isFrozen());
|
||||
Bukkit.getOnlinePlayers().forEach(player -> TinyProtocol.instance.sendPacket(player, packet));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTickRate(float tickRate) {
|
||||
if (isFrozen()) {
|
||||
setFreeze(false);
|
||||
}
|
||||
manager.setTickRate(tickRate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFrozen() {
|
||||
return manager.isFrozen();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFreeze(boolean freeze) {
|
||||
manager.setFrozen(freeze);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stepTicks(int ticks) {
|
||||
if (manager.isSprinting()) {
|
||||
manager.stopSprinting();
|
||||
} else if (manager.isSteppingForward()) {
|
||||
manager.stopStepping();
|
||||
}
|
||||
this.totalSteps = ticks;
|
||||
manager.setFrozen(true);
|
||||
manager.stepGameIfPaused(ticks);
|
||||
manager.setFrozen(false);
|
||||
Bukkit.getScheduler().runTaskTimer(BauSystem.getInstance(), (bukkitTask) -> {
|
||||
if (manager.isSteppingForward()) return;
|
||||
manager.setFrozen(true);
|
||||
bukkitTask.cancel();
|
||||
}, 1, 1);
|
||||
manager.tick();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sprintTicks(int ticks) {
|
||||
if (manager.isSteppingForward()) {
|
||||
manager.stopStepping();
|
||||
} else if (manager.isSprinting()) {
|
||||
manager.stopSprinting();
|
||||
}
|
||||
this.totalSteps = ticks;
|
||||
manager.requestGameToSprint(ticks, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSprinting() {
|
||||
return manager.isSprinting();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStepping() {
|
||||
return manager.isSteppingForward();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getTickRate() {
|
||||
return manager.tickrate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getRemainingTicks() {
|
||||
if (isSprinting()) {
|
||||
return remainingSprintTicks.get(manager);
|
||||
} else {
|
||||
return frozenTicksToRun.get(manager);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDoneTicks() {
|
||||
return totalSteps - getRemainingTicks();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTotalTicks() {
|
||||
return totalSteps;
|
||||
}
|
||||
}
|
||||
@ -25,7 +25,7 @@ PAGE_LIST=§e Page ({0}/{1}) »»
|
||||
LIST_PREVIOUS_PAGE=§ePrevious page
|
||||
LIST_NEXT_PAGE=§eNext page
|
||||
# Permissions
|
||||
NO_PERMISSION=You are not allowed to use that here
|
||||
NO_PERMISSION=§7You are not allowed to use that here
|
||||
SPECTATOR=§fSpectator
|
||||
# Scoreboard
|
||||
SCOREBOARD_TIME=Time
|
||||
@ -390,6 +390,12 @@ INVENTORY_FILL_HELP=§8/§einventoryfill §8- §7Toggles InventoryFill
|
||||
INVENTORY_FILL_INFO=§7Helps you fill containers by looking at them while sneaking and dropping the item. Or just scroll on a container to change the amount of the item inside.
|
||||
INVENTORY_FILL_ENABLE=§aInventoryFiller activated
|
||||
INVENTORY_FILL_DISABLE=§cInventoryFiller deactivated
|
||||
INVENTORY_FILL_GUI_NAME=Inventory Filler
|
||||
INVENTORY_FILL_GUI_POWER=§ePower§8:§7 {0}
|
||||
INVENTORY_FILL_GUI_TNT=§eTNT
|
||||
# Ray Visualizer
|
||||
RAY_VISUALIZER_ENABLE=§aRayVisualizer activated
|
||||
RAY_VISUALIZER_DISABLE=§aRayVisualizer deactivated
|
||||
# Killchecker
|
||||
KILLCHECKER_HELP_ENABLE=§8/§ekillchecker enable §8- §7Enables Killchecker / Recalculates kills
|
||||
KILLCHECKER_HELP_DISABLE=§8/§ekillchecker disable §8- §7Disables Killchecker
|
||||
|
||||
@ -25,7 +25,7 @@ PAGE_LIST=§e Seite ({0}/{1}) »»
|
||||
LIST_PREVIOUS_PAGE=§eVorherige Seite
|
||||
LIST_NEXT_PAGE=§eNächste Seite
|
||||
# Permission
|
||||
NO_PERMISSION=Du darfst dies hier nicht nutzen
|
||||
NO_PERMISSION=§7Du darfst dies hier nicht nutzen
|
||||
SPECTATOR=§fZuschauer
|
||||
# Scoreboard
|
||||
SCOREBOARD_TIME=Uhrzeit
|
||||
@ -350,8 +350,11 @@ SMART_PLACE_DISABLE=§cSmartPlace deaktiviert
|
||||
# InventoryFiller
|
||||
INVENTORY_FILL_HELP=§8/§einventoryfill §8- §7Toggled InventoryFill
|
||||
INVENTORY_FILL_INFO=§7Hilft dir, Behälter zu füllen, indem du sie beim sneaken ansiehst und den Gegenstand fallen lässt. Oder scrolle einfach auf einen Behälter, um die Menge des gehaltenen Gegenstandes darin zu ändern.
|
||||
INVENTORY_FILL_ENABLE=§aInventoryFiller activated
|
||||
INVENTORY_FILL_DISABLE=§cInventoryFiller deactivated
|
||||
INVENTORY_FILL_ENABLE=§aInventoryFiller aktiviert
|
||||
INVENTORY_FILL_DISABLE=§cInventoryFiller deaktiviert
|
||||
# Ray Visualizer
|
||||
RAY_VISUALIZER_ENABLE=§aRayVisualizer aktiviert
|
||||
RAY_VISUALIZER_DISABLE=§aRayVisualizer deaktiviert
|
||||
# Killchecker
|
||||
KILLCHECKER_HELP_ENABLE=§8/§ekillchecker enable §8- §7Aktiviert Killchecker / Berechnet kills neu
|
||||
KILLCHECKER_HELP_DISABLE=§8/§ekillchecker disable §8- §7Deaktiviert Killchecker
|
||||
|
||||
@ -19,7 +19,6 @@
|
||||
|
||||
package de.steamwar.bausystem;
|
||||
|
||||
import de.steamwar.core.WorldEditRendererCUIEditor;
|
||||
import de.steamwar.bausystem.config.BauServer;
|
||||
import de.steamwar.bausystem.configplayer.Config;
|
||||
import de.steamwar.bausystem.configplayer.ConfigConverter;
|
||||
@ -29,7 +28,6 @@ import de.steamwar.bausystem.features.script.lua.libs.LuaLib;
|
||||
import de.steamwar.bausystem.features.slaves.laufbau.BoundingBoxLoader;
|
||||
import de.steamwar.bausystem.features.slaves.panzern.Panzern;
|
||||
import de.steamwar.bausystem.features.slaves.panzern.PanzernAlgorithm;
|
||||
import de.steamwar.bausystem.features.tpslimit.TPSFreezeUtils;
|
||||
import de.steamwar.bausystem.features.tracer.TraceManager;
|
||||
import de.steamwar.bausystem.features.tracer.TraceRecorder;
|
||||
import de.steamwar.bausystem.features.world.BauScoreboard;
|
||||
@ -39,11 +37,13 @@ import de.steamwar.bausystem.region.loader.RegionLoader;
|
||||
import de.steamwar.bausystem.region.loader.Updater;
|
||||
import de.steamwar.bausystem.utils.ScoreboardElement;
|
||||
import de.steamwar.bausystem.utils.TickListener;
|
||||
import de.steamwar.bausystem.utils.TickManager;
|
||||
import de.steamwar.bausystem.worlddata.WorldData;
|
||||
import de.steamwar.command.AbstractValidator;
|
||||
import de.steamwar.command.SWCommand;
|
||||
import de.steamwar.command.SWCommandUtils;
|
||||
import de.steamwar.core.Core;
|
||||
import de.steamwar.core.WorldEditRendererCUIEditor;
|
||||
import de.steamwar.linkage.LinkedInstance;
|
||||
import de.steamwar.linkage.MaxVersion;
|
||||
import de.steamwar.linkage.MinVersion;
|
||||
@ -266,7 +266,7 @@ public class BauSystem extends JavaPlugin {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (TPSFreezeUtils.isFrozen()) return;
|
||||
if (TickManager.impl.isFrozen()) return;
|
||||
if (counter >= delay) {
|
||||
runnable.run();
|
||||
cancel();
|
||||
@ -284,7 +284,7 @@ public class BauSystem extends JavaPlugin {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (TPSFreezeUtils.isFrozen()) return;
|
||||
if (TickManager.impl.isFrozen()) return;
|
||||
if (counter >= (first ? delay : period)) {
|
||||
first = false;
|
||||
runnable.run();
|
||||
|
||||
@ -4,12 +4,45 @@ import de.steamwar.bausystem.BauSystem;
|
||||
import de.steamwar.bausystem.SWUtils;
|
||||
import de.steamwar.bausystem.configplayer.Config;
|
||||
import de.steamwar.command.SWCommand;
|
||||
import de.steamwar.inventory.SWInventory;
|
||||
import de.steamwar.inventory.SWItem;
|
||||
import de.steamwar.linkage.Linked;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Barrel;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.block.Chest;
|
||||
import org.bukkit.block.ShulkerBox;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.BlockStateMeta;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Linked
|
||||
public class InventoryFillerCommand extends SWCommand {
|
||||
|
||||
private static final Map<Integer, Integer> POWER_TO_FILLLEVEL = new HashMap<>();
|
||||
|
||||
static {
|
||||
POWER_TO_FILLLEVEL.put(0, 0);
|
||||
POWER_TO_FILLLEVEL.put(1, 1);
|
||||
POWER_TO_FILLLEVEL.put(2, 1 * 64 + 60);
|
||||
POWER_TO_FILLLEVEL.put(3, 3 * 64 + 55);
|
||||
POWER_TO_FILLLEVEL.put(4, 5 * 64 + 51);
|
||||
POWER_TO_FILLLEVEL.put(5, 7 * 64 + 46);
|
||||
POWER_TO_FILLLEVEL.put(6, 9 * 64 + 42);
|
||||
POWER_TO_FILLLEVEL.put(7, 11 * 64 + 37);
|
||||
POWER_TO_FILLLEVEL.put(8, 13 * 64 + 32);
|
||||
POWER_TO_FILLLEVEL.put(9, 15 * 64 + 28);
|
||||
POWER_TO_FILLLEVEL.put(10, 17 * 64 + 23);
|
||||
POWER_TO_FILLLEVEL.put(11, 19 * 64 + 19);
|
||||
POWER_TO_FILLLEVEL.put(12, 21 * 64 + 14);
|
||||
POWER_TO_FILLLEVEL.put(13, 23 * 64 + 10);
|
||||
POWER_TO_FILLLEVEL.put(14, 25 * 64 + 5);
|
||||
POWER_TO_FILLLEVEL.put(15, 27 * 64 + 0);
|
||||
}
|
||||
|
||||
public InventoryFillerCommand() {
|
||||
super("inventoryfill");
|
||||
}
|
||||
@ -25,4 +58,112 @@ public class InventoryFillerCommand extends SWCommand {
|
||||
SWUtils.sendToActionbar(player, BauSystem.MESSAGE.parse("INVENTORY_FILL_DISABLE", player));
|
||||
}
|
||||
}
|
||||
|
||||
@Register("gui")
|
||||
public void gui(Player player) {
|
||||
SWInventory inventory = new SWInventory(player, 18, BauSystem.MESSAGE.parse("INVENTORY_FILL_GUI_NAME", player));
|
||||
inventory.setItem(0, new SWItem(Material.REDSTONE, BauSystem.MESSAGE.parse("INVENTORY_FILL_GUI_POWER", player, 0)).setAmount(1));
|
||||
inventory.setItem(1, new SWItem(Material.REDSTONE_TORCH, BauSystem.MESSAGE.parse("INVENTORY_FILL_GUI_POWER", player, 1)).setAmount(1));
|
||||
inventory.setItem(2, new SWItem(Material.REDSTONE_TORCH, BauSystem.MESSAGE.parse("INVENTORY_FILL_GUI_POWER", player, 2)).setAmount(2));
|
||||
inventory.setItem(3, new SWItem(Material.REDSTONE_TORCH, BauSystem.MESSAGE.parse("INVENTORY_FILL_GUI_POWER", player, 3)).setAmount(3));
|
||||
inventory.setItem(4, new SWItem(Material.REDSTONE_TORCH, BauSystem.MESSAGE.parse("INVENTORY_FILL_GUI_POWER", player, 4)).setAmount(4));
|
||||
inventory.setItem(5, new SWItem(Material.REDSTONE_TORCH, BauSystem.MESSAGE.parse("INVENTORY_FILL_GUI_POWER", player, 5)).setAmount(5));
|
||||
inventory.setItem(6, new SWItem(Material.REDSTONE_TORCH, BauSystem.MESSAGE.parse("INVENTORY_FILL_GUI_POWER", player, 6)).setAmount(6));
|
||||
inventory.setItem(7, new SWItem(Material.REDSTONE_TORCH, BauSystem.MESSAGE.parse("INVENTORY_FILL_GUI_POWER", player, 7)).setAmount(7));
|
||||
inventory.setItem(8, new SWItem(Material.REDSTONE_TORCH, BauSystem.MESSAGE.parse("INVENTORY_FILL_GUI_POWER", player, 8)).setAmount(8));
|
||||
inventory.setItem(9, new SWItem(Material.REDSTONE_TORCH, BauSystem.MESSAGE.parse("INVENTORY_FILL_GUI_POWER", player, 9)).setAmount(9));
|
||||
inventory.setItem(10, new SWItem(Material.REDSTONE_TORCH, BauSystem.MESSAGE.parse("INVENTORY_FILL_GUI_POWER", player, 10)).setAmount(10));
|
||||
inventory.setItem(11, new SWItem(Material.REDSTONE_TORCH, BauSystem.MESSAGE.parse("INVENTORY_FILL_GUI_POWER", player, 11)).setAmount(11));
|
||||
inventory.setItem(12, new SWItem(Material.REDSTONE_TORCH, BauSystem.MESSAGE.parse("INVENTORY_FILL_GUI_POWER", player, 12)).setAmount(12));
|
||||
inventory.setItem(13, new SWItem(Material.REDSTONE_TORCH, BauSystem.MESSAGE.parse("INVENTORY_FILL_GUI_POWER", player, 13)).setAmount(13));
|
||||
inventory.setItem(14, new SWItem(Material.REDSTONE_TORCH, BauSystem.MESSAGE.parse("INVENTORY_FILL_GUI_POWER", player, 14)).setAmount(14));
|
||||
inventory.setItem(15, new SWItem(Material.REDSTONE_TORCH, BauSystem.MESSAGE.parse("INVENTORY_FILL_GUI_POWER", player, 15)).setAmount(15));
|
||||
inventory.setItem(17, new SWItem(Material.TNT, BauSystem.MESSAGE.parse("INVENTORY_FILL_GUI_TNT", player)));
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
inventory.setEventCallback(i, inventoryClickEvent -> {
|
||||
selectInventoryType(player, inventoryClickEvent.getCurrentItem().getItemMeta().getDisplayName(), Material.DANDELION, POWER_TO_FILLLEVEL.get(inventoryClickEvent.getCurrentItem().getAmount()));
|
||||
});
|
||||
}
|
||||
inventory.setEventCallback(17, inventoryClickEvent -> {
|
||||
selectInventoryType(player, inventoryClickEvent.getCurrentItem().getItemMeta().getDisplayName(), Material.TNT, POWER_TO_FILLLEVEL.get(15));
|
||||
});
|
||||
|
||||
inventory.open();
|
||||
}
|
||||
|
||||
private final Material[] SHULKER_BOX_MATERIALS = new Material[]{
|
||||
Material.SHULKER_BOX,
|
||||
Material.WHITE_SHULKER_BOX,
|
||||
Material.LIGHT_GRAY_SHULKER_BOX,
|
||||
Material.GRAY_SHULKER_BOX,
|
||||
Material.BLACK_SHULKER_BOX,
|
||||
Material.BROWN_SHULKER_BOX,
|
||||
Material.RED_SHULKER_BOX,
|
||||
Material.ORANGE_SHULKER_BOX,
|
||||
Material.YELLOW_SHULKER_BOX,
|
||||
Material.LIME_SHULKER_BOX,
|
||||
Material.GREEN_SHULKER_BOX,
|
||||
Material.CYAN_SHULKER_BOX,
|
||||
Material.LIGHT_BLUE_SHULKER_BOX,
|
||||
Material.BLUE_SHULKER_BOX,
|
||||
Material.PURPLE_SHULKER_BOX,
|
||||
Material.MAGENTA_SHULKER_BOX,
|
||||
Material.PINK_SHULKER_BOX
|
||||
};
|
||||
|
||||
private void selectInventoryType(Player player, String name, Material material, int count) {
|
||||
ItemStack[] itemStacks = new ItemStack[27];
|
||||
int index = 0;
|
||||
int amount = count;
|
||||
while (amount > 0) {
|
||||
ItemStack stack;
|
||||
if (amount > 64) {
|
||||
stack = new ItemStack(material, 64);
|
||||
amount -= 64;
|
||||
} else {
|
||||
stack = new ItemStack(material, amount);
|
||||
amount = 0;
|
||||
}
|
||||
itemStacks[index++] = stack;
|
||||
}
|
||||
|
||||
SWInventory inventory = new SWInventory(player, 27, BauSystem.MESSAGE.parse("INVENTORY_FILL_GUI_NAME", player));
|
||||
int i = 0;
|
||||
for (Material type : SHULKER_BOX_MATERIALS) {
|
||||
inventory.setItemEvent(i++, generateFilledInventory(name, type, itemStacks), inventoryClickEvent -> {
|
||||
SWUtils.giveItemToPlayer(player, inventoryClickEvent.getCurrentItem());
|
||||
});
|
||||
}
|
||||
inventory.setItemEvent(27 - 6, generateFilledInventory(name, Material.CHEST, itemStacks), inventoryClickEvent -> {
|
||||
SWUtils.giveItemToPlayer(player, inventoryClickEvent.getCurrentItem());
|
||||
});
|
||||
inventory.setItemEvent(27 - 4, generateFilledInventory(name, Material.BARREL, itemStacks), inventoryClickEvent -> {
|
||||
SWUtils.giveItemToPlayer(player, inventoryClickEvent.getCurrentItem());
|
||||
});
|
||||
inventory.open();
|
||||
}
|
||||
|
||||
private ItemStack generateFilledInventory(String name, Material material, ItemStack[] itemStacks) {
|
||||
ItemStack itemStack = new ItemStack(material);
|
||||
BlockStateMeta meta = (BlockStateMeta) itemStack.getItemMeta();
|
||||
BlockState state = meta.getBlockState();
|
||||
|
||||
if (state instanceof ShulkerBox box) {
|
||||
box.getInventory().setContents(itemStacks);
|
||||
box.update();
|
||||
meta.setBlockState(box);
|
||||
} else if (state instanceof Chest chest) {
|
||||
chest.getInventory().setContents(itemStacks);
|
||||
chest.update();
|
||||
meta.setBlockState(chest);
|
||||
} else if (state instanceof Barrel barrel) {
|
||||
barrel.getInventory().setContents(itemStacks);
|
||||
barrel.update();
|
||||
meta.setBlockState(barrel);
|
||||
}
|
||||
meta.setDisplayName(name);
|
||||
itemStack.setItemMeta(meta);
|
||||
return itemStack;
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,7 +73,7 @@ public class Loader implements Listener {
|
||||
Bukkit.getPluginManager().registerEvents(this, BauSystem.getInstance());
|
||||
|
||||
BauSystem.runTaskTimer(BauSystem.getInstance(), () -> {
|
||||
if (stage != Stage.RUNNING) return;
|
||||
if (stage != Stage.RUNNING && stage != Stage.SINGLE) return;
|
||||
if(!Permission.BUILD.hasPermission(p)) return;
|
||||
if (waitTime > 0) {
|
||||
waitTime--;
|
||||
@ -149,13 +149,16 @@ public class Loader implements Listener {
|
||||
}
|
||||
|
||||
public boolean setTicksBetweenShots(int delay) {
|
||||
if (elements.size() == 0) return false;
|
||||
if (elements.isEmpty()) return false;
|
||||
LoaderElement loaderElement = elements.get(elements.size() - 1);
|
||||
if (loaderElement instanceof LoaderWait) {
|
||||
((LoaderWait) loaderElement).setDelay(delay);
|
||||
return true;
|
||||
} else {
|
||||
LoaderWait loaderWait = new LoaderWait(delay);
|
||||
elements.add(loaderWait);
|
||||
pause();
|
||||
}
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setTicksBetweenBlocks(int delay) {
|
||||
|
||||
@ -0,0 +1,198 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2020 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.bausystem.features.rayvisualizer;
|
||||
|
||||
import de.steamwar.bausystem.BauSystem;
|
||||
import de.steamwar.bausystem.Permission;
|
||||
import de.steamwar.bausystem.SWUtils;
|
||||
import de.steamwar.bausystem.configplayer.Config;
|
||||
import de.steamwar.bausystem.utils.BauMemberUpdateEvent;
|
||||
import de.steamwar.command.SWCommand;
|
||||
import de.steamwar.entity.CRay;
|
||||
import de.steamwar.entity.REntityServer;
|
||||
import de.steamwar.linkage.Linked;
|
||||
import de.steamwar.linkage.MinVersion;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.TNTPrimed;
|
||||
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.util.RayTraceResult;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Linked
|
||||
@MinVersion(20)
|
||||
public class RayVisualizerCommand extends SWCommand implements Listener {
|
||||
|
||||
private class CRayData {
|
||||
private CRay[] rays = new CRay[27 * 400];
|
||||
private boolean[] used = new boolean[27 * 400];
|
||||
|
||||
public void reset() {
|
||||
for (int i = 0; i < 27 * 400; i++) {
|
||||
if (!used[i] && rays[i] != null) {
|
||||
rays[i].die();
|
||||
rays[i] = null;
|
||||
}
|
||||
used[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean locEquals(Location loc1, Location loc2) {
|
||||
if ((long)(loc1.getX() * 1000) != (long)(loc2.getX() * 1000)) return false;
|
||||
if ((long)(loc1.getY() * 1000) != (long)(loc2.getY() * 1000)) return false;
|
||||
if ((long)(loc1.getZ() * 1000) != (long)(loc2.getZ() * 1000)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public CRay get(Location from, Location to) {
|
||||
for (int i = 0; i < rays.length; i++) {
|
||||
if (rays[i] != null && locEquals(from, rays[i].getFrom()) && locEquals(to, rays[i].getTo())) {
|
||||
used[i] = true;
|
||||
return rays[i];
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < rays.length; i++) {
|
||||
if (rays[i] != null && locEquals(from, rays[i].getFrom()) && !used[i]) {
|
||||
used[i] = true;
|
||||
return rays[i];
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < rays.length; i++) {
|
||||
if (used[i]) continue;
|
||||
CRay ray = rays[i];
|
||||
if (ray != null) {
|
||||
return ray;
|
||||
}
|
||||
ray = new CRay(server);
|
||||
ray.setBlock(Material.LIME_CONCRETE.createBlockData());
|
||||
ray.setWidth(1 / 32f);
|
||||
rays[i] = ray;
|
||||
used[i] = true;
|
||||
return ray;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private CRayData rayData = new CRayData();
|
||||
|
||||
private final REntityServer server = new REntityServer();
|
||||
private final World WORLD = Bukkit.getWorlds().get(0);
|
||||
|
||||
public RayVisualizerCommand() {
|
||||
super("rayvisualizer");
|
||||
|
||||
Bukkit.getScheduler().runTaskTimer(BauSystem.getInstance(), () -> {
|
||||
if (server.getPlayers().isEmpty()) return;
|
||||
Map<Integer, List<TNTPrimed>> primedList = WORLD.getEntitiesByClass(TNTPrimed.class)
|
||||
.stream()
|
||||
.collect(Collectors.groupingBy(TNTPrimed::getFuseTicks));
|
||||
rayData.reset();
|
||||
if (primedList.isEmpty()) return;
|
||||
|
||||
List<Integer> fuseTicks = primedList.keySet().stream().sorted().collect(Collectors.toList());
|
||||
List<TNTPrimed> current = new ArrayList<>();
|
||||
for (int i = 0; i < fuseTicks.size(); i++) {
|
||||
List<TNTPrimed> tnts = primedList.get(fuseTicks.get(i));
|
||||
calculateRays(current, tnts);
|
||||
current.addAll(tnts);
|
||||
}
|
||||
}, 1, 1);
|
||||
}
|
||||
|
||||
private void calculateRays(List<TNTPrimed> fromTNTs, List<TNTPrimed> toTNTs) {
|
||||
for (TNTPrimed from : fromTNTs) {
|
||||
if (!from.isInWater()) continue;
|
||||
for (TNTPrimed to : toTNTs) {
|
||||
if (from == to) continue;
|
||||
if (to.getLocation().distanceSquared(from.getLocation()) > 25) continue;
|
||||
|
||||
Location fromLoc = from.getLocation();
|
||||
Location toLoc = to.getLocation().clone().add(-0.49, 0, -0.49);
|
||||
|
||||
final double minX = 0.5 * (1 - Math.floor(2 * 0.98 + 1) / (2 * 0.98 + 1));
|
||||
final double minZ = 0.5 * (1 - Math.floor(2 * 0.98 + 1) / (2 * 0.98 + 1));
|
||||
final double spacing = 0.98 / (2 * 0.98 + 1);
|
||||
|
||||
for (int dx = 0; dx < 3; dx++) {
|
||||
for (int dy = 0; dy < 3; dy++) {
|
||||
for (int dz = 0; dz < 3; dz++) {
|
||||
Location end = toLoc.clone().add(minX + dx * spacing, 0 + dy * spacing, minZ + dz * spacing);
|
||||
RayTraceResult result = fromLoc.getWorld().rayTraceBlocks(fromLoc, end.clone().subtract(fromLoc).toVector(), end.distance(fromLoc), FluidCollisionMode.NEVER, true);
|
||||
if (result != null && result.getHitBlock() != null) {
|
||||
continue;
|
||||
}
|
||||
CRay cRay = rayData.get(fromLoc, end);
|
||||
if (cRay == null) continue;
|
||||
cRay.setFrom(fromLoc);
|
||||
cRay.setTo(end);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||
if (!Permission.BUILD.hasPermission(event.getPlayer())) return;
|
||||
boolean rayvisualizer = Config.getInstance().get(event.getPlayer()).getPlainValueOrDefault("rayvisualizer", false);
|
||||
if (rayvisualizer) server.addPlayer(event.getPlayer());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||
server.removePlayer(event.getPlayer());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onBauMemberUpdate(BauMemberUpdateEvent event) {
|
||||
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> {
|
||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||
if (Permission.BUILD.hasPermission(player)) {
|
||||
boolean rayvisualizer = Config.getInstance().get(player).getPlainValueOrDefault("rayvisualizer", false);
|
||||
if (rayvisualizer) server.addPlayer(player);
|
||||
} else {
|
||||
server.removePlayer(player);
|
||||
}
|
||||
}
|
||||
}, 1);
|
||||
}
|
||||
|
||||
@Register
|
||||
public void toggle(@Validator Player player) {
|
||||
boolean rayvisualizer = Config.getInstance().get(player).getPlainValueOrDefault("rayvisualizer", false);
|
||||
Config.getInstance().get(player).put("rayvisualizer", !rayvisualizer);
|
||||
if (!rayvisualizer) {
|
||||
SWUtils.sendToActionbar(player, BauSystem.MESSAGE.parse("RAY_VISUALIZER_ENABLE", player));
|
||||
server.addPlayer(player);
|
||||
} else {
|
||||
SWUtils.sendToActionbar(player, BauSystem.MESSAGE.parse("RAY_VISUALIZER_DISABLE", player));
|
||||
server.removePlayer(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -34,8 +34,6 @@ import de.steamwar.linkage.Linked;
|
||||
import de.steamwar.linkage.LinkedInstance;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@Linked
|
||||
public class ColorCommand extends SWCommand {
|
||||
|
||||
@ -47,7 +45,7 @@ public class ColorCommand extends SWCommand {
|
||||
}
|
||||
|
||||
@Register(description = "REGION_COLOR_HELP_COLOR")
|
||||
public void genericColor(Player p, ColorMode color) {
|
||||
public void genericColor(@Validator Player p, ColorMode color) {
|
||||
genericColorSet(p, color, ColorizationType.LOCAL);
|
||||
}
|
||||
|
||||
@ -78,7 +76,7 @@ public class ColorCommand extends SWCommand {
|
||||
}
|
||||
|
||||
@Register
|
||||
public void genericColorSet(Player p, ColorizationType colorizationType, ColorMode color) {
|
||||
public void genericColorSet(@Validator Player p, ColorizationType colorizationType, ColorMode color) {
|
||||
genericColorSet(p, color, colorizationType);
|
||||
}
|
||||
|
||||
|
||||
@ -20,6 +20,7 @@
|
||||
package de.steamwar.bausystem.features.script.lua.libs;
|
||||
|
||||
import de.steamwar.bausystem.features.tpslimit.TPSSystem;
|
||||
import de.steamwar.bausystem.utils.TickManager;
|
||||
import de.steamwar.core.TPSWatcher;
|
||||
import de.steamwar.linkage.Linked;
|
||||
import de.steamwar.linkage.LinkedInstance;
|
||||
@ -51,7 +52,7 @@ public class TpsLib implements LuaLib {
|
||||
tpsLib.set("fiveMinute", getter(() -> TPSWatcher.getTPS(TPSWatcher.TPSType.FIVE_MINUTES)));
|
||||
tpsLib.set("tenMinute", getter(() -> TPSWatcher.getTPS(TPSWatcher.TPSType.TEN_MINUTES)));
|
||||
tpsLib.set("current", getter(TPSWatcher::getTPS));
|
||||
tpsLib.set("limit", getter(TPSSystem::getCurrentTPSLimit));
|
||||
tpsLib.set("limit", getter(() -> (double) TickManager.impl.getTickRate()));
|
||||
return tpsLib;
|
||||
}
|
||||
}
|
||||
|
||||
@ -76,7 +76,7 @@ public class SimulatorCommand extends SWCommand {
|
||||
|
||||
@Register(value = "start", description = "SIMULATOR_START_HELP")
|
||||
public void start(@Validator Player p, @ErrorMessage("SIMULATOR_NOT_EXISTS") Simulator simulator) {
|
||||
SimulatorExecutor.run(simulator, () -> {});
|
||||
SimulatorExecutor.run(p, simulator, null);
|
||||
}
|
||||
|
||||
@Register(value = "rename", description = "SIMULATOR_RENAME_HELP")
|
||||
|
||||
@ -367,7 +367,7 @@ public class SimulatorCursor implements Listener {
|
||||
if (simulator == null) {
|
||||
return;
|
||||
}
|
||||
SimulatorExecutor.run(simulator, () -> {});
|
||||
SimulatorExecutor.run(event.getPlayer(), simulator, null);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -40,9 +40,11 @@ public final class Simulator {
|
||||
private SimulatorStabGenerator stabGenerator = null;
|
||||
private Material material = Material.BARREL;
|
||||
private final String name;
|
||||
private boolean autoTrace = false;
|
||||
private final List<SimulatorGroup> groups = new ArrayList<>();
|
||||
|
||||
private boolean autoTrace = false;
|
||||
private boolean autoTestblock = false;
|
||||
|
||||
public void move(int x, int y, int z) {
|
||||
groups.forEach(simulatorGroup -> {
|
||||
simulatorGroup.move(x, y, z);
|
||||
|
||||
@ -31,6 +31,7 @@ import de.steamwar.linkage.Linked;
|
||||
import de.steamwar.linkage.MinVersion;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
@ -46,7 +47,7 @@ public class SimulatorExecutor implements Listener {
|
||||
private static Map<Long, Map<Integer, List<SimulatorAction>>> tickStartActions = new HashMap<>();
|
||||
private static Map<Long, List<SimulatorAction>> tickEndActions = new HashMap<>();
|
||||
|
||||
public static boolean run(Simulator simulator, Runnable onEnd) {
|
||||
public static boolean run(Player player, Simulator simulator, Runnable onEnd) {
|
||||
if (currentlyRunning.contains(simulator)) return false;
|
||||
currentlyRunning.add(simulator);
|
||||
|
||||
@ -83,10 +84,15 @@ public class SimulatorExecutor implements Listener {
|
||||
});
|
||||
}
|
||||
|
||||
if (onEnd != null) {
|
||||
onEnd.run();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (player != null && simulator.isAutoTestblock()) {
|
||||
player.performCommand("tb");
|
||||
}
|
||||
if (simulator.isAutoTrace() && onEnd == null) {
|
||||
simulator.getGroups()
|
||||
.stream()
|
||||
|
||||
@ -58,7 +58,7 @@ public abstract class StabStep {
|
||||
protected abstract void start();
|
||||
|
||||
protected final void runSimulator(Runnable onFinish) {
|
||||
SimulatorExecutor.run(data.simulator, () -> {
|
||||
SimulatorExecutor.run(null, data.simulator, () -> {
|
||||
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> {
|
||||
if (this instanceof Listener) {
|
||||
HandlerList.unregisterAll((Listener) this);
|
||||
|
||||
@ -56,10 +56,14 @@ public class SimulatorSettingsGui extends SimulatorBaseGui {
|
||||
}));
|
||||
|
||||
//AutoTrace
|
||||
inventory.setItem(20, new SWItem(simulator.isAutoTrace() ? Material.CHAIN_COMMAND_BLOCK : Material.COMMAND_BLOCK, "§eAutoTrace§8: " + (simulator.isAutoTrace() ? "§aOn" : "§cOff"), clickType -> {
|
||||
inventory.setItem(19, new SWItem(simulator.isAutoTrace() ? Material.CHAIN_COMMAND_BLOCK : Material.COMMAND_BLOCK, "§eAutoTrace§8: " + (simulator.isAutoTrace() ? "§aOn" : "§cOff"), clickType -> {
|
||||
simulator.setAutoTrace(!simulator.isAutoTrace());
|
||||
SimulatorWatcher.update(simulator);
|
||||
}));
|
||||
inventory.setItem(20, new SWItem(simulator.isAutoTestblock() ? Material.END_STONE : Material.BARRIER, "§eTestblock§8: " + (simulator.isAutoTestblock() ? "§aOn" : "§cOff"), clickType -> {
|
||||
simulator.setAutoTestblock(!simulator.isAutoTestblock());
|
||||
SimulatorWatcher.update(simulator);
|
||||
}));
|
||||
|
||||
//Pos X
|
||||
inventory.setItem(15, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
|
||||
|
||||
@ -68,6 +68,7 @@ public class SimFormatSimulatorLoader implements SimulatorLoader {
|
||||
private void loadSimulator(YAPIONObject simulatorObject, Simulator simulator) {
|
||||
simulator.setMaterial(Material.valueOf(simulatorObject.getPlainValue("material")));
|
||||
simulator.setAutoTrace(simulatorObject.getPlainValue("autoTrace"));
|
||||
simulator.setAutoTestblock(simulatorObject.getPlainValueOrDefault("autoTestblock", false));
|
||||
|
||||
YAPIONArray groups = simulatorObject.getArray("groups");
|
||||
groups.streamObject().forEach(groupObject -> {
|
||||
|
||||
@ -39,6 +39,7 @@ public class SimulatorSaver {
|
||||
YAPIONObject simulatorObject = new YAPIONObject();
|
||||
simulatorObject.add("material", simulator.getMaterial().name());
|
||||
simulatorObject.add("autoTrace", simulator.isAutoTrace());
|
||||
simulatorObject.add("autoTestblock", simulator.isAutoTestblock());
|
||||
|
||||
YAPIONArray groups = new YAPIONArray();
|
||||
simulator.getGroups().forEach(group -> {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2023 SteamWar.de-Serverteam
|
||||
* Copyright (C) 2020 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
|
||||
@ -27,19 +27,17 @@ import de.steamwar.bausystem.region.GlobalRegion;
|
||||
import de.steamwar.bausystem.region.Region;
|
||||
import de.steamwar.bausystem.utils.ScoreboardElement;
|
||||
import de.steamwar.bausystem.utils.TickEndEvent;
|
||||
import de.steamwar.bausystem.utils.TickManager;
|
||||
import de.steamwar.bausystem.utils.bossbar.BauSystemBossbar;
|
||||
import de.steamwar.bausystem.utils.bossbar.BossBarService;
|
||||
import de.steamwar.command.AbstractSWCommand;
|
||||
import de.steamwar.command.SWCommand;
|
||||
import de.steamwar.core.Core;
|
||||
import de.steamwar.core.TPSWarpUtils;
|
||||
import de.steamwar.core.TPSWatcher;
|
||||
import de.steamwar.inventory.SWAnvilInv;
|
||||
import de.steamwar.inventory.SWItem;
|
||||
import de.steamwar.linkage.Linked;
|
||||
import de.steamwar.linkage.LinkedInstance;
|
||||
import de.steamwar.linkage.MaxVersion;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.boss.BarColor;
|
||||
@ -52,91 +50,61 @@ import org.bukkit.inventory.ItemStack;
|
||||
import java.util.Arrays;
|
||||
|
||||
@Linked
|
||||
@MaxVersion(20) // Hotfix for 1.21 tps limit! -> Backport coming later
|
||||
public class TPSSystem implements Listener {
|
||||
|
||||
@Getter
|
||||
private static double currentTPSLimit = 20;
|
||||
|
||||
public TPSSystem() {
|
||||
if (TPSFreezeUtils.isCanFreeze()) {
|
||||
if (TickManager.impl.canFreeze()) {
|
||||
new TPSFreezeCommand();
|
||||
new TickFreezeCommand();
|
||||
new TickStepCommand();
|
||||
}
|
||||
new TPSLimitCommand();
|
||||
new TickLimitCommand();
|
||||
if (Core.getVersion() >= 15 && Core.getVersion() <= 20) { // If 1.21 support is not directly present
|
||||
if (Core.getVersion() >= 15) {
|
||||
new TPSWarpCommand();
|
||||
new TickWarpCommand();
|
||||
if (TPSFreezeUtils.isCanFreeze()) {
|
||||
if (TickManager.impl.canFreeze()) {
|
||||
new TickWarpingCommand();
|
||||
}
|
||||
}
|
||||
if (Core.getVersion() >= 21) {
|
||||
new Tick21Command();
|
||||
}
|
||||
new TPSDefaultCommand();
|
||||
new TickDefaultCommand();
|
||||
new TPSBaseCommand();
|
||||
new TickBaseCommand();
|
||||
}
|
||||
|
||||
private void setTPS(double tps) {
|
||||
if (currentlyStepping) {
|
||||
currentlyStepping = false;
|
||||
Bukkit.getOnlinePlayers().forEach(player -> {
|
||||
BossBarService.instance.remove(player, GlobalRegion.getInstance(), "TickStep");
|
||||
});
|
||||
}
|
||||
TPSWarpUtils.warp(tps);
|
||||
if (currentTPSLimit == 0 && tps != 0) {
|
||||
TPSFreezeUtils.unfreeze();
|
||||
}
|
||||
currentTPSLimit = tps;
|
||||
if (tps == 0) {
|
||||
TPSLimitUtils.unlimit();
|
||||
TPSFreezeUtils.freeze();
|
||||
} else if (tps < 20.0) {
|
||||
TPSLimitUtils.limit(tps);
|
||||
} else if (tps >= 20) {
|
||||
TPSLimitUtils.unlimit();
|
||||
}
|
||||
|
||||
Bukkit.getOnlinePlayers().forEach(player -> {
|
||||
if (currentTPSLimit == 0) {
|
||||
SWUtils.sendToActionbar(player, BauSystem.MESSAGE.parse("TPSLIMIT_FROZEN", player));
|
||||
} else {
|
||||
SWUtils.sendToActionbar(player, BauSystem.MESSAGE.parse("TPSLIMIT_SET", player, currentTPSLimit));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private boolean currentlyStepping = false;
|
||||
private double currentLimit;
|
||||
private int stepsTotal;
|
||||
private int stepsLeft;
|
||||
|
||||
private void setSkip(int steps, double tpsLimitToUse) {
|
||||
currentLimit = tpsLimitToUse == 20 ? 0 : currentTPSLimit;
|
||||
setTPS(tpsLimitToUse);
|
||||
stepsLeft = steps;
|
||||
stepsTotal = steps;
|
||||
currentlyStepping = true;
|
||||
Bukkit.getPluginManager().registerEvents(TickManager.impl, BauSystem.getInstance());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onTickEnd(TickEndEvent event) {
|
||||
if (!currentlyStepping) return;
|
||||
if (stepsTotal > 1) {
|
||||
bossbar();
|
||||
}
|
||||
|
||||
private void bossbar() {
|
||||
if ((TickManager.impl.isStepping() || TickManager.impl.isSprinting()) && TickManager.impl.getRemainingTicks() > 0) {
|
||||
Bukkit.getOnlinePlayers().forEach(player -> {
|
||||
BauSystemBossbar bossbar = BossBarService.instance.get(player, GlobalRegion.getInstance(), "TickStep");
|
||||
bossbar.setColor(BarColor.YELLOW);
|
||||
bossbar.setTitle(BauSystem.MESSAGE.parse("TICK_BOSSBAR", player, (stepsTotal - stepsLeft), stepsTotal));
|
||||
bossbar.setProgress((stepsTotal - stepsLeft) / (double) stepsTotal);
|
||||
bossbar.setTitle(BauSystem.MESSAGE.parse("TICK_BOSSBAR", player, TickManager.impl.getDoneTicks(), TickManager.impl.getTotalTicks()));
|
||||
bossbar.setProgress(TickManager.impl.getDoneTicks() / (double) TickManager.impl.getTotalTicks());
|
||||
});
|
||||
} else {
|
||||
Bukkit.getOnlinePlayers().forEach(player -> {
|
||||
BossBarService.instance.remove(player, GlobalRegion.getInstance(), "TickStep");
|
||||
});
|
||||
}
|
||||
stepsLeft--;
|
||||
if (stepsLeft <= 0) {
|
||||
setTPS(currentLimit);
|
||||
}
|
||||
|
||||
public static void sendTickRateChange() {
|
||||
Bukkit.getOnlinePlayers().forEach(player -> {
|
||||
if (TickManager.impl.isFrozen()) {
|
||||
SWUtils.sendToActionbar(player, BauSystem.MESSAGE.parse("TPSLIMIT_FROZEN", player));
|
||||
} else {
|
||||
SWUtils.sendToActionbar(player, BauSystem.MESSAGE.parse("TPSLIMIT_SET", player, TickManager.impl.getTickRate()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private class TPSBaseCommand extends SWCommand {
|
||||
@ -157,7 +125,8 @@ public class TPSSystem implements Listener {
|
||||
|
||||
@Register(value = "0", description = "TPSLIMIT_FREEZE_HELP")
|
||||
public void freeze(@Validator Player player) {
|
||||
setTPS(0);
|
||||
TickManager.impl.setFreeze(true);
|
||||
sendTickRateChange();
|
||||
}
|
||||
}
|
||||
|
||||
@ -169,8 +138,9 @@ public class TPSSystem implements Listener {
|
||||
}
|
||||
|
||||
@Register(description = "TPSLIMIT_LIMIT_HELP")
|
||||
public void limit(@Validator Player player, @Min(doubleValue = 0.5) @Max(doubleValue = 20.0) double tpsLimit) {
|
||||
setTPS(tpsLimit);
|
||||
public void limit(@Validator Player player, @Min(doubleValue = 0.5) @Max(doubleValue = 20.0) float tpsLimit) {
|
||||
TickManager.impl.setTickRate(tpsLimit);
|
||||
sendTickRateChange();
|
||||
}
|
||||
}
|
||||
|
||||
@ -182,8 +152,9 @@ public class TPSSystem implements Listener {
|
||||
}
|
||||
|
||||
@Register(description = "TPSLIMIT_WARP_HELP")
|
||||
public void warp(@Validator Player player, @Min(doubleValue = 20.0, inclusive = false) double tpsLimit) {
|
||||
setTPS(tpsLimit);
|
||||
public void warp(@Validator Player player, @Min(doubleValue = 20.0, inclusive = false) float tpsLimit) {
|
||||
TickManager.impl.setTickRate(tpsLimit);
|
||||
sendTickRateChange();
|
||||
}
|
||||
}
|
||||
|
||||
@ -196,12 +167,13 @@ public class TPSSystem implements Listener {
|
||||
|
||||
@Register(description = "TPSLIMIT_HELP")
|
||||
public void currentLimit(Player player) {
|
||||
BauSystem.MESSAGE.send("TPSLIMIT_CURRENT", player, currentTPSLimit);
|
||||
BauSystem.MESSAGE.send("TPSLIMIT_CURRENT", player, TickManager.impl.getTickRate());
|
||||
}
|
||||
|
||||
@Register(value = "default", description = "TPSLIMIT_DEFAULT_HELP")
|
||||
public void reset(@Validator Player player) {
|
||||
setTPS(20);
|
||||
TickManager.impl.setTickRate(20.0F);
|
||||
sendTickRateChange();
|
||||
}
|
||||
}
|
||||
|
||||
@ -223,12 +195,14 @@ public class TPSSystem implements Listener {
|
||||
@Register(value = {"rate", "0"}, description = "TICK_FREEZE_HELP")
|
||||
@Register(value = "freeze", description = "TICK_FREEZE_HELP_2")
|
||||
public void freeze(@Validator Player player) {
|
||||
setTPS(0);
|
||||
TickManager.impl.setFreeze(true);
|
||||
sendTickRateChange();
|
||||
}
|
||||
|
||||
@Register(value = "unfreeze", description = "TICK_UNFREEZE_HELP")
|
||||
public void unfreeze(@Validator Player player) {
|
||||
setTPS(20);
|
||||
TickManager.impl.setTickRate(20.0F);
|
||||
sendTickRateChange();
|
||||
}
|
||||
}
|
||||
|
||||
@ -241,7 +215,9 @@ public class TPSSystem implements Listener {
|
||||
|
||||
@Register(value = "step", description = "TICK_STEPPING_HELP")
|
||||
public void step(@Validator Player player, @Min(intValue = 1) @OptionalValue("1") int steps) {
|
||||
setSkip(steps, 20);
|
||||
TickManager.impl.stepTicks(steps);
|
||||
sendTickRateChange();
|
||||
bossbar();
|
||||
}
|
||||
}
|
||||
|
||||
@ -253,8 +229,9 @@ public class TPSSystem implements Listener {
|
||||
}
|
||||
|
||||
@Register(value = "warp", description = "TICK_WARPING_HELP")
|
||||
public void warp(@Validator Player player, @Min(intValue = 1) @OptionalValue("1") int steps, @Min(doubleValue = 20) @OptionalValue("4000") double tps) {
|
||||
setSkip(steps, tps);
|
||||
public void warp(@Validator Player player, @Min(intValue = 1) @OptionalValue("1") int steps) {
|
||||
TickManager.impl.sprintTicks(steps);
|
||||
sendTickRateChange();
|
||||
}
|
||||
}
|
||||
|
||||
@ -266,8 +243,9 @@ public class TPSSystem implements Listener {
|
||||
}
|
||||
|
||||
@Register(value = "rate", description = "TICK_LIMIT_HELP")
|
||||
public void limit(@Validator Player player, @Min(doubleValue = 0.5, inclusive = false) @Max(doubleValue = 20.0) double tpsLimit) {
|
||||
setTPS(tpsLimit);
|
||||
public void limit(@Validator Player player, @Min(doubleValue = 0.5, inclusive = false) @Max(doubleValue = 20.0) float tpsLimit) {
|
||||
TickManager.impl.setTickRate(tpsLimit);
|
||||
sendTickRateChange();
|
||||
}
|
||||
}
|
||||
|
||||
@ -279,8 +257,9 @@ public class TPSSystem implements Listener {
|
||||
}
|
||||
|
||||
@Register(value = "rate", description = "TICK_WARP_HELP")
|
||||
public void warp(@Validator Player player, @Min(doubleValue = 20.0, inclusive = false) double tpsLimit) {
|
||||
setTPS(tpsLimit);
|
||||
public void warp(@Validator Player player, @Min(doubleValue = 20.0, inclusive = false) float tpsLimit) {
|
||||
TickManager.impl.setTickRate(tpsLimit);
|
||||
sendTickRateChange();
|
||||
}
|
||||
}
|
||||
|
||||
@ -293,12 +272,31 @@ public class TPSSystem implements Listener {
|
||||
|
||||
@Register(value = "rate", description = "TICK_HELP")
|
||||
public void currentLimit(Player player) {
|
||||
BauSystem.MESSAGE.send("TPSLIMIT_CURRENT", player, currentTPSLimit);
|
||||
BauSystem.MESSAGE.send("TPSLIMIT_CURRENT", player, TickManager.impl.getTickRate());
|
||||
}
|
||||
|
||||
@Register(value = {"rate", "default"}, description = "TICK_DEFAULT_HELP")
|
||||
public void reset(@Validator Player player) {
|
||||
setTPS(20);
|
||||
TickManager.impl.setTickRate(20.0F);
|
||||
sendTickRateChange();
|
||||
}
|
||||
}
|
||||
|
||||
@AbstractSWCommand.PartOf(TickBaseCommand.class)
|
||||
private class Tick21Command extends SWCommand {
|
||||
|
||||
private Tick21Command() {
|
||||
super("");
|
||||
}
|
||||
|
||||
@Register(value = "normalclient")
|
||||
public void smooth(@Validator Player player) {
|
||||
TickManager.impl.setBlockTpsPacket(true);
|
||||
}
|
||||
|
||||
@Register(value = "slowclient")
|
||||
public void unsmooth(@Validator Player player) {
|
||||
TickManager.impl.setBlockTpsPacket(false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -320,7 +318,10 @@ public class TPSSystem implements Listener {
|
||||
|
||||
@Override
|
||||
public String get(Region region, Player p) {
|
||||
if (tpsSystem != null && tpsSystem.currentlyStepping) {
|
||||
boolean isWarping = TickManager.impl.isSprinting();
|
||||
boolean isFrozen = TickManager.impl.isFrozen();
|
||||
|
||||
if (tpsSystem != null && isWarping) {
|
||||
long time = System.currentTimeMillis() % 1000;
|
||||
if (time < 250) {
|
||||
return "§e" + BauSystem.MESSAGE.parse("SCOREBOARD_TPS", p) + "§8: §7•••";
|
||||
@ -331,7 +332,7 @@ public class TPSSystem implements Listener {
|
||||
} else {
|
||||
return "§e" + BauSystem.MESSAGE.parse("SCOREBOARD_TPS", p) + "§8: §7••§e•";
|
||||
}
|
||||
} else if (TPSFreezeUtils.frozen()) {
|
||||
} else if (isFrozen) {
|
||||
return "§e" + BauSystem.MESSAGE.parse("SCOREBOARD_TPS", p) + "§8: " + BauSystem.MESSAGE.parse("SCOREBOARD_TPS_FROZEN", p);
|
||||
} else {
|
||||
return "§e" + BauSystem.MESSAGE.parse("SCOREBOARD_TPS", p) + "§8: " + tpsColor() + TPSWatcher.getTPSUnlimited(TPSWatcher.TPSType.ONE_SECOND) + tpsLimit();
|
||||
@ -340,20 +341,20 @@ public class TPSSystem implements Listener {
|
||||
|
||||
private String tpsColor() {
|
||||
double tps = TPSWatcher.getTPSUnlimited(TPSWatcher.TPSType.ONE_SECOND);
|
||||
if (tps > TPSSystem.getCurrentTPSLimit() * 0.9) {
|
||||
if (tps > TickManager.impl.getTickRate() * 0.9) {
|
||||
return "§a";
|
||||
}
|
||||
if (tps > TPSSystem.getCurrentTPSLimit() * 0.5) {
|
||||
if (tps > TickManager.impl.getTickRate() * 0.5) {
|
||||
return "§e";
|
||||
}
|
||||
return "§c";
|
||||
}
|
||||
|
||||
private String tpsLimit() {
|
||||
if (TPSSystem.getCurrentTPSLimit() == 20) {
|
||||
if (TickManager.impl.getTickRate() == 20) {
|
||||
return "";
|
||||
}
|
||||
return "§8/§7" + TPSSystem.getCurrentTPSLimit();
|
||||
return "§8/§7" + TickManager.impl.getTickRate();
|
||||
}
|
||||
}
|
||||
|
||||
@ -369,7 +370,7 @@ public class TPSSystem implements Listener {
|
||||
|
||||
@Override
|
||||
public ItemStack getItem(Player player) {
|
||||
return new SWItem(Material.CLOCK, BauSystem.MESSAGE.parse("TPSLIMIT_GUI_ITEM_NAME", player), Arrays.asList(BauSystem.MESSAGE.parse("TPSLIMIT_GUI_ITEM_LORE", player, tpsSystem.currentTPSLimit)), false, clickType -> {
|
||||
return new SWItem(Material.CLOCK, BauSystem.MESSAGE.parse("TPSLIMIT_GUI_ITEM_NAME", player), Arrays.asList(BauSystem.MESSAGE.parse("TPSLIMIT_GUI_ITEM_LORE", player, TickManager.impl.getTickRate())), false, clickType -> {
|
||||
}).getItemStack();
|
||||
}
|
||||
|
||||
|
||||
@ -22,19 +22,15 @@ package de.steamwar.bausystem.features.tracer;
|
||||
import de.steamwar.bausystem.region.Region;
|
||||
import de.steamwar.bausystem.region.utils.RegionExtensionType;
|
||||
import de.steamwar.bausystem.region.utils.RegionType;
|
||||
import de.steamwar.core.Core;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.TNTPrimed;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.io.Externalizable;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInput;
|
||||
import java.io.ObjectOutput;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@ -106,7 +102,11 @@ public class TNTPoint{
|
||||
List<TNTPoint> history, List<Block> destroyedBlocks) {
|
||||
this.tntId = tntId;
|
||||
this.explosion = explosion;
|
||||
if (Core.getVersion() > 15) {
|
||||
this.inWater = tnt.isInWater();
|
||||
} else {
|
||||
this.inWater = false;
|
||||
}
|
||||
this.afterFirstExplosion = afterFirstExplosion;
|
||||
this.ticksSinceStart = ticksSinceStart;
|
||||
fuse = tnt.getFuseTicks();
|
||||
|
||||
@ -21,13 +21,9 @@ package de.steamwar.bausystem.features.util;
|
||||
|
||||
import de.steamwar.bausystem.BauSystem;
|
||||
import de.steamwar.bausystem.Permission;
|
||||
import de.steamwar.entity.REntityServer;
|
||||
import de.steamwar.entity.RFallingBlockEntity;
|
||||
import de.steamwar.entity.*;
|
||||
import de.steamwar.linkage.Linked;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
import net.md_5.bungee.api.ChatMessageType;
|
||||
import de.steamwar.linkage.MinVersion;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
@ -37,55 +33,186 @@ import org.bukkit.block.PistonMoveReaction;
|
||||
import org.bukkit.block.TileState;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.block.data.type.Piston;
|
||||
import org.bukkit.entity.Display;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.TextDisplay;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.block.*;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Linked
|
||||
@MinVersion(20)
|
||||
public class PistonCalculator implements Listener {
|
||||
|
||||
private final Map<Player, Long> DEBOUNCE = new HashMap<>();
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerInteract(PlayerInteractEvent event) {
|
||||
if (!Permission.BUILD.hasPermission(event.getPlayer())) return;
|
||||
if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return;
|
||||
if (!event.hasItem() || event.getItem().getType() != Material.SLIME_BALL) return;
|
||||
if (event.getItem() == null) {}
|
||||
else if (event.getItem() != null && event.getItem().getType() == Material.SLIME_BALL) {}
|
||||
else if (!event.getItem().getType().isBlock()) {
|
||||
DEBOUNCE.put(event.getPlayer(), System.currentTimeMillis());
|
||||
return;
|
||||
}
|
||||
else return;
|
||||
if (event.getClickedBlock() == null) return;
|
||||
Block clickedBlock = event.getClickedBlock();
|
||||
Material blockType = clickedBlock.getType();
|
||||
if (!(blockType == Material.PISTON || blockType == Material.STICKY_PISTON)) return;
|
||||
Piston piston = (Piston) clickedBlock.getBlockData();
|
||||
if (System.currentTimeMillis() - DEBOUNCE.getOrDefault(event.getPlayer(), 0L) <= 200) return;
|
||||
DEBOUNCE.put(event.getPlayer(), System.currentTimeMillis());
|
||||
|
||||
if (blockType == Material.PISTON && piston.isExtended()) {
|
||||
BauSystem.MESSAGE.sendPrefixless("PISTON_INFO", event.getPlayer(), ChatMessageType.ACTION_BAR, "§a", 0);
|
||||
Location location = event.getClickedBlock().getLocation();
|
||||
if (pistOrders.containsKey(location)) {
|
||||
PistOrder pistOrder = pistOrders.get(location);
|
||||
if (pistOrder.server.getPlayers().contains(event.getPlayer())) {
|
||||
pistOrder.server.removePlayer(event.getPlayer());
|
||||
} else {
|
||||
pistOrder.server.addPlayer(event.getPlayer());
|
||||
}
|
||||
if (pistOrder.server.getPlayers().isEmpty()) {
|
||||
pistOrders.remove(location);
|
||||
pistOrder.server.close();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
boolean pulling = blockType == Material.STICKY_PISTON && (clickedBlock.getRelative(piston.getFacing()).getType() == Material.AIR || piston.isExtended());
|
||||
PistOrder pistOrder = new PistOrder(clickedBlock);
|
||||
pistOrder.calculate();
|
||||
pistOrder.server.addPlayer(event.getPlayer());
|
||||
pistOrders.put(location, pistOrder);
|
||||
}
|
||||
|
||||
CalculationResult result = calc(clickedBlock, piston.getFacing(), (pulling ? piston.getFacing().getOppositeFace() : piston.getFacing()));
|
||||
result.entityServer.addPlayer(event.getPlayer());
|
||||
BauSystem.MESSAGE.sendPrefixless("PISTON_INFO", event.getPlayer(), ChatMessageType.ACTION_BAR, result.unmovable ? "§c" : (result.tooMany ? "§e" : "§a"), result.amount);
|
||||
@EventHandler
|
||||
public void onBlockPistonExtend(BlockPistonExtendEvent event) {
|
||||
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> {
|
||||
movePistOrders(event.getDirection(), event.getBlocks());
|
||||
pistOrders.values().forEach(PistOrder::calculate);
|
||||
}, 3);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onBlockPistonRetract(BlockPistonRetractEvent event) {
|
||||
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> {
|
||||
movePistOrders(event.getDirection(), event.getBlocks());
|
||||
pistOrders.values().forEach(PistOrder::calculate);
|
||||
}, 3);
|
||||
}
|
||||
|
||||
private void movePistOrders(BlockFace direction, List<Block> blocks) {
|
||||
Set<PistOrder> orders = new HashSet<>();
|
||||
blocks.forEach(block -> {
|
||||
PistOrder pistOrder = pistOrders.get(block.getLocation());
|
||||
if (pistOrder == null) return;
|
||||
pistOrders.remove(block.getLocation());
|
||||
pistOrder.piston = pistOrder.piston.getRelative(direction);
|
||||
orders.add(pistOrder);
|
||||
});
|
||||
orders.forEach(pistOrder -> {
|
||||
pistOrders.put(pistOrder.piston.getLocation(), pistOrder);
|
||||
});
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onBlockPlace(BlockPlaceEvent event) {
|
||||
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> {
|
||||
pistOrders.values().forEach(PistOrder::calculate);
|
||||
}, 1);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onBlockBreak(BlockBreakEvent event) {
|
||||
if (pistOrders.containsKey(event.getBlock().getLocation())) {
|
||||
PistOrder pistOrder = pistOrders.remove(event.getBlock().getLocation());
|
||||
pistOrder.server.close();
|
||||
}
|
||||
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> {
|
||||
pistOrders.values().forEach(PistOrder::calculate);
|
||||
}, 1);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||
DEBOUNCE.remove(event.getPlayer());
|
||||
|
||||
Set<Location> toRemove = new HashSet<>();
|
||||
pistOrders.forEach((location, pistOrder) -> {
|
||||
pistOrder.server.removePlayer(event.getPlayer());
|
||||
if (pistOrder.server.getPlayers().isEmpty()) {
|
||||
toRemove.add(location);
|
||||
pistOrder.server.close();
|
||||
}
|
||||
});
|
||||
toRemove.forEach(pistOrders::remove);
|
||||
}
|
||||
|
||||
private final BlockFace[] FACES = new BlockFace[]{BlockFace.UP, BlockFace.DOWN, BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST};
|
||||
|
||||
private CalculationResult calc(Block origin, BlockFace facing, BlockFace direction) {
|
||||
Set<Block> blockSet = new HashSet<>();
|
||||
Set<Location> unmovable = new HashSet<>();
|
||||
private final Map<Location, PistOrder> pistOrders = new HashMap<>();
|
||||
|
||||
private final class PistOrder {
|
||||
private Block piston;
|
||||
private REntityServer server = new REntityServer();
|
||||
|
||||
private boolean pulling = false;
|
||||
private List<Location> movedBlocks = new ArrayList<>();
|
||||
private List<Location> brokenBlocks = new ArrayList<>();
|
||||
private Set<Location> immovableBlocks = new HashSet<>();
|
||||
|
||||
public PistOrder(Block piston) {
|
||||
this.piston = piston;
|
||||
}
|
||||
|
||||
public void calculate() {
|
||||
movedBlocks.clear();
|
||||
brokenBlocks.clear();
|
||||
immovableBlocks.clear();
|
||||
|
||||
if (piston.isEmpty()) {
|
||||
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> {
|
||||
server.close();
|
||||
pistOrders.remove(piston.getLocation());
|
||||
}, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
BlockData blockData = piston.getBlockData();
|
||||
if (!(blockData instanceof Piston)) return;
|
||||
Piston pistonData = (Piston) blockData;
|
||||
if (piston.getType() == Material.PISTON && pistonData.isExtended()) {
|
||||
visualize();
|
||||
return;
|
||||
}
|
||||
|
||||
pulling = piston.getType() == Material.STICKY_PISTON && (piston.getRelative(pistonData.getFacing()).getType() == Material.AIR || pistonData.isExtended());
|
||||
|
||||
calculate(piston, pistonData.getFacing(), (pulling ? pistonData.getFacing().getOppositeFace() : pistonData.getFacing()));
|
||||
|
||||
Collections.reverse(movedBlocks);
|
||||
Collections.reverse(brokenBlocks);
|
||||
|
||||
visualize();
|
||||
}
|
||||
|
||||
private void calculate(Block origin, BlockFace facing, BlockFace direction) {
|
||||
Block calcOrigin = origin;
|
||||
if (facing != direction) calcOrigin = origin.getRelative(facing, 3);
|
||||
|
||||
List<Block> toCalc = new LinkedList<>();
|
||||
calcDirection(origin, null, calcOrigin, facing != direction ? origin.getRelative(facing) : null, facing, direction, blockSet, toCalc, unmovable);
|
||||
calcDirection(origin, null, calcOrigin, facing != direction ? origin.getRelative(facing) : null, facing, direction, toCalc);
|
||||
|
||||
while (!toCalc.isEmpty()) {
|
||||
Block current = toCalc.remove(0);
|
||||
blockSet.add(current);
|
||||
if (!movedBlocks.contains(current.getLocation())) {
|
||||
movedBlocks.add(current.getLocation());
|
||||
}
|
||||
|
||||
Material type = current.getType();
|
||||
if (type != Material.SLIME_BLOCK && type != Material.HONEY_BLOCK) continue;
|
||||
@ -94,44 +221,132 @@ public class PistonCalculator implements Listener {
|
||||
for (BlockFace face : FACES) {
|
||||
Block block = current.getRelative(face);
|
||||
if (block.getType().isAir()) continue;
|
||||
if (!isPiston(block) && (block.getPistonMoveReaction() == PistonMoveReaction.BLOCK || block.getPistonMoveReaction() == PistonMoveReaction.IGNORE || block.getPistonMoveReaction() == PistonMoveReaction.PUSH_ONLY || block.getState() instanceof TileState || block.getPistonMoveReaction() == PistonMoveReaction.BREAK)) continue;
|
||||
if (isImmovable(block) || block.getPistonMoveReaction() == PistonMoveReaction.BREAK) continue;
|
||||
if (block.getType() != oppositeType) {
|
||||
if (!blockSet.contains(block)) toCalc.add(block);
|
||||
calcDirection(null, origin, block, null, facing, direction, blockSet, toCalc, unmovable);
|
||||
if (!movedBlocks.contains(block.getLocation())) toCalc.add(block);
|
||||
calcDirection(null, origin, block, null, facing, direction, toCalc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
blockSet.remove(origin);
|
||||
if (facing != direction) blockSet.remove(origin.getRelative(facing, 1));
|
||||
|
||||
REntityServer entityServer = new REntityServer();
|
||||
for (Location loc : unmovable) {
|
||||
RFallingBlockEntity rFallingBlockEntity = new RFallingBlockEntity(entityServer, loc.clone().add(0.5, 0, 0.5), Material.RED_STAINED_GLASS);
|
||||
rFallingBlockEntity.setGlowing(true);
|
||||
rFallingBlockEntity.setNoGravity(true);
|
||||
rFallingBlockEntity.setInvisible(true);
|
||||
}
|
||||
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), entityServer::close, 20);
|
||||
return new CalculationResult(blockSet.size(), blockSet.size() > 12, !unmovable.isEmpty(), entityServer);
|
||||
movedBlocks.remove(origin.getLocation());
|
||||
if (facing != direction) movedBlocks.remove(origin.getRelative(facing, 1).getLocation());
|
||||
if (pulling) immovableBlocks.remove(origin.getRelative(facing).getLocation());
|
||||
}
|
||||
|
||||
private void calcDirection(Block origin, Block blockOrigin, Block calcOrigin, Block ignore, BlockFace facing, BlockFace direction, Set<Block> blockSet, List<Block> toCalc, Set<Location> unmovable) {
|
||||
private void calcDirection(Block origin, Block blockOrigin, Block calcOrigin, Block ignore, BlockFace facing, BlockFace direction, List<Block> toCalc) {
|
||||
for (int i = 1; i < 24; i++) {
|
||||
Block block = calcOrigin.getRelative(direction, i);
|
||||
if (block.equals(ignore)) return;
|
||||
if (block.getPistonMoveReaction() == PistonMoveReaction.BREAK) return;
|
||||
if (!isPiston(block) && (block.getPistonMoveReaction() == PistonMoveReaction.BLOCK || block.getPistonMoveReaction() == PistonMoveReaction.IGNORE || block.getState() instanceof TileState)) {
|
||||
unmovable.add(block.getLocation());
|
||||
if (block.getPistonMoveReaction() == PistonMoveReaction.BREAK) {
|
||||
if (!brokenBlocks.contains(block.getLocation())) {
|
||||
brokenBlocks.add(block.getLocation());
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (isImmovable(block)) {
|
||||
immovableBlocks.add(block.getLocation());
|
||||
return;
|
||||
}
|
||||
if (block.getType().isAir()) return;
|
||||
if (facing == direction && block.equals(blockOrigin)) {
|
||||
unmovable.add(block.getLocation());
|
||||
immovableBlocks.add(block.getLocation());
|
||||
return;
|
||||
}
|
||||
if (facing != direction && (block.equals(origin) || block.getRelative(facing.getOppositeFace()).equals(origin))) return;
|
||||
if (!blockSet.contains(block)) toCalc.add(block);
|
||||
if (!movedBlocks.contains(block.getLocation())) toCalc.add(block);
|
||||
}
|
||||
}
|
||||
|
||||
private void visualize() {
|
||||
server.getEntities().forEach(REntity::die);
|
||||
|
||||
for (int i = 0; i < movedBlocks.size(); i++) {
|
||||
Location location = movedBlocks.get(i);
|
||||
int order = i + 1;
|
||||
|
||||
CCubedTextDisplay display = new CCubedTextDisplay(server, location);
|
||||
display.setText("§e" + order);
|
||||
display.setBackgroundColor(0);
|
||||
display.setShadowed(false);
|
||||
|
||||
Set<BlockFace> toHide = Arrays.stream(FACES).filter(blockFace -> {
|
||||
return movedBlocks.contains(location.clone().add(blockFace.getModX(), blockFace.getModY(), blockFace.getModZ()));
|
||||
}).collect(Collectors.toSet());
|
||||
display.hide(toHide);
|
||||
}
|
||||
|
||||
for (int i = 0; i < brokenBlocks.size(); i++) {
|
||||
Location location = brokenBlocks.get(i);
|
||||
int order = i + 1;
|
||||
|
||||
RTextDisplay textDisplay = new RTextDisplay(server, location.clone().add(0.5, 0.4, 0.5));
|
||||
textDisplay.setText("§c" + order);
|
||||
textDisplay.setBillboard(Display.Billboard.CENTER);
|
||||
textDisplay.setAlignment(TextDisplay.TextAlignment.CENTER);
|
||||
textDisplay.setSeeThrough(true);
|
||||
textDisplay.setBackgroundColor(0);
|
||||
textDisplay.setShadowed(false);
|
||||
textDisplay.setBrightness(new Display.Brightness(15, 15));
|
||||
}
|
||||
|
||||
for (Location location : immovableBlocks) {
|
||||
CWireframe wireframe = new CWireframe(server);
|
||||
wireframe.setPos1(location);
|
||||
wireframe.setPos2(location);
|
||||
wireframe.setWidth(1 / 32f);
|
||||
wireframe.setBlock(Material.RED_CONCRETE.createBlockData());
|
||||
}
|
||||
|
||||
CWireframe wireframe = new CWireframe(server);
|
||||
wireframe.setPos1(piston.getLocation());
|
||||
wireframe.setPos2(piston.getLocation());
|
||||
if (!immovableBlocks.isEmpty()) {
|
||||
wireframe.setBlock(Material.RED_CONCRETE.createBlockData());
|
||||
} else if (movedBlocks.size() > 12) {
|
||||
wireframe.setBlock(Material.YELLOW_CONCRETE.createBlockData());
|
||||
} else {
|
||||
wireframe.setBlock(Material.LIME_CONCRETE.createBlockData());
|
||||
}
|
||||
wireframe.setWidth(1 / 32f);
|
||||
|
||||
RTextDisplay textDisplay = new RTextDisplay(server, piston.getLocation().clone().add(0.5, 0.3, 0.5));
|
||||
StringBuilder text = new StringBuilder();
|
||||
if (pulling) {
|
||||
text.append("§ePull\n");
|
||||
} else {
|
||||
text.append("§ePush\n");
|
||||
}
|
||||
text.append("§f").append(movedBlocks.size()).append(" §eBlocks");
|
||||
textDisplay.setText(text.toString());
|
||||
textDisplay.setBillboard(Display.Billboard.CENTER);
|
||||
textDisplay.setAlignment(TextDisplay.TextAlignment.CENTER);
|
||||
textDisplay.setSeeThrough(true);
|
||||
textDisplay.setBackgroundColor(0);
|
||||
textDisplay.setShadowed(false);
|
||||
textDisplay.setBrightness(new Display.Brightness(15, 15));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isImmovable(Block block) {
|
||||
if (block.isEmpty() || block.isLiquid()) {
|
||||
return false;
|
||||
}
|
||||
BlockData blockData = block.getBlockData();
|
||||
if (blockData instanceof Piston) {
|
||||
return ((Piston) blockData).isExtended();
|
||||
}
|
||||
if (block.getState() instanceof TileState) {
|
||||
return true;
|
||||
}
|
||||
PistonMoveReaction reaction = block.getPistonMoveReaction();
|
||||
if (reaction == PistonMoveReaction.IGNORE) return true;
|
||||
if (reaction == PistonMoveReaction.BLOCK) return true;
|
||||
switch (block.getType()) {
|
||||
case OBSIDIAN:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -142,13 +357,4 @@ public class PistonCalculator implements Listener {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
private static class CalculationResult {
|
||||
private int amount;
|
||||
private boolean tooMany;
|
||||
private boolean unmovable;
|
||||
private REntityServer entityServer;
|
||||
}
|
||||
}
|
||||
|
||||
@ -22,9 +22,11 @@ package de.steamwar.bausystem.features.util;
|
||||
import de.steamwar.bausystem.BauSystem;
|
||||
import de.steamwar.command.SWCommand;
|
||||
import de.steamwar.linkage.Linked;
|
||||
import de.steamwar.linkage.MinVersion;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
@Linked
|
||||
@MinVersion(20)
|
||||
public class PistonCalculatorCommand extends SWCommand {
|
||||
|
||||
public PistonCalculatorCommand() {
|
||||
|
||||
@ -21,6 +21,7 @@ package de.steamwar.bausystem.features.world;
|
||||
|
||||
import de.steamwar.bausystem.Permission;
|
||||
import de.steamwar.linkage.Linked;
|
||||
import de.steamwar.sql.NodeData;
|
||||
import de.steamwar.sql.SchematicData;
|
||||
import de.steamwar.sql.SchematicNode;
|
||||
import de.steamwar.sql.SteamwarUser;
|
||||
@ -65,7 +66,8 @@ public class ClipboardListener implements Listener {
|
||||
}
|
||||
|
||||
try {
|
||||
new SchematicData(schematic).saveFromPlayer(e.getPlayer());
|
||||
NodeData.get(schematic).forEach(NodeData::delete);
|
||||
SchematicData.saveFromPlayer(e.getPlayer(), schematic);
|
||||
} catch (Exception ex) {
|
||||
if (newSchem) {
|
||||
schematic.delete();
|
||||
|
||||
@ -0,0 +1,180 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2020 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.bausystem.features.worldedit;
|
||||
|
||||
import de.steamwar.bausystem.BauSystem;
|
||||
import de.steamwar.bausystem.region.Point;
|
||||
import de.steamwar.bausystem.utils.FlatteningWrapper;
|
||||
import de.steamwar.core.WorldEditRenderer;
|
||||
import de.steamwar.linkage.Linked;
|
||||
import de.steamwar.linkage.MinVersion;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
@Linked
|
||||
@MinVersion(20)
|
||||
public class SelectAdjacent implements Listener {
|
||||
|
||||
private Vector[] FACES = {
|
||||
new Vector(1, 0, 0),
|
||||
new Vector(-1, 0, 0),
|
||||
new Vector(0, 1, 0),
|
||||
new Vector(0, -1, 0),
|
||||
new Vector(0, 0, 1),
|
||||
new Vector(0, 0, -1),
|
||||
|
||||
new Vector(1, 1, 0),
|
||||
new Vector(1, -1, 0),
|
||||
new Vector(1, 0, 1),
|
||||
new Vector(1, 0, -1),
|
||||
new Vector(-1, 1, 0),
|
||||
new Vector(-1, -1, 0),
|
||||
new Vector(-1, 0, 1),
|
||||
new Vector(-1, 0, -1),
|
||||
new Vector(0, 1, 1),
|
||||
new Vector(0, 1, -1),
|
||||
new Vector(0, -1, 1),
|
||||
new Vector(0, -1, -1),
|
||||
};
|
||||
|
||||
private Map<Player, Selector> selectors = new HashMap<>();
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerInteract(PlayerInteractEvent event) {
|
||||
if (!event.hasItem()) return;
|
||||
if (event.getItem().getType() != Material.WOODEN_AXE) return;
|
||||
if (!event.getPlayer().isSneaking()) return;
|
||||
if (event.getAction() != Action.LEFT_CLICK_BLOCK) return;
|
||||
Selector selector = selectors.get(event.getPlayer());
|
||||
if (selector != null) selector.cancel();
|
||||
Material material = event.getPlayer().getInventory().getItemInOffHand().getType();
|
||||
if (material.isAir()) {
|
||||
selector = new Selector(event.getClickedBlock(), event.getPlayer(), __ -> true);
|
||||
} else {
|
||||
selector = new Selector(event.getClickedBlock(), event.getPlayer(), type -> type == material);
|
||||
}
|
||||
selectors.put(event.getPlayer(), selector);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
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 int minX;
|
||||
private int minY;
|
||||
private int minZ;
|
||||
private int maxX;
|
||||
private int maxY;
|
||||
private int maxZ;
|
||||
|
||||
private BukkitTask bukkitTask;
|
||||
private Predicate<Material> predicate;
|
||||
private Set<Location> seen = new HashSet<>();
|
||||
private Set<Location> toCalc = new HashSet<>();
|
||||
|
||||
public Selector(Block block, Player player, Predicate<Material> predicate) {
|
||||
this.predicate = predicate;
|
||||
toCalc.add(block.getLocation());
|
||||
minX = block.getX();
|
||||
minY = block.getY();
|
||||
minZ = block.getZ();
|
||||
maxX = block.getX();
|
||||
maxY = block.getY();
|
||||
maxZ = block.getZ();
|
||||
|
||||
bukkitTask = Bukkit.getScheduler().runTaskTimer(BauSystem.getInstance(), () -> {
|
||||
run();
|
||||
|
||||
long volume = (long)(maxX - minX + 1) * (long)(maxY - minY + 1) * (long)(maxZ - minZ + 1);
|
||||
player.sendTitle("", "§e" + volume + " §7Blocks", 0, 5, 0);
|
||||
|
||||
Point minPoint = new Point(minX, minY, minZ);
|
||||
Point maxPoint = new Point(maxX, maxY, maxZ);
|
||||
|
||||
FlatteningWrapper.impl.setSelection(player, minPoint, maxPoint);
|
||||
WorldEditRenderer.renderPlayer(player);
|
||||
|
||||
// boolean finished = toCalc.stream().allMatch(location -> {
|
||||
// return location.getBlockX() >= minX && location.getBlockY() >= minY && location.getBlockZ() >= minZ &&
|
||||
// location.getBlockX() <= maxX && location.getBlockY() <= maxY && location.getBlockZ() <= maxZ;
|
||||
// });
|
||||
|
||||
if (toCalc.isEmpty() || seen.size() > MAX_BLOCKS) {
|
||||
bukkitTask.cancel();
|
||||
player.sendTitle("§aDone", "§e" + volume + " §7Blocks", 0, 20, 5);
|
||||
}
|
||||
}, 1, 1);
|
||||
}
|
||||
|
||||
private void cancel() {
|
||||
bukkitTask.cancel();
|
||||
}
|
||||
|
||||
private void run() {
|
||||
Set<Location> current = toCalc;
|
||||
toCalc = new HashSet<>();
|
||||
|
||||
for (Location location : current) {
|
||||
Block block = location.getBlock();
|
||||
if (block.isEmpty() || block.isLiquid()) continue;
|
||||
if (!predicate.test(block.getType())) continue;
|
||||
seen.add(location);
|
||||
|
||||
minX = Math.min(minX, location.getBlockX());
|
||||
maxX = Math.max(maxX, location.getBlockX());
|
||||
minY = Math.min(minY, location.getBlockY());
|
||||
maxY = Math.max(maxY, location.getBlockY());
|
||||
minZ = Math.min(minZ, location.getBlockZ());
|
||||
maxZ = Math.max(maxZ, location.getBlockZ());
|
||||
|
||||
for (Vector face : FACES) {
|
||||
Block next = block.getRelative(face.getBlockX(), face.getBlockY(), face.getBlockZ());
|
||||
if (next.isEmpty() || next.isLiquid()) continue;
|
||||
if (!predicate.test(next.getType())) continue;
|
||||
Location loc = next.getLocation();
|
||||
if (seen.contains(loc)) continue;
|
||||
toCalc.add(loc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -145,6 +145,13 @@ public class PasteBuilder {
|
||||
public PasteBuilder removeWater(boolean removeWater) {
|
||||
if (!removeWater) return this;
|
||||
BaseBlock water = Objects.requireNonNull(BlockTypes.get("water")).getDefaultState().toBaseBlock();
|
||||
BlockType bubble_column_type = BlockTypes.get("bubble_column");
|
||||
BaseBlock bubble_column;
|
||||
if (bubble_column_type == null) {
|
||||
bubble_column = null;
|
||||
} else {
|
||||
bubble_column = bubble_column_type.getDefaultState().toBaseBlock();
|
||||
}
|
||||
BaseBlock air = Objects.requireNonNull(BlockTypes.get("air")).getDefaultState().toBaseBlock();
|
||||
WaterloggedRemover waterloggedRemover = new WaterloggedRemover(getClipboard());
|
||||
|
||||
@ -154,6 +161,10 @@ public class PasteBuilder {
|
||||
clipboard.setBlock(blockVector3, air);
|
||||
return;
|
||||
}
|
||||
if (bubble_column != null && baseBlock.equals(bubble_column)) {
|
||||
clipboard.setBlock(blockVector3, air);
|
||||
return;
|
||||
}
|
||||
String blockName = clipboard.getFullBlock(blockVector3).getBlockType().getName();
|
||||
if (blockName.equals("Water")) {
|
||||
clipboard.setBlock(blockVector3, air);
|
||||
|
||||
@ -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 de.steamwar.bausystem.BauSystem;
|
||||
import de.steamwar.core.VersionDependent;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
public interface TickManager extends Listener {
|
||||
TickManager impl = VersionDependent.getVersionImpl(BauSystem.getInstance());
|
||||
|
||||
void setTickRate(float tickRate);
|
||||
float getTickRate();
|
||||
|
||||
boolean canFreeze();
|
||||
void setFreeze(boolean freeze);
|
||||
boolean isFrozen();
|
||||
|
||||
void stepTicks(int ticks);
|
||||
boolean isStepping();
|
||||
|
||||
void sprintTicks(int ticks);
|
||||
boolean isSprinting();
|
||||
|
||||
void setBlockTpsPacket(boolean block);
|
||||
long getRemainingTicks();
|
||||
long getDoneTicks();
|
||||
long getTotalTicks();
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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.network.packets.client;
|
||||
|
||||
import de.steamwar.network.packets.NetworkPacket;
|
||||
import lombok.*;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@ToString
|
||||
@Builder(toBuilder = true)
|
||||
public class AnvilAnswerPacket extends NetworkPacket {
|
||||
private int playerId;
|
||||
private Action action;
|
||||
private String text;
|
||||
|
||||
public enum Action {
|
||||
CLOSE,
|
||||
ANSWER,
|
||||
LEFT_CLICK
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.network.packets.server;
|
||||
|
||||
import de.steamwar.network.packets.NetworkPacket;
|
||||
import lombok.*;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@ToString
|
||||
public class AnvilInventoryPacket extends NetworkPacket {
|
||||
private static final long serialVersionUID = -6004390311854048209L;
|
||||
private int playerId;
|
||||
private String title;
|
||||
private String defaultText;
|
||||
private String material;
|
||||
}
|
||||
125
CommonCore/SQL/src/de/steamwar/sql/AuditLog.java
Normal file
125
CommonCore/SQL/src/de/steamwar/sql/AuditLog.java
Normal file
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2020 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.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);
|
||||
}
|
||||
}
|
||||
@ -35,7 +35,8 @@ import java.util.stream.Collectors;
|
||||
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.AllowReplay) AND (r.NodeId IS NULL OR r.AllowReplay) 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> 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");
|
||||
|
||||
@ -51,6 +52,10 @@ public class Fight {
|
||||
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);
|
||||
}
|
||||
|
||||
@ -23,8 +23,13 @@ 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
|
||||
@ -40,26 +45,47 @@ public class NodeData {
|
||||
|
||||
private static final Table<NodeData> table = new Table<>(NodeData.class);
|
||||
|
||||
private static final Statement updateDatabase = new Statement("INSERT INTO NodeData(NodeId, NodeFormat, SchemData) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE NodeFormat = VALUES(NodeFormat), SchemData = VALUES(SchemData)");
|
||||
private static final Statement selSchemData = new Statement("SELECT SchemData FROM NodeData WHERE NodeId = ?");
|
||||
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 = table.select(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 get(SchematicNode node) {
|
||||
if(node.isDir())
|
||||
throw new IllegalArgumentException("Node is a directory");
|
||||
return get.select(rs -> {
|
||||
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 new NodeData(node.getId(), SchematicFormat.values()[rs.getInt("NodeFormat")]);
|
||||
return rs.getInt("CNT");
|
||||
} else {
|
||||
return new NodeData(node.getId(), SchematicFormat.MCEDIT);
|
||||
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;
|
||||
|
||||
@ -84,15 +110,19 @@ public class NodeData {
|
||||
} catch (IOException e) {
|
||||
throw new SecurityException("SchemData is wrong", e);
|
||||
}
|
||||
}, nodeId);
|
||||
}, nodeId, createdAt);
|
||||
} catch (Exception e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void saveFromStream(InputStream blob, SchematicFormat newFormat) {
|
||||
updateDatabase.update(nodeId, newFormat, blob);
|
||||
nodeFormat = newFormat;
|
||||
saveFromStream(SchematicNode.getSchematicNode(nodeId), blob, newFormat);
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
delete.update(nodeId, createdAt);
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
|
||||
@ -42,13 +42,13 @@ public class SchematicNode {
|
||||
TAB_CACHE.clear();
|
||||
}
|
||||
|
||||
private static final String nodeSelector = "SELECT NodeId, NodeOwner, NodeOwner AS EffectiveOwner, NodeName, ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, ReplaceColor, AllowReplay FROM SchematicNode ";
|
||||
private static final String nodeSelector = "SELECT NodeId, NodeOwner, NodeOwner AS EffectiveOwner, NodeName, ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, Config FROM SchematicNode ";
|
||||
|
||||
private static final Table<SchematicNode> table = new Table<>(SchematicNode.class);
|
||||
private static final Statement create = table.insertFields(true, "NodeOwner", "NodeName", "ParentNode", "NodeItem",
|
||||
"NodeType");
|
||||
private static final Statement update = table.update(Table.PRIMARY, "NodeName", "ParentNode", "NodeItem",
|
||||
"NodeType", "NodeRank", "ReplaceColor", "AllowReplay");
|
||||
"NodeType", "NodeRank", "Config");
|
||||
private static final Statement delete = table.delete(Table.PRIMARY);
|
||||
|
||||
private static final SelectStatement<SchematicNode> byId = new SelectStatement<>(table,
|
||||
@ -66,13 +66,13 @@ public class SchematicNode {
|
||||
private static final SelectStatement<SchematicNode> all = new SelectStatement<>(table,
|
||||
"WITH RECURSIVE Nodes AS (SELECT NodeId, ParentId as ParentNode FROM NodeMember WHERE UserId = ? UNION SELECT NodeId, ParentNode FROM SchematicNode WHERE NodeOwner = ?), RSN AS ( SELECT NodeId, ParentNode FROM Nodes UNION SELECT SN.NodeId, SN.ParentNode FROM SchematicNode SN, RSN WHERE SN.ParentNode = RSN.NodeId ) SELECT SN.*, ? AS EffectiveOwner FROM RSN INNER JOIN SchematicNode SN ON RSN.NodeId = SN.NodeId");
|
||||
private static final SelectStatement<SchematicNode> list = new SelectStatement<>(table,
|
||||
"SELECT SchematicNode.NodeId, NodeOwner, ? AS EffectiveOwner, NodeName, NM.ParentId AS ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, ReplaceColor, AllowReplay FROM SchematicNode INNER JOIN NodeMember NM on SchematicNode.NodeId = NM.NodeId WHERE NM.ParentId "
|
||||
"SELECT SchematicNode.NodeId, NodeOwner, ? AS EffectiveOwner, NodeName, NM.ParentId AS ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, Config FROM SchematicNode INNER JOIN NodeMember NM on SchematicNode.NodeId = NM.NodeId WHERE NM.ParentId "
|
||||
+ Statement.NULL_SAFE_EQUALS
|
||||
+ "? AND NM.UserId = ? UNION ALL SELECT SchematicNode.NodeId, NodeOwner, ? AS EffectiveOwner, NodeName, ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, ReplaceColor, AllowReplay FROM SchematicNode WHERE (? IS NULL AND ParentNode IS NULL AND NodeOwner = ?) OR (? IS NOT NULL AND ParentNode = ?) ORDER BY NodeName");
|
||||
+ "? AND NM.UserId = ? UNION ALL SELECT SchematicNode.NodeId, NodeOwner, ? AS EffectiveOwner, NodeName, ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, Config FROM SchematicNode WHERE (? IS NULL AND ParentNode IS NULL AND NodeOwner = ?) OR (? IS NOT NULL AND ParentNode = ?) ORDER BY NodeName");
|
||||
private static final SelectStatement<SchematicNode> byParentName = new SelectStatement<>(table,
|
||||
"SELECT SchematicNode.NodeId, NodeOwner, ? AS EffectiveOwner, NodeName, NM.ParentId AS ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, ReplaceColor, AllowReplay FROM SchematicNode INNER JOIN NodeMember NM on SchematicNode.NodeId = NM.NodeId WHERE NM.ParentId "
|
||||
"SELECT SchematicNode.NodeId, NodeOwner, ? AS EffectiveOwner, NodeName, NM.ParentId AS ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, Config FROM SchematicNode INNER JOIN NodeMember NM on SchematicNode.NodeId = NM.NodeId WHERE NM.ParentId "
|
||||
+ Statement.NULL_SAFE_EQUALS
|
||||
+ "? AND NM.UserId = ? AND SchematicNode.NodeName = ? UNION ALL SELECT SchematicNode.NodeId, NodeOwner, ? AS EffectiveOwner, NodeName, ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, ReplaceColor, AllowReplay FROM SchematicNode WHERE ((? IS NULL AND ParentNode IS NULL AND NodeOwner = ?) OR (? IS NOT NULL AND ParentNode = ?)) AND NodeName = ?");
|
||||
+ "? AND NM.UserId = ? AND SchematicNode.NodeName = ? UNION ALL SELECT SchematicNode.NodeId, NodeOwner, ? AS EffectiveOwner, NodeName, ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, Config FROM SchematicNode WHERE ((? IS NULL AND ParentNode IS NULL AND NodeOwner = ?) OR (? IS NOT NULL AND ParentNode = ?)) AND NodeName = ?");
|
||||
private static final SelectStatement<SchematicNode> schematicAccessibleForUser = new SelectStatement<>(table,
|
||||
"WITH RECURSIVE Nodes AS (SELECT NodeId, ParentId as ParentNode FROM NodeMember WHERE UserId = ? UNION SELECT NodeId, ParentNode FROM SchematicNode WHERE NodeOwner = ?), RSN AS ( SELECT NodeId, ParentNode FROM Nodes UNION SELECT SN.NodeId, SN.ParentNode FROM SchematicNode SN, RSN WHERE SN.ParentNode = RSN.NodeId ) SELECT SN.*, ? AS EffectiveOwner FROM RSN INNER JOIN SchematicNode SN ON RSN.NodeId = SN.NodeId WHERE NodeId = ?");
|
||||
private static final SelectStatement<SchematicNode> accessibleByUserTypeInParent = new SelectStatement<>(table,
|
||||
@ -81,7 +81,7 @@ public class SchematicNode {
|
||||
private static final SelectStatement<SchematicNode> accessibleByUserType = new SelectStatement<>(table,
|
||||
"WITH RECURSIVE Nodes AS (SELECT NodeId, ParentId as ParentNode FROM NodeMember WHERE UserId = ? UNION SELECT NodeId, ParentNode FROM SchematicNode WHERE NodeOwner = ?), RSN AS ( SELECT NodeId, ParentNode FROM Nodes UNION SELECT SN.NodeId, SN.ParentNode FROM SchematicNode SN, RSN WHERE SN.ParentNode = RSN.NodeId ) SELECT SN.*, ? AS EffectiveOwner FROM RSN INNER JOIN SchematicNode SN ON RSN.NodeId = SN.NodeId WHERE NodeType = ?");
|
||||
private static final SelectStatement<SchematicNode> byIdAndUser = new SelectStatement<>(table,
|
||||
"SELECT NodeId, NodeOwner, ? AS EffectiveOwner, NodeName, ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, ReplaceColor, AllowReplay FROM SchematicNode WHERE NodeId = ?");
|
||||
"SELECT NodeId, NodeOwner, ? AS EffectiveOwner, NodeName, ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, Config FROM SchematicNode WHERE NodeId = ?");
|
||||
private static final SelectStatement<SchematicNode> allParentsOfNode = new SelectStatement<>(table,
|
||||
"WITH RECURSIVE R AS (SELECT NodeId, ParentNode FROM EffectiveSchematicNode WHERE NodeId = ? AND EffectiveOwner = ? UNION SELECT E.NodeId, E.ParentNode FROM R, EffectiveSchematicNode E WHERE R.ParentNode = E.NodeId AND E.EffectiveOwner = ?) SELECT SN.NodeId, SN.NodeOwner, ? AS EffectiveOwner, SN.NodeName, R.ParentNode, SN.LastUpdate, SN.NodeItem, SN.NodeType, SN.NodeRank, SN.ReplaceColor, SN.AllowReplay FROM R INNER JOIN SchematicNode SN ON SN.NodeId = R.NodeId");
|
||||
|
||||
@ -108,10 +108,8 @@ public class SchematicNode {
|
||||
private SchematicType nodeType;
|
||||
@Field(def = "0")
|
||||
private int nodeRank;
|
||||
@Field(def = "1")
|
||||
private boolean replaceColor;
|
||||
@Field(def = "1")
|
||||
private boolean allowReplay;
|
||||
@Field
|
||||
private int config;
|
||||
|
||||
private String brCache;
|
||||
|
||||
@ -125,8 +123,7 @@ public class SchematicNode {
|
||||
String nodeItem,
|
||||
SchematicType nodeType,
|
||||
int nodeRank,
|
||||
boolean replaceColor,
|
||||
boolean allowReplay) {
|
||||
int config) {
|
||||
this.nodeId = nodeId;
|
||||
this.nodeOwner = nodeOwner;
|
||||
this.effectiveOwner = effectiveOwner;
|
||||
@ -136,8 +133,7 @@ public class SchematicNode {
|
||||
this.nodeType = nodeType;
|
||||
this.lastUpdate = lastUpdate;
|
||||
this.nodeRank = nodeRank;
|
||||
this.replaceColor = replaceColor;
|
||||
this.allowReplay = allowReplay;
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
public static List<SchematicNode> getAll(SteamwarUser user) {
|
||||
@ -407,7 +403,7 @@ public class SchematicNode {
|
||||
public String getFileEnding() {
|
||||
if (isDir())
|
||||
throw new SecurityException("Node is Directory");
|
||||
return NodeData.get(this).getNodeFormat().getFileEnding();
|
||||
return NodeData.getLatest(this).getNodeFormat().getFileEnding();
|
||||
}
|
||||
|
||||
public int getRank() {
|
||||
@ -441,24 +437,45 @@ public class SchematicNode {
|
||||
}
|
||||
|
||||
public boolean replaceColor() {
|
||||
return replaceColor;
|
||||
return getConfig(ConfigFlags.REPLACE_COLOR);
|
||||
}
|
||||
|
||||
public void setReplaceColor(boolean replaceColor) {
|
||||
if (isDir())
|
||||
throw new SecurityException("Is Directory");
|
||||
this.replaceColor = replaceColor;
|
||||
updateDB();
|
||||
setConfig(ConfigFlags.REPLACE_COLOR, replaceColor);
|
||||
}
|
||||
|
||||
public boolean allowReplay() {
|
||||
return allowReplay;
|
||||
return getConfig(ConfigFlags.ALLOW_REPLAY);
|
||||
}
|
||||
|
||||
public void setAllowReplay(boolean allowReplay) {
|
||||
if (isDir())
|
||||
throw new SecurityException("Is Directory");
|
||||
this.allowReplay = allowReplay;
|
||||
setConfig(ConfigFlags.ALLOW_REPLAY, allowReplay);
|
||||
}
|
||||
|
||||
public boolean isPrepared() {
|
||||
return getConfig(ConfigFlags.IS_PREPARED);
|
||||
}
|
||||
|
||||
public void setPrepared(boolean prepared) {
|
||||
if (isDir())
|
||||
throw new SecurityException("Is Directory");
|
||||
setConfig(ConfigFlags.IS_PREPARED, prepared);
|
||||
}
|
||||
|
||||
public boolean getConfig(ConfigFlags flag) {
|
||||
return (config & (1 << flag.ordinal())) != 0;
|
||||
}
|
||||
|
||||
public void setConfig(ConfigFlags flag, boolean value) {
|
||||
if (value) {
|
||||
config |= (1 << flag.ordinal());
|
||||
} else {
|
||||
config &= ~(1 << flag.ordinal());
|
||||
}
|
||||
updateDB();
|
||||
}
|
||||
|
||||
@ -486,7 +503,7 @@ public class SchematicNode {
|
||||
|
||||
private void updateDB() {
|
||||
this.lastUpdate = Timestamp.from(Instant.now());
|
||||
update.update(nodeName, parentNode, nodeItem, nodeType, nodeRank, replaceColor, allowReplay, nodeId);
|
||||
update.update(nodeName, parentNode, nodeItem, nodeType, nodeRank, config, nodeId);
|
||||
TAB_CACHE.clear();
|
||||
}
|
||||
|
||||
@ -608,4 +625,10 @@ public class SchematicNode {
|
||||
TAB_CACHE.computeIfAbsent(user.getId(), integer -> new HashMap<>()).putIfAbsent(cacheKey, list);
|
||||
return list;
|
||||
}
|
||||
|
||||
public static enum ConfigFlags {
|
||||
REPLACE_COLOR,
|
||||
ALLOW_REPLAY,
|
||||
IS_PREPARED
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,13 +54,13 @@ public enum UserPerm {
|
||||
emptyPrefix = new Prefix("§7", "");
|
||||
p.put(PREFIX_NONE, emptyPrefix);
|
||||
p.put(PREFIX_YOUTUBER, new Prefix("§7", "YT"));
|
||||
p.put(PREFIX_GUIDE, new Prefix("§a", "Guide")); // 55FF55
|
||||
p.put(PREFIX_GUIDE, new Prefix("§x§e§7§6§2§e§d", "Guide")); // E762ED
|
||||
|
||||
p.put(PREFIX_SUPPORTER, new Prefix("§x§3§4§0§0§f§f", "Sup")); // 3400ff
|
||||
p.put(PREFIX_MODERATOR, new Prefix("§x§c§7§5§e§2§2", "Mod")); // C75E22
|
||||
p.put(PREFIX_BUILDER, new Prefix("§2", "Arch")); // 00AA00
|
||||
p.put(PREFIX_DEVELOPER, new Prefix("§3", "Dev")); // 00AAAA
|
||||
p.put(PREFIX_ADMIN, new Prefix("§x§F§2§2§8§2§4", "Admin")); // F22824
|
||||
p.put(PREFIX_SUPPORTER, new Prefix("§x§6§0§9§5§F§B", "Sup")); // 6095FB
|
||||
p.put(PREFIX_MODERATOR, new Prefix("§x§F§F§A§2§5§C", "Mod")); // FFA25C
|
||||
p.put(PREFIX_BUILDER, new Prefix("§x§6§0§F§F§6§A", "Arch")); // 60FF6A
|
||||
p.put(PREFIX_DEVELOPER, new Prefix("§x§0§B§B§C§B§3", "Dev")); // 0BBCB3
|
||||
p.put(PREFIX_ADMIN, new Prefix("§x§F§F§2§B§2§4", "Admin")); // FF2B24
|
||||
prefixes = Collections.unmodifiableMap(p);
|
||||
}
|
||||
|
||||
|
||||
@ -55,4 +55,7 @@ public class CraftbukkitWrapper10 implements CraftbukkitWrapper {
|
||||
public Stream<?> entityIterator() {
|
||||
return ((CraftWorld) Config.world).getHandle().entityList.stream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupGamerule() { }
|
||||
}
|
||||
|
||||
@ -55,4 +55,7 @@ public class CraftbukkitWrapper12 implements CraftbukkitWrapper {
|
||||
public Stream<?> entityIterator() {
|
||||
return ((CraftWorld) Config.world).getHandle().entityList.stream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupGamerule() { }
|
||||
}
|
||||
|
||||
@ -56,4 +56,7 @@ public class CraftbukkitWrapper14 implements CraftbukkitWrapper {
|
||||
public Stream<?> entityIterator() {
|
||||
return ((CraftWorld) Config.world).getHandle().entitiesById.values().stream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupGamerule() { }
|
||||
}
|
||||
|
||||
@ -145,6 +145,6 @@ public class WorldeditWrapper14 implements WorldeditWrapper {
|
||||
throw new SecurityException(e);
|
||||
}
|
||||
|
||||
new SchematicData(schem).saveFromBytes(outputStream.toByteArray(), NodeData.SchematicFormat.SPONGE_V2);
|
||||
SchematicData.saveFromBytes(schem, outputStream.toByteArray(), NodeData.SchematicFormat.SPONGE_V2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,4 +56,7 @@ public class CraftbukkitWrapper15 implements CraftbukkitWrapper {
|
||||
public Stream<?> entityIterator() {
|
||||
return ((CraftWorld) Config.world).getHandle().entitiesById.values().stream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupGamerule() { }
|
||||
}
|
||||
|
||||
@ -62,4 +62,7 @@ public class CraftbukkitWrapper18 implements CraftbukkitWrapper {
|
||||
public Stream<?> entityIterator() {
|
||||
return StreamSupport.stream(((Iterable<?>) getIterable.invoke(getWorldEntities.invoke(getWorld.invoke(Config.world)))).spliterator(), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupGamerule() { }
|
||||
}
|
||||
|
||||
@ -24,6 +24,7 @@ plugins {
|
||||
dependencies {
|
||||
compileOnly(project(":FightSystem:FightSystem_Core", "default"))
|
||||
compileOnly(project(":FightSystem:FightSystem_18", "default"))
|
||||
compileOnly(project(":SpigotCore", "default"))
|
||||
|
||||
compileOnly(libs.paperapi21) {
|
||||
attributes {
|
||||
@ -40,4 +41,5 @@ dependencies {
|
||||
}
|
||||
|
||||
compileOnly(libs.fastutil)
|
||||
compileOnly(libs.authlib)
|
||||
}
|
||||
|
||||
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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.fightsystem.utils;
|
||||
|
||||
import com.comphenix.tinyprotocol.TinyProtocol;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import de.steamwar.core.ProtocolWrapper;
|
||||
import de.steamwar.fightsystem.FightSystem;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.craftbukkit.CraftWorld;
|
||||
import org.bukkit.craftbukkit.block.CraftBlockState;
|
||||
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class BlockIdWrapper21 implements BlockIdWrapper {
|
||||
|
||||
@Override
|
||||
public Material idToMaterial(int blockState) {
|
||||
return CraftMagicNumbers.getMaterial(net.minecraft.world.level.block.Block.stateById(blockState)).getItemType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int blockToId(Block block) {
|
||||
return net.minecraft.world.level.block.Block.getId(((CraftBlockState) block.getState()).getHandle());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlock(World world, int x, int y, int z, int blockState) {
|
||||
BlockState blockData = net.minecraft.world.level.block.Block.stateById(blockState);
|
||||
ServerLevel level = ((CraftWorld) world).getHandle();
|
||||
BlockPos pos = new BlockPos(x, y, z);
|
||||
|
||||
level.removeBlockEntity(pos);
|
||||
level.setBlock(pos, blockData, blockState);
|
||||
level.getChunkSource().blockChanged(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void trackEntity(Player player, Entity entity) {
|
||||
if(entity instanceof Player)
|
||||
TinyProtocol.instance.sendPacket(player, ProtocolWrapper.impl.playerInfoPacketConstructor(ProtocolWrapper.PlayerInfoAction.REMOVE, new GameProfile(entity.getUniqueId(), entity.getName()), GameMode.CREATIVE));
|
||||
|
||||
player.showEntity(FightSystem.getPlugin(), entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void untrackEntity(Player player, Entity entity) {
|
||||
player.hideEntity(FightSystem.getPlugin(), entity);
|
||||
|
||||
if(entity instanceof Player)
|
||||
TinyProtocol.instance.sendPacket(player, ProtocolWrapper.impl.playerInfoPacketConstructor(ProtocolWrapper.PlayerInfoAction.ADD, new GameProfile(entity.getUniqueId(), entity.getName()), GameMode.CREATIVE));
|
||||
}
|
||||
}
|
||||
@ -19,12 +19,43 @@
|
||||
|
||||
package de.steamwar.fightsystem.utils;
|
||||
|
||||
import de.steamwar.fightsystem.Config;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
import net.minecraft.world.level.chunk.LevelChunkSection;
|
||||
import org.bukkit.GameRule;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.craftbukkit.CraftWorld;
|
||||
import org.bukkit.entity.Entity;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class CraftbukkitWrapper21 extends CraftbukkitWrapper18 {
|
||||
|
||||
@Override
|
||||
public float headRotation(Entity e) {
|
||||
return getEntity(e).getYHeadRot();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupGamerule() {
|
||||
Config.world.setGameRule(GameRule.LOCATOR_BAR, false);
|
||||
}
|
||||
|
||||
private LevelChunk getChunk(World world, int x, int z) {
|
||||
return ((CraftWorld) world).getHandle().getChunk(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetChunk(World world, World backup, int x, int z) {
|
||||
LevelChunk worldChunk = getChunk(world, x, z);
|
||||
LevelChunk backupChunk = getChunk(backup, x, z);
|
||||
LevelChunkSection[] sections = worldChunk.getSections();
|
||||
System.arraycopy(backupChunk.getSections(), 0, sections, 0, sections.length);
|
||||
Set<BlockPos> blocks = new HashSet<>(worldChunk.blockEntities.keySet());
|
||||
blocks.stream().filter(key -> !backupChunk.blockEntities.containsKey(key)).forEach(worldChunk::removeBlockEntity);
|
||||
worldChunk.heightmaps.clear();
|
||||
worldChunk.heightmaps.putAll(backupChunk.heightmaps);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.fightsystem.utils;
|
||||
|
||||
import io.papermc.paper.datacomponent.DataComponentTypes;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public class ReflectionWrapper21 implements ReflectionWrapper {
|
||||
@Override
|
||||
public Object explosionHider(Player player, Object packet, PacketHiderFunction packetHiderFunction) {
|
||||
return packet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasItems(ItemStack stack) {
|
||||
return stack.getDataTypes().stream().anyMatch(dataComponentType -> dataComponentType != DataComponentTypes.ENCHANTMENTS || dataComponentType != DataComponentTypes.DAMAGE);
|
||||
}
|
||||
}
|
||||
@ -52,4 +52,7 @@ public class CraftbukkitWrapper8 implements CraftbukkitWrapper {
|
||||
public Stream<?> entityIterator() {
|
||||
return ((CraftWorld) Config.world).getHandle().entityList.stream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupGamerule() { }
|
||||
}
|
||||
|
||||
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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.fightsystem.utils;
|
||||
|
||||
import de.steamwar.Reflection;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class ReflectionWrapper8 implements ReflectionWrapper {
|
||||
|
||||
private static final Class<?> packetPlayOutExplosion = Reflection.getClass("net.minecraft.network.protocol.game.ClientboundExplodePacket");
|
||||
private static final Reflection.Field<List> explosionBlocks = Reflection.getField(packetPlayOutExplosion, List.class, 0);
|
||||
private static final Function<Object, Location> explosionLocation = HullHider.posPacketToLocation(packetPlayOutExplosion, double.class, 1.0);
|
||||
|
||||
@Override
|
||||
public Object explosionHider(Player player, Object packet, PacketHiderFunction packetHiderFunction) {
|
||||
if(explosionBlocks.get(packet).isEmpty())
|
||||
return packetHiderFunction.hide(player, packet, explosionLocation.apply(packet));
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
|
||||
private static final Class<?> itemStack = Reflection.getClass("net.minecraft.world.item.ItemStack");
|
||||
private static final Reflection.Method asNMSCopy = Reflection.getTypedMethod(Reflection.getClass("org.bukkit.craftbukkit.inventory.CraftItemStack"), "asNMSCopy", itemStack, ItemStack.class);
|
||||
private static final Class<?> nbtTagCompound = Reflection.getClass("net.minecraft.nbt.CompoundTag");
|
||||
private static final Reflection.Method getTag = Reflection.getTypedMethod(itemStack, null, nbtTagCompound);
|
||||
private static final Reflection.Method getKeys = Reflection.getTypedMethod(nbtTagCompound, null, Set.class);
|
||||
@Override
|
||||
public boolean hasItems(ItemStack stack) {
|
||||
Set<String> keys = new HashSet<>((Set<String>) getKeys.invoke(getTag.invoke(asNMSCopy.invoke(null, stack))));
|
||||
keys.remove("Enchantments");
|
||||
keys.remove("Damage");
|
||||
return !keys.isEmpty();
|
||||
}
|
||||
}
|
||||
@ -140,6 +140,6 @@ public class WorldeditWrapper8 implements WorldeditWrapper {
|
||||
throw new SecurityException(e);
|
||||
}
|
||||
|
||||
new SchematicData(schem).saveFromBytes(outputStream.toByteArray(), NodeData.SchematicFormat.MCEDIT);
|
||||
SchematicData.saveFromBytes(schem, outputStream.toByteArray(), NodeData.SchematicFormat.MCEDIT);
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,4 +55,7 @@ public class CraftbukkitWrapper9 implements CraftbukkitWrapper {
|
||||
public Stream<?> entityIterator() {
|
||||
return ((CraftWorld) Config.world).getHandle().entityList.stream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupGamerule() { }
|
||||
}
|
||||
|
||||
@ -108,6 +108,7 @@ public class Config {
|
||||
public static final boolean PercentEntern;
|
||||
public static final boolean PercentBlocksWhitelist;
|
||||
public static final Set<Material> PercentBlocks;
|
||||
public static final int TechKoTime;
|
||||
|
||||
//default kits
|
||||
public static final String MemberDefault;
|
||||
@ -209,6 +210,7 @@ public class Config {
|
||||
PercentEntern = config.getBoolean("WinConditionParams.PercentEntern", true);
|
||||
PercentBlocksWhitelist = config.getBoolean("WinConditionParams.BlocksWhitelist", false);
|
||||
PercentBlocks = Collections.unmodifiableSet(config.getStringList("WinConditionParams.Blocks").stream().map(Material::valueOf).collect(Collectors.toSet()));
|
||||
TechKoTime = config.getInt("WinConditionParams.TechKoTime", 90);
|
||||
|
||||
EnterStages = Collections.unmodifiableList(config.getIntegerList("EnterStages"));
|
||||
AllowMissiles = config.getBoolean("Arena.AllowMissiles", !EnterStages.isEmpty());
|
||||
|
||||
@ -41,6 +41,7 @@ import de.steamwar.fightsystem.states.StateDependentListener;
|
||||
import de.steamwar.fightsystem.utils.*;
|
||||
import de.steamwar.fightsystem.winconditions.*;
|
||||
import de.steamwar.message.Message;
|
||||
import de.steamwar.sql.NodeData;
|
||||
import de.steamwar.sql.SchematicNode;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.Bukkit;
|
||||
@ -68,6 +69,11 @@ public class FightSystem extends JavaPlugin {
|
||||
Core.setInstance(this);
|
||||
TinyProtocol.init();
|
||||
}
|
||||
if (Config.SpectatePort != 0) {
|
||||
Core.setServerName("Spectate");
|
||||
} else if (Config.ReplayID != 0) {
|
||||
Core.setServerName("Replay");
|
||||
}
|
||||
|
||||
message = new Message("de.steamwar.fightsystem.FightSystem", FightSystem.class.getClassLoader());
|
||||
|
||||
@ -126,6 +132,7 @@ public class FightSystem extends JavaPlugin {
|
||||
new WinconditionPointsAirShip();
|
||||
new WinconditionTimeout();
|
||||
new WinconditionTimeTechKO();
|
||||
new WinconditionTimedDamageTechKO();
|
||||
new EventTeamOffWincondition();
|
||||
new WinconditionComparisonTimeout(Winconditions.HEART_RATIO_TIMEOUT, "HeartTimeout", "WIN_MORE_HEALTH", FightTeam::getHeartRatio);
|
||||
new WinconditionComparisonTimeout(Winconditions.PERCENT_TIMEOUT, "PercentTimeout", "WIN_LESS_DAMAGE", team -> -Wincondition.getPercentWincondition().getPercent(team));
|
||||
@ -173,17 +180,16 @@ public class FightSystem extends JavaPlugin {
|
||||
SchematicNode checkSchematicNode = SchematicNode.getSchematicNode(Config.CheckSchemID);
|
||||
Fight.getBlueTeam().setSchem(checkSchematicNode);
|
||||
|
||||
if (checkSchematicNode.getName().endsWith("-prepared")) {
|
||||
SchematicNode unpreparedSchematicNode = SchematicNode.getSchematicNode(checkSchematicNode.getOwner(), checkSchematicNode.getName().substring(0, checkSchematicNode.getName().length() - 9), checkSchematicNode.getParent());
|
||||
if (unpreparedSchematicNode != null) {
|
||||
Fight.getRedTeam().setSchem(unpreparedSchematicNode);
|
||||
}
|
||||
if (checkSchematicNode.isPrepared()) {
|
||||
Fight.getRedTeam().setSchem(checkSchematicNode, NodeData.getRevisions(checkSchematicNode) - 1);
|
||||
}
|
||||
|
||||
new TechareaCommand();
|
||||
}else if(Config.mode == ArenaMode.PREPARE) {
|
||||
Fight.getUnrotated().setSchem(SchematicNode.getSchematicNode(Config.PrepareSchemID));
|
||||
}
|
||||
|
||||
CraftbukkitWrapper.impl.setupGamerule();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -191,6 +191,7 @@ BAR_POINTS_OF={0}§8/§7{1} §8Points
|
||||
BAR_PERCENT={0}§8%
|
||||
BAR_CANNONS={0} §8Cannons
|
||||
BAR_WATER={0} §8Water
|
||||
BAR_SECONDS={0}§8s
|
||||
|
||||
|
||||
# Winconditions
|
||||
|
||||
@ -19,20 +19,14 @@
|
||||
|
||||
package de.steamwar.fightsystem.fight;
|
||||
|
||||
import com.comphenix.tinyprotocol.TinyProtocol;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import de.steamwar.core.Core;
|
||||
import de.steamwar.core.ProtocolWrapper;
|
||||
import de.steamwar.fightsystem.ArenaMode;
|
||||
import de.steamwar.fightsystem.Config;
|
||||
import de.steamwar.fightsystem.FightSystem;
|
||||
import de.steamwar.fightsystem.record.GlobalRecorder;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
|
||||
@ -31,6 +31,7 @@ import de.steamwar.fightsystem.states.StateDependent;
|
||||
import de.steamwar.fightsystem.utils.ColorConverter;
|
||||
import de.steamwar.fightsystem.utils.Region;
|
||||
import de.steamwar.fightsystem.utils.WorldeditWrapper;
|
||||
import de.steamwar.fightsystem.winconditions.Winconditions;
|
||||
import de.steamwar.sql.SchematicData;
|
||||
import de.steamwar.sql.SchematicNode;
|
||||
import de.steamwar.sql.SchematicType;
|
||||
@ -51,20 +52,28 @@ public class FightSchematic extends StateDependent {
|
||||
|
||||
private final FightTeam team;
|
||||
private final Region region;
|
||||
|
||||
private final boolean rotate;
|
||||
@Getter
|
||||
private boolean usedRotate;
|
||||
|
||||
@Getter
|
||||
private Clipboard clipboard = null;
|
||||
private int schematic = 0;
|
||||
|
||||
public FightSchematic(FightTeam team, boolean rotate) {
|
||||
public FightSchematic(FightTeam team, boolean usedRotate) {
|
||||
super(ArenaMode.All, FightState.PostSchemSetup);
|
||||
this.team = team;
|
||||
this.region = team.getSchemRegion();
|
||||
this.rotate = rotate;
|
||||
this.rotate = usedRotate;
|
||||
this.usedRotate = usedRotate;
|
||||
register();
|
||||
}
|
||||
|
||||
public void setChangeRotate(boolean rotate) {
|
||||
this.usedRotate = this.rotate ^ rotate;
|
||||
}
|
||||
|
||||
public boolean hasSchematic() {
|
||||
return clipboard != null;
|
||||
}
|
||||
@ -74,9 +83,13 @@ public class FightSchematic extends StateDependent {
|
||||
}
|
||||
|
||||
public void setSchematic(SchematicNode schem) {
|
||||
setSchematic(schem, -1);
|
||||
}
|
||||
|
||||
public void setSchematic(SchematicNode schem, int revision) {
|
||||
schematic = schem.getId();
|
||||
try {
|
||||
clipboard = new SchematicData(schem).load();
|
||||
clipboard = new SchematicData(schem, revision).load();
|
||||
|
||||
if(schem.replaceColor())
|
||||
replaceTeamColor(clipboard);
|
||||
@ -119,10 +132,15 @@ public class FightSchematic extends StateDependent {
|
||||
}
|
||||
|
||||
if(ArenaMode.AntiReplay.contains(Config.mode)) {
|
||||
boolean changeRotation = false;
|
||||
if (Config.ActiveWinconditions.contains(Winconditions.RANDOM_ROTATE)) {
|
||||
changeRotation = new Random().nextBoolean();
|
||||
usedRotate = rotate ^ changeRotation;
|
||||
}
|
||||
if(team.isBlue())
|
||||
GlobalRecorder.getInstance().blueSchem(schematic);
|
||||
GlobalRecorder.getInstance().blueSchem(schematic, changeRotation);
|
||||
else
|
||||
GlobalRecorder.getInstance().redSchem(schematic);
|
||||
GlobalRecorder.getInstance().redSchem(schematic, changeRotation);
|
||||
}
|
||||
|
||||
Bukkit.getScheduler().runTask(FightSystem.getPlugin(), this::paste);
|
||||
@ -140,7 +158,6 @@ public class FightSchematic extends StateDependent {
|
||||
FreezeWorld freezer = new FreezeWorld();
|
||||
|
||||
team.teleportToSpawn();
|
||||
|
||||
Vector dims = WorldeditWrapper.impl.getDimensions(clipboard);
|
||||
WorldeditWrapper.impl.pasteClipboard(
|
||||
clipboard,
|
||||
@ -149,8 +166,8 @@ public class FightSchematic extends StateDependent {
|
||||
Config.PasteAligned && Config.BlueToRedX != 0 ? region.getSizeX()/2.0 - dims.getBlockX() : -dims.getBlockX()/2.0,
|
||||
Config.WaterDepth != 0 ? Config.WaterDepth - WorldeditWrapper.impl.getWaterDepth(clipboard) : 0,
|
||||
Config.PasteAligned && Config.BlueToRedZ != 0 ? region.getSizeZ()/2.0 - dims.getBlockZ() : -dims.getBlockZ()/2.0
|
||||
).add(new Vector(rotate ? 1 : 0, 0, rotate ? 1 : 0)),
|
||||
new AffineTransform().rotateY(rotate ? 180 : 0)
|
||||
).add(new Vector(usedRotate ? 1 : 0, 0, usedRotate ? 1 : 0)),
|
||||
new AffineTransform().rotateY(usedRotate ? 180 : 0)
|
||||
);
|
||||
FightSystem.getHullHider().initialize(team);
|
||||
team.getPlayers().forEach(fightPlayer -> fightPlayer.ifAI(ai -> ai.schematic(clipboard)));
|
||||
|
||||
@ -412,7 +412,11 @@ public class FightTeam {
|
||||
}
|
||||
|
||||
public void setSchem(SchematicNode schematic){
|
||||
this.schematic.setSchematic(schematic);
|
||||
setSchem(schematic, -1);
|
||||
}
|
||||
|
||||
public void setSchem(SchematicNode schematic, int revision){
|
||||
this.schematic.setSchematic(schematic, revision);
|
||||
broadcast("SCHEMATIC_CHOSEN", Config.GameName, schematic.getName());
|
||||
}
|
||||
|
||||
@ -458,6 +462,10 @@ public class FightTeam {
|
||||
return schematic.getId();
|
||||
}
|
||||
|
||||
public void setSchematicChangeRotate(boolean rotate) {
|
||||
schematic.setChangeRotate(rotate);
|
||||
}
|
||||
|
||||
public Clipboard getClipboard() {
|
||||
return schematic.getClipboard();
|
||||
}
|
||||
|
||||
@ -26,6 +26,7 @@ import de.steamwar.fightsystem.commands.Commands;
|
||||
import de.steamwar.fightsystem.commands.GUI;
|
||||
import de.steamwar.fightsystem.listener.PersonalKitCreator;
|
||||
import de.steamwar.fightsystem.utils.FlatteningWrapper;
|
||||
import de.steamwar.fightsystem.utils.ReflectionWrapper;
|
||||
import de.steamwar.inventory.SWInventory;
|
||||
import de.steamwar.inventory.SWItem;
|
||||
import de.steamwar.sql.PersonalKit;
|
||||
@ -214,17 +215,8 @@ public class Kit {
|
||||
assert normal != null;
|
||||
return !normal.isEnchantmentInKit(stack) && !stack.getEnchantments().isEmpty();
|
||||
}
|
||||
|
||||
private static final Class<?> itemStack = Reflection.getClass("net.minecraft.world.item.ItemStack");
|
||||
private static final Reflection.Method asNMSCopy = Reflection.getTypedMethod(Reflection.getClass("org.bukkit.craftbukkit.inventory.CraftItemStack"), "asNMSCopy", itemStack, ItemStack.class);
|
||||
private static final Class<?> nbtTagCompound = Reflection.getClass("net.minecraft.nbt.CompoundTag");
|
||||
private static final Reflection.Method getTag = Reflection.getTypedMethod(itemStack, null, nbtTagCompound);
|
||||
private static final Reflection.Method getKeys = Reflection.getTypedMethod(nbtTagCompound, null, Set.class);
|
||||
public static boolean hasItems(ItemStack stack) {
|
||||
Set<String> keys = new HashSet<>((Set<String>) getKeys.invoke(getTag.invoke(asNMSCopy.invoke(null, stack))));
|
||||
keys.remove("Enchantments");
|
||||
keys.remove("Damage");
|
||||
return !keys.isEmpty();
|
||||
return ReflectionWrapper.impl.hasItems(stack);
|
||||
}
|
||||
|
||||
private boolean isEnchantmentInKit(ItemStack stack){
|
||||
|
||||
@ -83,13 +83,8 @@ public class PrepareSchem implements Listener {
|
||||
return;
|
||||
}
|
||||
|
||||
if(schemExists(schem))
|
||||
return;
|
||||
|
||||
SchematicNode old = schem;
|
||||
schem = SchematicNode.createSchematicNode(schem.getOwner(), preparedName(schem), schem.getParent(), Config.SchematicType.checkType().toDB(), schem.getItem());
|
||||
schem.setReplaceColor(old.replaceColor());
|
||||
schem.setAllowReplay(old.allowReplay());
|
||||
schem.setSchemtype(Config.SchematicType.checkType());
|
||||
schem.setPrepared(true);
|
||||
|
||||
try{
|
||||
WorldeditWrapper.impl.saveSchem(schem, region, minY);
|
||||
@ -119,20 +114,5 @@ public class PrepareSchem implements Listener {
|
||||
FightState.setFightState(FightState.PRE_SCHEM_SETUP);
|
||||
FightState.setFightState(FightState.POST_SCHEM_SETUP);
|
||||
}
|
||||
|
||||
schemExists(SchematicNode.getSchematicNode(Config.PrepareSchemID));
|
||||
}
|
||||
|
||||
private boolean schemExists(SchematicNode schem) {
|
||||
if(SchematicNode.getSchematicNode(schem.getOwner(), preparedName(schem), schem.getParent()) != null) {
|
||||
FightSystem.getMessage().broadcast("PREPARE_SCHEM_EXISTS");
|
||||
Bukkit.shutdown();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private String preparedName(SchematicNode schem) {
|
||||
return schem.getName() + "-prepared";
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,7 +20,6 @@
|
||||
package de.steamwar.fightsystem.record;
|
||||
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import de.steamwar.core.Core;
|
||||
import de.steamwar.core.TrickyTrialsWrapper;
|
||||
import de.steamwar.core.WorldEditWrapper;
|
||||
import de.steamwar.entity.REntity;
|
||||
@ -144,6 +143,8 @@ public class PacketProcessor implements Listener {
|
||||
packetDecoder[0xb2] = this::teams;
|
||||
packetDecoder[0xb3] = () -> pasteEmbeddedSchem(Fight.getBlueTeam());
|
||||
packetDecoder[0xb4] = () -> pasteEmbeddedSchem(Fight.getRedTeam());
|
||||
packetDecoder[0xb5] = () -> rotateSchem(Fight.getBlueTeam());
|
||||
packetDecoder[0xb6] = () -> rotateSchem(Fight.getRedTeam());
|
||||
packetDecoder[0xc0] = this::scoreboardTitle;
|
||||
packetDecoder[0xc1] = this::scoreboardData;
|
||||
packetDecoder[0xc2] = this::bossBar;
|
||||
@ -529,6 +530,14 @@ public class PacketProcessor implements Listener {
|
||||
execSync(() -> team.pasteSchem(schemId, clipboard));
|
||||
}
|
||||
|
||||
private void rotateSchem(FightTeam team) throws IOException {
|
||||
boolean changeRotate = source.readBoolean();
|
||||
|
||||
execSync(() -> {
|
||||
team.setSchematicChangeRotate(changeRotate);
|
||||
});
|
||||
}
|
||||
|
||||
private void teams() throws IOException {
|
||||
int blueId = source.readInt();
|
||||
int redId = source.readInt();
|
||||
|
||||
@ -61,9 +61,9 @@ public interface Recorder {
|
||||
default void enableTeam(FightTeam team){
|
||||
if(FightState.Schem.contains(FightState.getFightState())){
|
||||
if(team.isBlue())
|
||||
blueSchem(team.getSchematic());
|
||||
blueSchem(team.getSchematic(), false);
|
||||
else
|
||||
redSchem(team.getSchematic());
|
||||
redSchem(team.getSchematic(), false);
|
||||
}
|
||||
|
||||
if(FightState.AntiSpectate.contains(FightState.getFightState())){
|
||||
@ -123,6 +123,8 @@ public interface Recorder {
|
||||
* TeamIDPacket (0xb2) + int blueTeamId, redTeamId
|
||||
* BlueEmbeddedSchemPacket (0xb3) + int blueSchemId + gzipt NBT blob
|
||||
* RedEmbeddedSchemPacket (0xb4) + int redSchemId + gzipt NBT blob
|
||||
* BlueSchemRotatePacket (0xb5) + boolean changeRotate
|
||||
* RedSchemRotatePacket (0xb6) + boolean changeRotate
|
||||
*
|
||||
* DEPRECATED ScoreboardTitlePacket (0xc0) + String scoreboardTitle
|
||||
* DEPRECATED ScoreboardDataPacket (0xc1) + String key + int value
|
||||
@ -259,14 +261,20 @@ public interface Recorder {
|
||||
write(0xb2, blueTeamId, redTeamId);
|
||||
}
|
||||
|
||||
default void blueSchem(int schemId) {
|
||||
default void blueSchem(int schemId, boolean changeRotate) {
|
||||
rotate(0xb5, changeRotate);
|
||||
schem(0xb3, 0xb0, schemId);
|
||||
}
|
||||
|
||||
default void redSchem(int schemId) {
|
||||
default void redSchem(int schemId, boolean changeRotate) {
|
||||
rotate(0xb6, changeRotate);
|
||||
schem(0xb4, 0xb1, schemId);
|
||||
}
|
||||
|
||||
default void rotate(int packetId, boolean changeRotate) {
|
||||
write(packetId, changeRotate);
|
||||
}
|
||||
|
||||
default void schem(int embedId, int noEmbedId, int schemId){
|
||||
if(schemId == 0) {
|
||||
write(noEmbedId, schemId);
|
||||
@ -275,7 +283,7 @@ public interface Recorder {
|
||||
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
try{
|
||||
copy(NodeData.get(SchematicNode.getSchematicNode(schemId)).schemData(), buffer);
|
||||
copy(NodeData.getLatest(SchematicNode.getSchematicNode(schemId)).schemData(), buffer);
|
||||
}catch (EOFException e) {
|
||||
Bukkit.getLogger().log(Level.INFO, "EOFException ignored");
|
||||
} catch (IOException e) {
|
||||
@ -339,6 +347,8 @@ public interface Recorder {
|
||||
stream.writeShort((Short)o);
|
||||
else if(o instanceof Integer)
|
||||
stream.writeInt((Integer)o);
|
||||
else if(o instanceof Long)
|
||||
stream.writeLong((Long)o);
|
||||
else if(o instanceof Float)
|
||||
stream.writeFloat((Float)o);
|
||||
else if(o instanceof Double)
|
||||
|
||||
@ -33,4 +33,6 @@ public interface CraftbukkitWrapper {
|
||||
float headRotation(Entity e);
|
||||
|
||||
Stream<?> entityIterator();
|
||||
|
||||
void setupGamerule();
|
||||
}
|
||||
|
||||
@ -62,6 +62,7 @@ public class HullHider implements Listener {
|
||||
private final Hull[] hulls;
|
||||
private final Map<Class<?>, BiFunction<Player, Object, Object>> packetHiders = new HashMap<>();
|
||||
|
||||
private static final Class<?> packetPlayOutExplosion = Reflection.getClass("net.minecraft.network.protocol.game.ClientboundExplodePacket");
|
||||
public HullHider() {
|
||||
if(!TechHiderWrapper.ENABLED) {
|
||||
hulls = new Hull[0];
|
||||
@ -208,14 +209,8 @@ public class HullHider implements Listener {
|
||||
return packetHider(player, packet, new Location(Config.world, TechHider.blockPositionX.get(baseBlock), blockPositionY.get(baseBlock), TechHider.blockPositionZ.get(baseBlock)));
|
||||
}
|
||||
|
||||
private static final Class<?> packetPlayOutExplosion = Reflection.getClass("net.minecraft.network.protocol.game.ClientboundExplodePacket");
|
||||
private static final Reflection.Field<List> explosionBlocks = Reflection.getField(packetPlayOutExplosion, List.class, 0);
|
||||
private static final Function<Object, Location> explosionLocation = posPacketToLocation(packetPlayOutExplosion, double.class, 1.0);
|
||||
private Object explosionHider(Player player, Object packet) {
|
||||
if(explosionBlocks.get(packet).isEmpty())
|
||||
return packetHider(player, packet, explosionLocation.apply(packet));
|
||||
|
||||
return packet;
|
||||
return ReflectionWrapper.impl.explosionHider(player, packet, this::packetHider);
|
||||
}
|
||||
|
||||
private void posHiderGenerator(String typeName, Class<? extends Number> posType, double factor) {
|
||||
@ -224,7 +219,7 @@ public class HullHider implements Listener {
|
||||
packetHiders.put(type, (player, packet) -> packetHider(player, packet, location.apply(packet)));
|
||||
}
|
||||
|
||||
private static Function<Object, Location> posPacketToLocation(Class<?> type, Class<? extends Number> posType, double factor) {
|
||||
public static Function<Object, Location> posPacketToLocation(Class<?> type, Class<? extends Number> posType, double factor) {
|
||||
Reflection.Field<? extends Number> x = Reflection.getField(type, posType, 0);
|
||||
Reflection.Field<? extends Number> y = Reflection.getField(type, posType, 1);
|
||||
Reflection.Field<? extends Number> z = Reflection.getField(type, posType, 2);
|
||||
|
||||
@ -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/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.fightsystem.utils;
|
||||
|
||||
import de.steamwar.core.VersionDependent;
|
||||
import de.steamwar.fightsystem.FightSystem;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public interface ReflectionWrapper {
|
||||
ReflectionWrapper impl = VersionDependent.getVersionImpl(FightSystem.getPlugin());
|
||||
|
||||
Object explosionHider(Player player, Object packet, PacketHiderFunction packetHiderFunction);
|
||||
boolean hasItems(ItemStack stack);
|
||||
|
||||
public interface PacketHiderFunction {
|
||||
Object hide(Player player, Object packet, Location location);
|
||||
}
|
||||
}
|
||||
@ -20,6 +20,7 @@
|
||||
package de.steamwar.fightsystem.winconditions;
|
||||
|
||||
import de.steamwar.core.TrickyTrialsWrapper;
|
||||
import de.steamwar.fightsystem.Config;
|
||||
import de.steamwar.fightsystem.countdown.Countdown;
|
||||
import de.steamwar.fightsystem.fight.Fight;
|
||||
import de.steamwar.fightsystem.fight.FightTeam;
|
||||
@ -30,7 +31,6 @@ import de.steamwar.fightsystem.states.StateDependentTask;
|
||||
import de.steamwar.fightsystem.utils.Message;
|
||||
import de.steamwar.fightsystem.utils.SWSound;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.EntityExplodeEvent;
|
||||
@ -41,8 +41,7 @@ import java.util.Map;
|
||||
|
||||
public class WinconditionTimeTechKO extends Wincondition implements Listener {
|
||||
|
||||
private static final int TECH_KO_TIME_IN_S = 90;
|
||||
private static final int TECH_KO_HALF_TIME = TECH_KO_TIME_IN_S/2;
|
||||
private static final int TECH_KO_HALF_TIME = Config.TechKoTime/2;
|
||||
|
||||
private final Map<Integer, FightTeam> spawnLocations = new HashMap<>();
|
||||
private final Map<FightTeam, TechKOCountdown> countdowns = new HashMap<>();
|
||||
|
||||
@ -0,0 +1,115 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2020 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.fightsystem.winconditions;
|
||||
|
||||
import de.steamwar.core.TrickyTrialsWrapper;
|
||||
import de.steamwar.fightsystem.Config;
|
||||
import de.steamwar.fightsystem.countdown.Countdown;
|
||||
import de.steamwar.fightsystem.fight.Fight;
|
||||
import de.steamwar.fightsystem.fight.FightTeam;
|
||||
import de.steamwar.fightsystem.states.FightState;
|
||||
import de.steamwar.fightsystem.states.StateDependent;
|
||||
import de.steamwar.fightsystem.states.StateDependentListener;
|
||||
import de.steamwar.fightsystem.utils.Message;
|
||||
import de.steamwar.fightsystem.utils.SWSound;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.EntityExplodeEvent;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class WinconditionTimedDamageTechKO extends Wincondition implements PrintableWincondition, Listener {
|
||||
|
||||
private final Map<FightTeam, TechKOCountdown> countdowns = new HashMap<>();
|
||||
|
||||
public WinconditionTimedDamageTechKO() {
|
||||
super("TechKO");
|
||||
|
||||
new StateDependentListener(Winconditions.TIMED_DAMAGE_TECH_KO, FightState.Running, this);
|
||||
new StateDependent(Winconditions.TIMED_DAMAGE_TECH_KO, FightState.Running) {
|
||||
@Override
|
||||
public void enable() {
|
||||
Fight.teams().forEach(team -> {
|
||||
TechKOCountdown countdown = new TechKOCountdown(team, Config.TechKoTime);
|
||||
countdowns.put(team, countdown);
|
||||
countdown.enable();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disable() {
|
||||
countdowns.values().forEach(Countdown::disable);
|
||||
countdowns.clear();
|
||||
}
|
||||
}.register();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message getDisplay(FightTeam team) {
|
||||
return new Message("BAR_SECONDS", team.getPrefix() + countdowns.get(team).getTimeLeft());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onExplode(EntityExplodeEvent e) {
|
||||
if (e.getEntityType() != TrickyTrialsWrapper.impl.getTntEntityType())
|
||||
return;
|
||||
|
||||
Location location = e.getLocation();
|
||||
TechKOCountdown countdown = null;
|
||||
FightTeam fightTeam = null;
|
||||
for (FightTeam team : Fight.teams()) {
|
||||
FightTeam current = Fight.getOpposite(team);
|
||||
if (current.getExtendRegion().inRegion(location)) {
|
||||
fightTeam = current;
|
||||
countdown = countdowns.get(team);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (fightTeam == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
FightTeam finalFightTeam = fightTeam;
|
||||
TechKOCountdown finalCountdown = countdown;
|
||||
e.blockList().forEach(block -> {
|
||||
if (block.isEmpty()) return;
|
||||
if (finalFightTeam.getExtendRegion().inRegion(block)) {
|
||||
finalCountdown.disable();
|
||||
finalCountdown.enable();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private class TechKOCountdown extends Countdown {
|
||||
private final FightTeam team;
|
||||
|
||||
public TechKOCountdown(FightTeam team, int countdownTime) {
|
||||
super(countdownTime, new Message("TECHKO_COUNTDOWN", team.getColoredName()), SWSound.BLOCK_NOTE_PLING, false);
|
||||
this.team = team;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void countdownFinished() {
|
||||
win(Fight.getOpposite(team), "WIN_TECHKO", team.getColoredName());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -31,6 +31,7 @@ public enum Winconditions {
|
||||
POINTS,
|
||||
POINTS_AIRSHIP,
|
||||
|
||||
TIMED_DAMAGE_TECH_KO,
|
||||
TIME_TECH_KO,
|
||||
WATER_TECH_KO,
|
||||
PUMPKIN_TECH_KO,
|
||||
@ -41,4 +42,5 @@ public enum Winconditions {
|
||||
PERSISTENT_DAMAGE,
|
||||
TNT_DISTRIBUTION,
|
||||
NO_GRAVITY,
|
||||
RANDOM_ROTATE,
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@ softdepend:
|
||||
- SpigotCore
|
||||
depend:
|
||||
- WorldEdit
|
||||
api-version: "1.13"
|
||||
api-version: "1.21.6"
|
||||
|
||||
commands:
|
||||
ak:
|
||||
|
||||
@ -49,3 +49,24 @@ tasks.register<FightServer>("WarGear20") {
|
||||
worldName = "arenas/Pentraki"
|
||||
config = "WarGear20.yml"
|
||||
}
|
||||
|
||||
tasks.register<FightServer>("WarGear21") {
|
||||
group = "run"
|
||||
description = "Run a WarGear 1.21 Fight Server"
|
||||
dependsOn(":SpigotCore:shadowJar")
|
||||
dependsOn(":FightSystem:shadowJar")
|
||||
template = "WarGear21"
|
||||
worldName = "arenas/Pentraki"
|
||||
config = "WarGear20.yml"
|
||||
jar = "/jars/paper-1.21.6.jar"
|
||||
}
|
||||
|
||||
tasks.register<FightServer>("SpaceCraftDev20") {
|
||||
group = "run"
|
||||
description = "Run a SpaceCraftDev 1.20 Fight Server"
|
||||
dependsOn(":SpigotCore:shadowJar")
|
||||
dependsOn(":FightSystem:shadowJar")
|
||||
template = "SpaceCraft20"
|
||||
worldName = "arenas/AS_Horizon"
|
||||
config = "SpaceCraftDev20.yml"
|
||||
}
|
||||
@ -53,6 +53,7 @@ public class BauSystem extends JavaPlugin implements Listener {
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
Core.setServerName("Dev");
|
||||
plugin = this;
|
||||
|
||||
Mapper.init();
|
||||
|
||||
@ -53,7 +53,7 @@ public class ClipboardListener implements Listener {
|
||||
}
|
||||
|
||||
try {
|
||||
new SchematicData(schematic).saveFromPlayer(e.getPlayer());
|
||||
SchematicData.saveFromPlayer(e.getPlayer(), schematic);
|
||||
} catch (Exception ex) {
|
||||
if (newSchem) {
|
||||
schematic.delete();
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
|
||||
package de.steamwar.lobby;
|
||||
|
||||
import de.steamwar.core.Core;
|
||||
import de.steamwar.entity.REntityServer;
|
||||
import de.steamwar.lobby.command.FlyCommand;
|
||||
import de.steamwar.lobby.command.HologramCommand;
|
||||
@ -52,6 +53,7 @@ public class LobbySystem extends JavaPlugin {
|
||||
message = new Message("de.steamwar.lobby.LobbySystem", getClassLoader());
|
||||
entityServer = new REntityServer();
|
||||
debugEntityServer = new REntityServer();
|
||||
Core.setServerName("Lobby");
|
||||
|
||||
CustomMap.init();
|
||||
|
||||
|
||||
@ -158,7 +158,7 @@ public class Config {
|
||||
EventKampf = null;
|
||||
TeamBlueName = "Blau";
|
||||
TeamRedName = "Rot";
|
||||
TeamBlueColor = "§3";
|
||||
TeamBlueColor = "§9";
|
||||
TeamRedColor = "§c";
|
||||
EventTeamBlueID = 0;
|
||||
EventTeamRedID = 0;
|
||||
|
||||
@ -76,7 +76,13 @@ public class AutoCheckerItems15 implements AutoCheckerItems {
|
||||
Material.DIAMOND_HORSE_ARMOR,
|
||||
Material.IRON_HORSE_ARMOR,
|
||||
Material.GOLDEN_HORSE_ARMOR,
|
||||
Material.HONEY_BOTTLE);
|
||||
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() {
|
||||
|
||||
@ -43,12 +43,19 @@ public class AutoCheckerItems19 extends AutoCheckerItems15 {
|
||||
Material.LILY_OF_THE_VALLEY,
|
||||
Material.WITHER_ROSE,
|
||||
Material.SUNFLOWER,
|
||||
Material.LILAC,
|
||||
Material.ROSE_BUSH,
|
||||
Material.PEONY,
|
||||
Material.TALL_GRASS,
|
||||
Material.LARGE_FERN,
|
||||
Material.TORCHFLOWER,
|
||||
// 16-stackable Items
|
||||
Material.HONEY_BOTTLE,
|
||||
// Non-stackable items
|
||||
Material.DIAMOND_HORSE_ARMOR,
|
||||
Material.IRON_HORSE_ARMOR,
|
||||
Material.GOLDEN_HORSE_ARMOR,
|
||||
Material.LEATHER_HORSE_ARMOR,
|
||||
// Disks
|
||||
Material.MUSIC_DISC_11,
|
||||
Material.MUSIC_DISC_13,
|
||||
|
||||
@ -26,6 +26,7 @@ CLICK_DRAG_ITEM=§7Click or drag item here
|
||||
CURRENT=§7Current: {0}
|
||||
CONFIRM=§aConfirm
|
||||
CANCEL=§cCancel
|
||||
BLANK={0}
|
||||
|
||||
UTIL_NAME_REQUIRED=§cFolder name required
|
||||
UTIL_NAME_TOO_LONG=§cSchematic name too long
|
||||
@ -49,6 +50,7 @@ UTIL_LIST_NEXT=Page ({0}/{1}) »»
|
||||
UTIL_LIST_NEXT_HOVER=§eNext page
|
||||
UTIL_INFO_SCHEM=§7Schematic: §e{0}
|
||||
UTIL_INFO_NAME=§7Name: §e{0}
|
||||
UTIL_INFO_REVISIONS=§7Revisions: §e{0}
|
||||
UTIL_INFO_OWNER=§7Owner: §e{0}
|
||||
UTIL_INFO_PARENT=§7Directory: §e{0}
|
||||
UTIL_INFO_UPDATED=§7Last update: §e{0}
|
||||
@ -70,6 +72,7 @@ UTIL_INFO_ACTION_TYPE_HOVER=§eChange schematic type
|
||||
UTIL_INFO_ACTION_ADD_HOVER=§eAdd member
|
||||
UTIL_INFO_ACTION_REMOVE_HOVER=§eRemove {0}
|
||||
UTIL_INFO_ACTION_MOVE_HOVER=§eMove schematic
|
||||
UTIL_INFO_ACTION_REVISIONS_HOVER=§eList revisions
|
||||
UTIL_INFO_ACTION_RENAME_HOVER=§eRename schematic
|
||||
UTIL_INFO_ACTION_DELETE=(Delete)
|
||||
UTIL_INFO_ACTION_DELETE_HOVER=§eDelete schematic
|
||||
@ -79,6 +82,7 @@ UTIL_LOAD_DIR=§cYou cannot load folders
|
||||
UTIL_LOAD_DONE=§7Schematic §e{0} loaded
|
||||
UTIL_LOAD_NO_DATA=§cNo data could be found in the Schematic
|
||||
UTIL_LOAD_ERROR=§cThe schematic could not be loaded
|
||||
UTIL_LOAD_ILLEGAL_REVISION=§cThe schematic doesn't have {0} revisions
|
||||
UTIL_DOWNLOAD_PUNISHED=§cYou are not allowed to download schematics: §f§l{0}
|
||||
UTIL_DOWNLOAD_NOT_OWN=§cYou may download only your own schematics
|
||||
UTIL_DOWNLOAD_LINK=Your download link:
|
||||
@ -224,6 +228,9 @@ GUI_DELETE_MEMBER_TITLE=Remove {0}
|
||||
GUI_DELETE_MEMBER_DONE=Access to Schematic §e{0} §7removed
|
||||
GUI_DELETE_MEMBERS_TITLE=Remove members
|
||||
GUI_CHANGE_ITEM=Change item
|
||||
GUI_LOAD_LATEST=§eLeft §7Click → §eLoad latest
|
||||
GUI_LOAD_REVISION=§eRight §7Click → §eList Revisions
|
||||
GUI_LOAD_REVISION_TITLE=Select Revision
|
||||
|
||||
AUTO_CHECK_RESULT_NOT_LOAD=The schematic could not be loaded
|
||||
AUTO_CHECK_RESULT_TOO_WIDE=The schematic is too wide ({0} > {1})
|
||||
@ -264,3 +271,7 @@ AUTO_CHECKER_RESULT_TOO_MANY_DISPENSER_ITEMS=§7Dispenser: §c[{0}, {1}, {2}]§7
|
||||
AUTO_CHECKER_RESULT_FORBIDDEN_ITEM_NBT=§7Forbidden Item NBT: [{0}, {1}, {2}] -> §c{3}
|
||||
AUTO_CHECKER_RESULT_TELEPORT_HERE=§7Teleport to block
|
||||
AUTO_CHECKER_RESULT_AFTER_DEADLINE=§cThe deadline has expired: {0}
|
||||
|
||||
REVISIONS_TITLE=§7Revisions:
|
||||
REVISIONS_REVISION_NUMBER=§7#{0}: §e{1}
|
||||
REVISIONS_EMPTY=§cNo Revisions
|
||||
@ -90,6 +90,9 @@ UTIL_SUBMIT_DIRECT=§eDirekt einsenden
|
||||
UTIL_SUBMIT_DIRECT_DONE=§aDie Schematic wird zeitnah überprüft
|
||||
UTIL_SUBMIT_EXTEND=§eSchematic ausfahren
|
||||
UTIL_SUBMIT_EXTEND_DONE=§aDer Vorbereitungsserver wird gestartet
|
||||
UTIL_INFO_ACTION_REVISIONS_HOVER=§eVersionen anzeigen
|
||||
UTIL_LOAD_ILLEGAL_REVISION=§cDie schematic hat nicht {0} Versionen
|
||||
UTIL_INFO_REVISIONS=§7Versionen: §e{0}
|
||||
|
||||
COMMAND_INVALID_NODE=§cDie Schematic konnte nicht gefunden werden
|
||||
COMMAND_NOT_OWN=§cDas darfst du nur bei deinen eigenen Schematics machen
|
||||
@ -204,6 +207,9 @@ GUI_DELETE_MEMBER_TITLE={0} entfernen
|
||||
GUI_DELETE_MEMBER_DONE=Zugriff zu Schematic §e{0} §7entfernt
|
||||
GUI_DELETE_MEMBERS_TITLE=Mitglieder entfernen
|
||||
GUI_CHANGE_ITEM=Item ändern
|
||||
GUI_LOAD_LATEST=§eLinks §7Klick → §eLetzte Laden
|
||||
GUI_LOAD_REVISION=§eRechts §7Klick → §eVersionen anzeigen
|
||||
GUI_LOAD_REVISION_TITLE=Version Laden
|
||||
|
||||
AUTO_CHECK_RESULT_NOT_LOAD=Die Schematic konnte nicht geladen werden
|
||||
AUTO_CHECK_RESULT_TOO_WIDE=Die Schematic ist zu breit ({0} > {1})
|
||||
@ -243,3 +249,6 @@ AUTO_CHECKER_RESULT_TOO_MANY_DISPENSER_ITEMS=§7Dispenser: §c[{0}, {1}, {2}]§7
|
||||
AUTO_CHECKER_RESULT_FORBIDDEN_ITEM_NBT=§7Verbotene NBT-Daten: [{0}, {1}, {2}] -> §c{3}
|
||||
AUTO_CHECKER_RESULT_TELEPORT_HERE=§7Zum block teleportieren
|
||||
AUTO_CHECKER_RESULT_AFTER_DEADLINE=§cDer einsendeschluss ist bereits vorbei: {0}
|
||||
|
||||
REVISIONS_TITLE=§7Versionen:
|
||||
REVISIONS_EMPTY=§cKeine Versionen
|
||||
@ -43,7 +43,7 @@ public class DownloadCommand extends SWCommand {
|
||||
}
|
||||
|
||||
try {
|
||||
new SchematicData(copyNode).saveFromPlayer(player);
|
||||
SchematicData.saveFromPlayer(player, copyNode);
|
||||
} catch (IOException e) {
|
||||
SchematicSystem.MESSAGE.send("DOWNLOAD_ERROR", player);
|
||||
if (newSchem) {
|
||||
|
||||
@ -95,9 +95,28 @@ public class GUI {
|
||||
SteamwarUser user = getUser(player);
|
||||
SWInventory inv = new SWInventory(player, 9 * 2, node.generateBreadcrumbs());
|
||||
if(!node.isDir()) {
|
||||
inv.setItem(0, SWItem.getMaterial("WOOD_AXE"), SchematicSystem.MESSAGE.parse("GUI_INFO_LOAD", player), click -> {
|
||||
inv.setItem(0, SWItem.getMaterial("WOOD_AXE"), SchematicSystem.MESSAGE.parse("GUI_INFO_LOAD", player), Arrays.asList(
|
||||
SchematicSystem.MESSAGE.parse("GUI_LOAD_LATEST", player),
|
||||
SchematicSystem.MESSAGE.parse("GUI_LOAD_REVISION", player)
|
||||
), false, click -> {
|
||||
if (click.isLeftClick()) {
|
||||
player.closeInventory();
|
||||
SchematicCommandUtils.loadSchem(player, node);
|
||||
SchematicCommandUtils.loadSchem(player, node, -1);
|
||||
} else if (click.isRightClick()) {
|
||||
List<SWListInv.SWListEntry<Integer>> entries = new ArrayList<>();
|
||||
List<NodeData> datas = NodeData.get(node);
|
||||
for (int i = 0; i < datas.size(); i++) {
|
||||
entries.add(new SWListInv.SWListEntry<>(new SWItem(SWItem.getMaterial(node.getItem()), "§e" + SchematicSystem.MESSAGE.parse("BLANK", player, datas.get(i).getCreatedAt())), i));
|
||||
}
|
||||
|
||||
SWListInv<Integer> listInv = new SWListInv<>(player, SchematicSystem.MESSAGE.parse("GUI_LOAD_REVISION_TITLE", player, node.generateBreadcrumbs()), entries, (clickType, revision) -> {
|
||||
if(revision == null) return;
|
||||
player.closeInventory();
|
||||
SchematicCommandUtils.loadSchem(player, node, revision);
|
||||
});
|
||||
listInv.setCallback(-999, click2 -> player.closeInventory());
|
||||
listInv.open();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -223,6 +223,11 @@ public class SchematicCommandUtils {
|
||||
} else {
|
||||
SchematicSystem.MESSAGE.sendPrefixless("UTIL_INFO_PARENT", player, node.getParent() == null ? "/" : node.getParentNode().generateBreadcrumbs());
|
||||
}
|
||||
player.spigot().sendMessage(
|
||||
new ComponentBuilder(SchematicSystem.MESSAGE.parseToComponent("UTIL_INFO_REVISIONS", false, player, NodeData.getRevisions(node)))
|
||||
.event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TextComponent[] {SchematicSystem.MESSAGE.parseToComponent("UTIL_INFO_ACTION_REVISIONS_HOVER", false, player)}))
|
||||
.event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/schem revisions " + node.generateBreadcrumbs()))
|
||||
.create());
|
||||
SchematicSystem.MESSAGE.sendPrefixless("UTIL_INFO_UPDATED", player, node.getLastUpdate());
|
||||
if (!node.isDir()) {
|
||||
if(node.getOwner() == user.getId()) {
|
||||
@ -357,7 +362,7 @@ public class SchematicCommandUtils {
|
||||
PUBLIC_TOGGLED.remove(player);
|
||||
}
|
||||
|
||||
public static void loadSchem(Player player, SchematicNode node) {
|
||||
public static void loadSchem(Player player, SchematicNode node, int revision) {
|
||||
SteamwarUser user = getUser(player);
|
||||
if(BauServerInfo.isBauServer() && BauServerInfo.getOwnerId() != user.getId() &&
|
||||
(Punishment.isPunished(user, Punishment.PunishmentType.NoSchemSharing, punishment ->
|
||||
@ -372,11 +377,13 @@ public class SchematicCommandUtils {
|
||||
}
|
||||
|
||||
try {
|
||||
new SchematicData(node).loadToPlayer(player);
|
||||
new SchematicData(node, revision).loadToPlayer(player);
|
||||
SchematicSystem.MESSAGE.send("UTIL_LOAD_DONE", player, node.getName());
|
||||
Bukkit.getLogger().log(Level.INFO, "{0} has loaded Schematic {1} {2}", new Object[]{player.getName(), node.getId(), node.getName()});
|
||||
} catch (NoClipboardException e) {
|
||||
SchematicSystem.MESSAGE.send("UTIL_LOAD_NO_DATA", player);
|
||||
} catch (IllegalArgumentException e) {
|
||||
SchematicSystem.MESSAGE.send("UTIL_LOAD_ILLEGAL_REVISION", player, revision);
|
||||
} catch (Exception e) {
|
||||
SchematicSystem.MESSAGE.send("UTIL_LOAD_ERROR", player);
|
||||
Bukkit.getLogger().log(Level.INFO, e.getMessage(), e);
|
||||
@ -421,6 +428,8 @@ public class SchematicCommandUtils {
|
||||
return;
|
||||
}
|
||||
|
||||
node.setPrepared(false);
|
||||
|
||||
if (type.writeable()) {
|
||||
node.setSchemtype(type);
|
||||
SchematicSystem.MESSAGE.send("UTIL_TYPE_DONE", player);
|
||||
@ -483,7 +492,7 @@ public class SchematicCommandUtils {
|
||||
node.setAllowReplay(!node.allowReplay());
|
||||
submitSchemGUI(player, node, type);
|
||||
});
|
||||
inv.setItem(1, SWItem.getMaterial(node.replaceColor() ? "PINK_WOOL" : "LIGHT_GRAY_WOOL"), SchematicSystem.MESSAGE.parse(node.allowReplay()?"UTIL_SUBMIT_COLOR_ON":"UTIL_SUBMIT_COLOR_OFF", player), click -> {
|
||||
inv.setItem(1, SWItem.getMaterial(node.replaceColor() ? "PINK_WOOL" : "LIGHT_GRAY_WOOL"), SchematicSystem.MESSAGE.parse(node.replaceColor()?"UTIL_SUBMIT_COLOR_ON":"UTIL_SUBMIT_COLOR_OFF", player), click -> {
|
||||
node.setReplaceColor(!node.replaceColor());
|
||||
submitSchemGUI(player, node, type);
|
||||
});
|
||||
|
||||
@ -27,7 +27,6 @@ import de.steamwar.providers.BauServerInfo;
|
||||
import de.steamwar.schematicsystem.SchematicSystem;
|
||||
import de.steamwar.schematicsystem.commands.schematiccommand.SchematicCommand;
|
||||
import de.steamwar.sql.*;
|
||||
import net.md_5.bungee.api.chat.ClickEvent;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
@ -44,16 +43,15 @@ public class SavePart extends SWCommand {
|
||||
}
|
||||
|
||||
@Register("save")
|
||||
@Register("s")
|
||||
public void saveSchem(Player player) {
|
||||
SchematicSelector selector = new SchematicSelector(player, SchematicSelector.selectSchematicNode(), schematicNode -> {
|
||||
if(schematicNode == null || schematicNode.isDir()) {
|
||||
SWAnvilInv anvilInv = new SWAnvilInv(player, SchematicSystem.MESSAGE.parse("COMMAND_ENTER_NAME", player));
|
||||
anvilInv.setCallback(s -> saveSchem(player, schematicNode==null?s:(schematicNode.generateBreadcrumbs() + s), true));
|
||||
anvilInv.setCallback(s -> saveSchem(player, schematicNode==null?s:(schematicNode.generateBreadcrumbs() + s)));
|
||||
anvilInv.setItem(Material.CAULDRON);
|
||||
anvilInv.open();
|
||||
} else {
|
||||
saveSchem(player, schematicNode.generateBreadcrumbs(), true);
|
||||
saveSchem(player, schematicNode.generateBreadcrumbs());
|
||||
}
|
||||
});
|
||||
selector.setSingleDirOpen(false);
|
||||
@ -61,8 +59,7 @@ public class SavePart extends SWCommand {
|
||||
}
|
||||
|
||||
@Register("save")
|
||||
@Register("s")
|
||||
public void saveSchem(Player player, @AbstractSWCommand.Mapper("stringMapper") String name, @AbstractSWCommand.StaticValue(value = {"", "-f"}, allowISE=true) @AbstractSWCommand.OptionalValue("") boolean overwrite) {
|
||||
public void saveSchem(Player player, @AbstractSWCommand.Mapper("stringMapper") String name) {
|
||||
SteamwarUser user = getUser(player);
|
||||
if(BauServerInfo.isBauServer() && BauServerInfo.getOwnerId() != user.getId() &&
|
||||
(Punishment.isPunished(user, Punishment.PunishmentType.NoSchemReceiving, punishment ->
|
||||
@ -88,9 +85,6 @@ public class SavePart extends SWCommand {
|
||||
} else if (!node.getSchemtype().writeable() || node.getOwner() != user.getId()) {
|
||||
SchematicSystem.MESSAGE.send("COMMAND_SAVE_NO_OVERWRITE", player);
|
||||
return;
|
||||
} else if(!overwrite) {
|
||||
SchematicSystem.MESSAGE.send("COMMAND_SAVE_OVERWRITE_CONFIRM", player, SchematicSystem.MESSAGE.parse("COMMAND_SAVE_OVERWRITE_CONFIRM_HOVER", player), new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/schem s " + name + " -f"), node.generateBreadcrumbs());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -101,7 +95,7 @@ public class SavePart extends SWCommand {
|
||||
}
|
||||
|
||||
try {
|
||||
new SchematicData(node).saveFromPlayer(player);
|
||||
SchematicData.saveFromPlayer(player, node);
|
||||
} catch (NoClipboardException e) {
|
||||
SchematicSystem.MESSAGE.send("COMMAND_SAVE_CLIPBOARD_EMPTY", player);
|
||||
if (newSchem)
|
||||
|
||||
@ -21,13 +21,23 @@ package de.steamwar.schematicsystem.commands.schematiccommand.parts;
|
||||
|
||||
import de.steamwar.command.AbstractSWCommand;
|
||||
import de.steamwar.command.SWCommand;
|
||||
import de.steamwar.schematicsystem.SchematicSystem;
|
||||
import de.steamwar.schematicsystem.commands.schematiccommand.GUI;
|
||||
import de.steamwar.schematicsystem.commands.schematiccommand.SchematicCommandUtils;
|
||||
import de.steamwar.schematicsystem.commands.schematiccommand.SchematicCommand;
|
||||
import de.steamwar.sql.NodeData;
|
||||
import de.steamwar.sql.SchematicNode;
|
||||
import de.steamwar.sql.SteamwarUser;
|
||||
import net.md_5.bungee.api.chat.ClickEvent;
|
||||
import net.md_5.bungee.api.chat.ComponentBuilder;
|
||||
import net.md_5.bungee.api.chat.HoverEvent;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.FormatStyle;
|
||||
import java.util.List;
|
||||
|
||||
import static de.steamwar.schematicsystem.commands.schematiccommand.SchematicCommandUtils.*;
|
||||
|
||||
@AbstractSWCommand.PartOf(SchematicCommand.class)
|
||||
@ -69,6 +79,25 @@ public class ViewPart extends SWCommand {
|
||||
printSchemInfo(player, node);
|
||||
}
|
||||
|
||||
@Register("revisions")
|
||||
public void revisions(Player player, @Validator("isSchemValidator") SchematicNode node) {
|
||||
List<NodeData> revisions = NodeData.get(node);
|
||||
if(revisions.isEmpty()) {
|
||||
SchematicSystem.MESSAGE.send("REVISIONS_EMPTY", player);
|
||||
return;
|
||||
}
|
||||
|
||||
SchematicSystem.MESSAGE.send("REVISIONS_TITLE", player);
|
||||
for (int j = Math.max(0, revisions.size() - 10); j < revisions.size(); j++) {
|
||||
player.spigot().sendMessage(
|
||||
new ComponentBuilder(SchematicSystem.MESSAGE.parseToComponent("REVISIONS_REVISION_NUMBER", false, player, j + 1, revisions.get(j).getCreatedAt()))
|
||||
.event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/schem load " + (node.getOwner() == 0 ? "public " : "") + node.generateBreadcrumbs() + " " + (j + 1)))
|
||||
.event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TextComponent[]{SchematicSystem.MESSAGE.parseToComponent("UTIL_INFO_ACTION_LOAD_HOVER", false, player)}))
|
||||
.create()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Register(value = "page", noTabComplete = true)
|
||||
public void pageCommand(Player player, int page) {
|
||||
cachedSchemList(player, page);
|
||||
@ -76,14 +105,14 @@ public class ViewPart extends SWCommand {
|
||||
|
||||
@Register({"l", "public"})
|
||||
@Register({"load", "public"})
|
||||
public void loadSchemPublic(Player player, @Validator("isSchemValidator") @Mapper("publicMapper") SchematicNode node) {
|
||||
loadSchem(player, node);
|
||||
public void loadSchemPublic(Player player, @Validator("isSchemValidator") @Mapper("publicMapper") SchematicNode node, @OptionalValue("-1") int revision) {
|
||||
loadSchem(player, node, revision);
|
||||
}
|
||||
|
||||
@Register("l")
|
||||
@Register("load")
|
||||
public void loadSchem(Player player, @Validator("isSchemValidator") SchematicNode node) {
|
||||
SchematicCommandUtils.loadSchem(player, node);
|
||||
public void loadSchem(Player player, @Validator("isSchemValidator") SchematicNode node, @OptionalValue("-1") int revision) {
|
||||
SchematicCommandUtils.loadSchem(player, node, revision);
|
||||
}
|
||||
|
||||
@Register("gui")
|
||||
@ -92,7 +121,7 @@ public class ViewPart extends SWCommand {
|
||||
}
|
||||
|
||||
@Register("download")
|
||||
public void download(Player player, @Validator("isOwnerSchematicValidator") SchematicNode node) {
|
||||
public void download(Player player, @Validator("isSchemValidator") SchematicNode node) {
|
||||
SchematicCommandUtils.download(player, node);
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,19 +31,23 @@ public class CRIUSupport {
|
||||
throw new UnsupportedOperationException("This is a Dummy");
|
||||
}
|
||||
|
||||
public void setAutoDedup(boolean autoDedup) {
|
||||
public CRIUSupport setGhostFileLimit(long limit) {
|
||||
throw new UnsupportedOperationException("This is a Dummy");
|
||||
}
|
||||
|
||||
public void setShellJob(boolean shellJob) {
|
||||
public CRIUSupport setAutoDedup(boolean autoDedup) {
|
||||
throw new UnsupportedOperationException("This is a Dummy");
|
||||
}
|
||||
|
||||
public void setFileLocks(boolean fileLocks) {
|
||||
public CRIUSupport setShellJob(boolean shellJob) {
|
||||
throw new UnsupportedOperationException("This is a Dummy");
|
||||
}
|
||||
|
||||
public void setLogFile(String logFile) {
|
||||
public CRIUSupport setFileLocks(boolean fileLocks) {
|
||||
throw new UnsupportedOperationException("This is a Dummy");
|
||||
}
|
||||
|
||||
public CRIUSupport setLogFile(String logFile) {
|
||||
throw new UnsupportedOperationException("This is a Dummy");
|
||||
}
|
||||
|
||||
|
||||
@ -19,5 +19,8 @@
|
||||
|
||||
package org.eclipse.openj9.criu;
|
||||
|
||||
import lombok.experimental.StandardException;
|
||||
|
||||
@StandardException
|
||||
public class JVMCRIUException extends Exception {
|
||||
}
|
||||
|
||||
@ -565,17 +565,17 @@ public class WorldEditWrapper14 implements WorldEditWrapper {
|
||||
for (Map<String, Tag> tileEntity : tileEntityTags) {
|
||||
int[] pos = requireTag(tileEntity, "Pos", IntArrayTag.class).getValue();
|
||||
final BlockVector3 pt = BlockVector3.at(pos[0], pos[1], pos[2]);
|
||||
Map<String, Tag> values = Maps.newHashMap(tileEntity);
|
||||
Map<String, Tag> values = Maps.newHashMap(v3Mode ? requireTag(tileEntity, "Data", CompoundTag.class).getValue() : tileEntity);
|
||||
if(faweSchem){
|
||||
values.put("x", new IntTag(pt.getBlockX() - offsetX));
|
||||
values.put("y", new IntTag(pt.getBlockY() - offsetY));
|
||||
values.put("z", new IntTag(pt.getBlockZ() - offsetZ));
|
||||
}else{
|
||||
values.put("x", new IntTag(pt.getBlockX()));
|
||||
values.put("y", new IntTag(pt.getBlockY()));
|
||||
values.put("z", new IntTag(pt.getBlockZ()));
|
||||
values.putIfAbsent("x", new IntTag(pt.getBlockX()));
|
||||
values.putIfAbsent("y", new IntTag(pt.getBlockY()));
|
||||
values.putIfAbsent("z", new IntTag(pt.getBlockZ()));
|
||||
}
|
||||
values.put("id", values.get("Id"));
|
||||
values.putIfAbsent("id", values.get("Id"));
|
||||
values.remove("Id");
|
||||
values.remove("Pos");
|
||||
if (fixer != null) {
|
||||
|
||||
@ -37,4 +37,7 @@ dependencies {
|
||||
|
||||
compileOnly(libs.paperapi21)
|
||||
compileOnly(libs.nms21)
|
||||
compileOnly(libs.datafixer)
|
||||
compileOnly(libs.netty)
|
||||
compileOnly(libs.authlib)
|
||||
}
|
||||
|
||||
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2022 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.core;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import de.steamwar.Reflection;
|
||||
import net.minecraft.Util;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket;
|
||||
import net.minecraft.world.level.GameType;
|
||||
import org.bukkit.GameMode;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.function.LongSupplier;
|
||||
|
||||
public class ProtocolWrapper21 implements ProtocolWrapper {
|
||||
|
||||
private static final Reflection.Field<List> equipmentStack = Reflection.getField(equipmentPacket, List.class, 0);
|
||||
@Override
|
||||
public void setEquipmentPacketStack(Object packet, Object slot, Object stack) {
|
||||
equipmentStack.set(packet, Collections.singletonList(new Pair<>(slot, stack)));
|
||||
}
|
||||
|
||||
private static final Reflection.Constructor removePacketConstructor = Reflection.getConstructor(ClientboundPlayerInfoRemovePacket.class, List.class);
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public Object playerInfoPacketConstructor(PlayerInfoAction action, GameProfile profile, GameMode mode) {
|
||||
if(action == PlayerInfoAction.REMOVE)
|
||||
return removePacketConstructor.invoke(Collections.singletonList(profile.getId()));
|
||||
return switch (action) {
|
||||
case ADD -> new ClientboundPlayerInfoUpdatePacket(EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER, ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE), new ClientboundPlayerInfoUpdatePacket.Entry(
|
||||
profile.getId(), profile, true, 0, GameType.byId(mode.getValue()), null, true, 0, null
|
||||
));
|
||||
case GAMEMODE -> new ClientboundPlayerInfoUpdatePacket(EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE), new ClientboundPlayerInfoUpdatePacket.Entry(
|
||||
profile.getId(), profile, true, 0, GameType.byId(mode.getValue()), null, true, 0, null
|
||||
));
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initTPSWarp(LongSupplier longSupplier) {
|
||||
Util.timeSource = () -> System.nanoTime() + longSupplier.getAsLong();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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.entity;
|
||||
|
||||
import net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket;
|
||||
import net.minecraft.world.entity.PositionMoveRotation;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
public class PacketConstructor21 implements PacketConstructor{
|
||||
@Override
|
||||
public Object teleportPacket(int entityId, double x, double y, double z, float yaw, float pitch) {
|
||||
PositionMoveRotation rot = new PositionMoveRotation(new Vec3(x, y, z), Vec3.ZERO, pitch, yaw);
|
||||
return new ClientboundTeleportEntityPacket(entityId, rot, Collections.emptySet(), false);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,157 @@
|
||||
/*
|
||||
* 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.techhider;
|
||||
|
||||
import de.steamwar.Reflection;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import net.minecraft.network.protocol.game.ClientboundLevelChunkPacketData;
|
||||
import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket;
|
||||
import net.minecraft.util.SimpleBitStorage;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.UnaryOperator;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ChunkHider21 implements ChunkHider {
|
||||
@Override
|
||||
public Class<?> mapChunkPacket() {
|
||||
return ClientboundLevelChunkWithLightPacket.class;
|
||||
}
|
||||
|
||||
private static final UnaryOperator<Object> chunkPacketCloner = ProtocolUtils.shallowCloneGenerator(ClientboundLevelChunkWithLightPacket.class);
|
||||
private static final UnaryOperator<Object> chunkDataCloner = ProtocolUtils.shallowCloneGenerator(ClientboundLevelChunkPacketData.class);
|
||||
|
||||
private static final Reflection.Field<Integer> chunkXField = Reflection.getField(ClientboundLevelChunkWithLightPacket.class, int.class, 0);
|
||||
private static final Reflection.Field<Integer> chunkZField = Reflection.getField(ClientboundLevelChunkWithLightPacket.class, int.class, 1);
|
||||
private static final Reflection.Field<ClientboundLevelChunkPacketData> chunkData = Reflection.getField(ClientboundLevelChunkWithLightPacket.class, ClientboundLevelChunkPacketData.class, 0);
|
||||
|
||||
private static final Reflection.Field<byte[]> dataField = Reflection.getField(ClientboundLevelChunkPacketData.class, byte[].class, 0);
|
||||
private static final Reflection.Field<List> tileEntities = Reflection.getField(ClientboundLevelChunkPacketData.class, List.class, 0);
|
||||
|
||||
@Override
|
||||
public BiFunction<Player, Object, Object> chunkHiderGenerator(TechHider techHider) {
|
||||
return (p, packet) -> {
|
||||
int chunkX = chunkXField.get(packet);
|
||||
int chunkZ = chunkZField.get(packet);
|
||||
if (techHider.getLocationEvaluator().skipChunk(p, chunkX, chunkZ))
|
||||
return packet;
|
||||
|
||||
packet = chunkPacketCloner.apply(packet);
|
||||
Object dataWrapper = chunkDataCloner.apply(chunkData.get(packet));
|
||||
|
||||
Set<String> hiddenBlockEntities = techHider.getHiddenBlockEntities();
|
||||
tileEntities.set(dataWrapper, ((List<?>)tileEntities.get(dataWrapper)).stream().filter(te -> tileEntityVisible(hiddenBlockEntities, te)).collect(Collectors.toList()));
|
||||
|
||||
ByteBuf in = Unpooled.wrappedBuffer(dataField.get(dataWrapper));
|
||||
ByteBuf out = Unpooled.buffer(in.readableBytes() + 64);
|
||||
for(int yOffset = p.getWorld().getMinHeight(); yOffset < p.getWorld().getMaxHeight(); yOffset += 16) {
|
||||
SectionHider section = new SectionHider(p, techHider, in, out, chunkX, yOffset/16, chunkZ);
|
||||
section.copyBlockCount();
|
||||
|
||||
blocks(section);
|
||||
biomes(section);
|
||||
}
|
||||
|
||||
if (in.readableBytes() != 0) {
|
||||
throw new IllegalStateException("ChunkHider21: Incomplete chunk data, " + in.readableBytes() + " bytes left");
|
||||
}
|
||||
|
||||
byte[] data = new byte[out.readableBytes()];
|
||||
out.readBytes(data);
|
||||
dataField.set(dataWrapper, data);
|
||||
|
||||
chunkData.set(packet, dataWrapper);
|
||||
return packet;
|
||||
};
|
||||
}
|
||||
|
||||
public static final Class<?> tileEntity = Reflection.getClass("net.minecraft.network.protocol.game.ClientboundLevelChunkPacketData$BlockEntityInfo");
|
||||
protected static final Reflection.Field<BlockEntityType> entityType = Reflection.getField(tileEntity, BlockEntityType.class, 0);
|
||||
private static final Class<?> builtInRegestries = Reflection.getClass("net.minecraft.core.registries.BuiltInRegistries");
|
||||
private static final Class<?> registry = Reflection.getClass("net.minecraft.core.Registry");
|
||||
private static final Reflection.Field<?> nameField = Reflection.getField(builtInRegestries, "BLOCK_ENTITY_TYPE", registry);
|
||||
private static final Class<?> resourceLocation = Reflection.getClass("net.minecraft.resources.ResourceLocation");
|
||||
private static final Reflection.Method getKey = Reflection.getTypedMethod(registry, "getKey", resourceLocation, Object.class);
|
||||
private static final Reflection.Method getName = Reflection.getTypedMethod(resourceLocation, "getPath", String.class);
|
||||
protected boolean tileEntityVisible(Set<String> hiddenBlockEntities, Object tile) {
|
||||
return !hiddenBlockEntities.contains(getName.invoke(getKey.invoke(nameField.get(null), entityType.get(tile))));
|
||||
}
|
||||
|
||||
private void blocks(SectionHider section) {
|
||||
section.copyBitsPerBlock();
|
||||
|
||||
boolean singleValued = section.getBitsPerBlock() == 0;
|
||||
if (singleValued) {
|
||||
int value = ProtocolUtils.readVarInt(section.getIn());
|
||||
ProtocolUtils.writeVarInt(section.getOut(), !section.isSkipSection() && section.getObfuscate().contains(value) ? section.getTarget() : value);
|
||||
return;
|
||||
} else {
|
||||
section.processPalette();
|
||||
}
|
||||
|
||||
if (section.isSkipSection() || (!section.blockPrecise() && section.isPaletted())) {
|
||||
section.skipNewDataArray(4096);
|
||||
return;
|
||||
}
|
||||
|
||||
SimpleBitStorage values = new SimpleBitStorage(section.getBitsPerBlock(), 4096, section.readNewDataArray(4096));
|
||||
|
||||
for (int y = 0; y < 16; y++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
int pos = (((y * 16) + z) * 16) + x;
|
||||
|
||||
TechHider.State test = section.test(x, y, z);
|
||||
|
||||
switch (test) {
|
||||
case SKIP:
|
||||
break;
|
||||
case CHECK:
|
||||
if (!section.getObfuscate().contains(values.get(pos)))
|
||||
break;
|
||||
case HIDE:
|
||||
values.set(pos, section.getTarget());
|
||||
break;
|
||||
case HIDE_AIR:
|
||||
default:
|
||||
values.set(pos, section.getAir());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
section.writeDataArray(values.getRaw());
|
||||
}
|
||||
|
||||
private void biomes(SectionHider section) {
|
||||
section.copyBitsPerBlock();
|
||||
if(section.getBitsPerBlock() == 0) {
|
||||
section.copyVarInt();
|
||||
} else if(section.getBitsPerBlock() < 6) {
|
||||
section.skipPalette();
|
||||
section.skipNewDataArray(64);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -157,7 +157,23 @@ public final class Reflection {
|
||||
} else if(MAJOR_VERSION < 21 || MINOR_VERSION < 4) {
|
||||
return Class.forName(spigotClassnames.getOrDefault(name, name));
|
||||
} else {
|
||||
return Class.forName(name);
|
||||
Class<?> clazz = null;
|
||||
try {
|
||||
clazz = Class.forName(name);
|
||||
} catch (ClassNotFoundException e) {}
|
||||
if (clazz != null && clazz.getName().equals(name)) {
|
||||
return clazz;
|
||||
}
|
||||
|
||||
try {
|
||||
return Core.class.getClassLoader().getParent().loadClass(name);
|
||||
} catch (ClassNotFoundException e) {
|
||||
if (clazz == null) {
|
||||
throw e;
|
||||
}
|
||||
|
||||
return clazz;
|
||||
}
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new IllegalArgumentException("Cannot find " + name, e);
|
||||
|
||||
@ -19,6 +19,10 @@
|
||||
|
||||
package de.steamwar.command;
|
||||
|
||||
import de.steamwar.core.Core;
|
||||
import de.steamwar.providers.BauServerInfo;
|
||||
import de.steamwar.sql.AuditLog;
|
||||
import de.steamwar.sql.SteamwarUser;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
@ -31,5 +35,6 @@ public class CaseInsensitiveCommandsListener implements Listener {
|
||||
String[] strings = event.getMessage().split(" ");
|
||||
strings[0] = strings[0].toLowerCase();
|
||||
event.setMessage(String.join(" ", strings));
|
||||
AuditLog.createCommand(Core.getServerName(), BauServerInfo.getOwnerUser(), SteamwarUser.get(event.getPlayer().getUniqueId()), event.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,8 +19,8 @@
|
||||
|
||||
package de.steamwar.core;
|
||||
|
||||
import de.steamwar.Reflection;
|
||||
import com.comphenix.tinyprotocol.TinyProtocol;
|
||||
import de.steamwar.Reflection;
|
||||
import de.steamwar.sql.internal.Statement;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import org.bukkit.Bukkit;
|
||||
@ -94,6 +94,7 @@ class CheckpointUtilsJ9 {
|
||||
private static final Reflection.Method bind = Reflection.getMethod(TinyProtocol.serverConnection, null, InetAddress.class, int.class);
|
||||
private static void freezeInternal(Path path) throws Exception {
|
||||
Bukkit.getPluginManager().callEvent(new CRIUSleepEvent());
|
||||
|
||||
Bukkit.getWorlds().forEach(FlatteningWrapper.impl::syncSave);
|
||||
Statement.closeAll();
|
||||
|
||||
@ -111,6 +112,7 @@ class CheckpointUtilsJ9 {
|
||||
// Do the checkpoint
|
||||
path.toFile().mkdirs();
|
||||
CRIUSupport criu = new CRIUSupport(path);
|
||||
criu.setGhostFileLimit(10L * 1024L * 1024L);
|
||||
criu.setAutoDedup(true);
|
||||
criu.setFileLocks(true);
|
||||
criu.setShellJob(true);
|
||||
@ -119,8 +121,9 @@ class CheckpointUtilsJ9 {
|
||||
criu.checkpointJVM();
|
||||
} catch (JVMCRIUException e) {
|
||||
Path logfile = path.resolve("criu.log");
|
||||
if(logfile.toFile().exists())
|
||||
if(logfile.toFile().exists()) {
|
||||
throw new IllegalStateException("Could not create checkpoint, criu log:\n" + new String(Files.readAllBytes(logfile)), e);
|
||||
}
|
||||
|
||||
throw e;
|
||||
}
|
||||
|
||||
@ -33,6 +33,8 @@ import de.steamwar.network.handlers.ServerDataHandler;
|
||||
import de.steamwar.sql.SchematicNode;
|
||||
import de.steamwar.sql.SteamwarUser;
|
||||
import de.steamwar.sql.internal.Statement;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.event.Listener;
|
||||
@ -52,12 +54,17 @@ public class Core extends JavaPlugin {
|
||||
return Reflection.MAJOR_VERSION;
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private static JavaPlugin instance;
|
||||
public static JavaPlugin getInstance() {
|
||||
return instance;
|
||||
|
||||
@Getter
|
||||
private static String serverName = "";
|
||||
|
||||
public static void setServerName(String serverName) {
|
||||
if (serverName.isEmpty()) {
|
||||
Core.serverName = serverName;
|
||||
}
|
||||
public static void setInstance(JavaPlugin instance) {
|
||||
Core.instance = instance;
|
||||
}
|
||||
|
||||
private ErrorHandler errorHandler;
|
||||
@ -66,6 +73,7 @@ public class Core extends JavaPlugin {
|
||||
@Override
|
||||
public void onLoad() {
|
||||
setInstance(this);
|
||||
serverName = System.getProperty("serverName", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -39,11 +39,14 @@ import org.bukkit.util.Vector;
|
||||
|
||||
public class WorldEditRenderer implements Listener {
|
||||
|
||||
private static WorldEditRenderer INSTANCE;
|
||||
|
||||
private static final Material WAND = FlatteningWrapper.impl.getMaterial("WOOD_AXE");
|
||||
|
||||
private final WorldEditPlugin we;
|
||||
|
||||
public WorldEditRenderer() {
|
||||
INSTANCE = this;
|
||||
we = WorldEditWrapper.getWorldEditPlugin();
|
||||
Bukkit.getPluginManager().registerEvents(this, Core.getInstance());
|
||||
|
||||
@ -54,6 +57,10 @@ public class WorldEditRenderer implements Listener {
|
||||
}, 20, 20);
|
||||
}
|
||||
|
||||
public static void renderPlayer(Player player) {
|
||||
WorldEditRenderer.INSTANCE.renderPlayer(player, false);
|
||||
}
|
||||
|
||||
private void renderPlayer(Player player, boolean scheduled) {
|
||||
LocalSession session = we.getSession(player);
|
||||
renderClipboard(player, session, scheduled);
|
||||
|
||||
@ -19,6 +19,9 @@
|
||||
|
||||
package de.steamwar.core.events;
|
||||
|
||||
import de.steamwar.core.Core;
|
||||
import de.steamwar.providers.BauServerInfo;
|
||||
import de.steamwar.sql.AuditLog;
|
||||
import de.steamwar.sql.SteamwarUser;
|
||||
import de.steamwar.sql.UserPerm;
|
||||
import de.steamwar.sql.internal.Statement;
|
||||
@ -44,12 +47,14 @@ public class PlayerJoinedEvent implements Listener{
|
||||
player.setDisplayName(prefix.getColorCode() + player.getName() + "§r");
|
||||
|
||||
event.setJoinMessage("§a§l» §r" + player.getDisplayName());
|
||||
AuditLog.createJoin(Core.getServerName(), BauServerInfo.getOwnerUser(), user);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
private void onQuit(PlayerQuitEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
|
||||
event.setQuitMessage("§c§l« §r" + player.getDisplayName());
|
||||
AuditLog.createLeave(Core.getServerName(), BauServerInfo.getOwnerUser(), SteamwarUser.get(player.getUniqueId()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2020 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.entity;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.util.Transformation;
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class CCubedTextDisplay extends CEntity {
|
||||
|
||||
private Map<BlockFace, RTextDisplay> displays = new HashMap<>();
|
||||
|
||||
public CCubedTextDisplay(REntityServer server, Location loc) {
|
||||
super(server);
|
||||
{
|
||||
Location location = loc.clone().add(0.5, 0.4, 1.01);
|
||||
RTextDisplay display = new RTextDisplay(server, location);
|
||||
entities.add(display);
|
||||
displays.put(BlockFace.SOUTH, display);
|
||||
}
|
||||
{
|
||||
Location location = loc.clone().add(0.5, 0.4, -0.01);
|
||||
RTextDisplay display = new RTextDisplay(server, location);
|
||||
display.setTransform(new Transformation(new Vector3f(0, 0, 0), new Quaternionf().rotateY((float) Math.toRadians(180)), new Vector3f(1, 1, 1), new Quaternionf()));
|
||||
entities.add(display);
|
||||
displays.put(BlockFace.NORTH, display);
|
||||
}
|
||||
{
|
||||
Location location = loc.clone().add(1.01, 0.4, 0.5);
|
||||
RTextDisplay display = new RTextDisplay(server, location);
|
||||
display.setTransform(new Transformation(new Vector3f(0, 0, 0), new Quaternionf().rotateY((float) Math.toRadians(90)), new Vector3f(1, 1, 1), new Quaternionf()));
|
||||
entities.add(display);
|
||||
displays.put(BlockFace.EAST, display);
|
||||
}
|
||||
{
|
||||
Location location = loc.clone().add(-0.01, 0.4, 0.5);
|
||||
RTextDisplay display = new RTextDisplay(server, location);
|
||||
display.setTransform(new Transformation(new Vector3f(0, 0, 0), new Quaternionf().rotateY((float) Math.toRadians(270)), new Vector3f(1, 1, 1), new Quaternionf()));
|
||||
entities.add(display);
|
||||
displays.put(BlockFace.WEST, display);
|
||||
}
|
||||
{
|
||||
Location location = loc.clone().add(0.5, 1.01, 0.6);
|
||||
RTextDisplay display = new RTextDisplay(server, location);
|
||||
display.setTransform(new Transformation(new Vector3f(0, 0, 0), new Quaternionf().rotationX((float) Math.toRadians(270)), new Vector3f(1, 1, 1), new Quaternionf()));
|
||||
entities.add(display);
|
||||
displays.put(BlockFace.UP, display);
|
||||
}
|
||||
{
|
||||
Location location = loc.clone().add(0.5, -0.01, 0.4);
|
||||
RTextDisplay display = new RTextDisplay(server, location);
|
||||
display.setTransform(new Transformation(new Vector3f(0, 0, 0), new Quaternionf().rotationX((float) Math.toRadians(90)), new Vector3f(1, 1, 1), new Quaternionf()));
|
||||
entities.add(display);
|
||||
displays.put(BlockFace.DOWN, display);
|
||||
}
|
||||
}
|
||||
|
||||
public void hide(Set<BlockFace> blockFaceSet) {
|
||||
for (BlockFace blockFace : BlockFace.values()) {
|
||||
RTextDisplay display = displays.get(blockFace);
|
||||
if (display == null) continue;
|
||||
display.hide(blockFaceSet.contains(blockFace));
|
||||
}
|
||||
if (displays.values().stream().allMatch(RTextDisplay::isHidden)) {
|
||||
displays.values().forEach(rTextDisplay -> rTextDisplay.hide(false));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void move(Location location) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void move(double locX, double locY, double locZ, float pitch, float yaw, byte headYaw) {
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
displays.values().forEach(rTextDisplay -> rTextDisplay.setText(text));
|
||||
}
|
||||
|
||||
public void setLineWidth(int lineWidth) {
|
||||
displays.values().forEach(rTextDisplay -> rTextDisplay.setLineWidth(lineWidth));
|
||||
}
|
||||
|
||||
public void setTextOpacity(byte textOpacity) {
|
||||
displays.values().forEach(rTextDisplay -> rTextDisplay.setTextOpacity(textOpacity));
|
||||
}
|
||||
|
||||
public void setShadowed(boolean shadowed) {
|
||||
displays.values().forEach(rTextDisplay -> rTextDisplay.setShadowed(shadowed));
|
||||
}
|
||||
|
||||
public void setSeeThrough(boolean seeThrough) {
|
||||
displays.values().forEach(rTextDisplay -> rTextDisplay.setSeeThrough(seeThrough));
|
||||
}
|
||||
|
||||
public void setBackgroundColor(int color) {
|
||||
displays.values().forEach(rTextDisplay -> rTextDisplay.setBackgroundColor(color));
|
||||
}
|
||||
|
||||
public void setDefaultBackground(boolean defaultBackground) {
|
||||
displays.values().forEach(rTextDisplay -> rTextDisplay.setDefaultBackground(defaultBackground));
|
||||
}
|
||||
}
|
||||
@ -19,6 +19,7 @@
|
||||
|
||||
package de.steamwar.entity;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.entity.Display;
|
||||
@ -31,6 +32,10 @@ import org.joml.Vector3f;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Can be used for Axis Aligned Lines of near infinite length.
|
||||
*/
|
||||
@Getter
|
||||
public class CLine extends CEntity {
|
||||
|
||||
public static final float DEFAULT_WIDTH = 1 / 16f;
|
||||
|
||||
131
SpigotCore/SpigotCore_Main/src/de/steamwar/entity/CRay.java
Normal file
131
SpigotCore/SpigotCore_Main/src/de/steamwar/entity/CRay.java
Normal file
@ -0,0 +1,131 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2020 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.entity;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.entity.Display;
|
||||
import org.bukkit.util.Consumer;
|
||||
import org.bukkit.util.Transformation;
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Can be used for Lines of short length.
|
||||
*/
|
||||
@Getter
|
||||
public class CRay extends CEntity {
|
||||
|
||||
public static final float DEFAULT_WIDTH = 1 / 16f;
|
||||
|
||||
private Location from;
|
||||
private Location to;
|
||||
private float width = DEFAULT_WIDTH;
|
||||
private BlockData blockData = RBlockDisplay.DEFAULT_BLOCK;
|
||||
private boolean hide = false;
|
||||
|
||||
public CRay(REntityServer server) {
|
||||
super(server);
|
||||
}
|
||||
|
||||
private <T> CRay checkAndSet(T currentValue, T newValue, Consumer<T> setter) {
|
||||
if (Objects.equals(currentValue, newValue)) return this;
|
||||
setter.accept(newValue);
|
||||
tick();
|
||||
return this;
|
||||
}
|
||||
|
||||
public CRay setFrom(Location from) {
|
||||
return checkAndSet(this.from, from, location -> this.from = location);
|
||||
}
|
||||
|
||||
public CRay setTo(Location to) {
|
||||
return checkAndSet(this.to, to, location -> this.to = location);
|
||||
}
|
||||
|
||||
public CRay setWidth(float width) {
|
||||
return checkAndSet(this.width, width, location -> this.width = width);
|
||||
}
|
||||
|
||||
public CRay setBlock(BlockData blockData) {
|
||||
if (this.blockData.equals(blockData)) return this;
|
||||
if (blockData == null) {
|
||||
this.blockData = RBlockDisplay.DEFAULT_BLOCK;
|
||||
} else {
|
||||
this.blockData = blockData;
|
||||
}
|
||||
if (display != null) {
|
||||
display.setBlock(blockData);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hide(boolean hide) {
|
||||
if (hide == this.hide) return;
|
||||
this.hide = hide;
|
||||
if (hide) {
|
||||
if (display != null) display.hide(true);
|
||||
} else {
|
||||
tick();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void tick() {
|
||||
if (from == null || to == null) return;
|
||||
if (hide) return;
|
||||
updateDisplay();
|
||||
}
|
||||
|
||||
private RBlockDisplay display;
|
||||
|
||||
private void updateDisplay() {
|
||||
if (display == null) {
|
||||
display = new RBlockDisplay(server, new Location(null, 0, 0, 0));
|
||||
display.setBrightness(new Display.Brightness(15, 15));
|
||||
display.setViewRange(560);
|
||||
display.setBlock(blockData);
|
||||
entities.add(display);
|
||||
} else {
|
||||
display.hide(false);
|
||||
}
|
||||
|
||||
Vector3f pointA = new Vector3f((float) from.getX(), (float) from.getY(), (float) from.getZ());
|
||||
Vector3f pointB = new Vector3f((float) to.getX(), (float) to.getY(), (float) to.getZ());
|
||||
Vector3f direction = new Vector3f(pointB).sub(pointA);
|
||||
float length = direction.length();
|
||||
|
||||
display.move(from);
|
||||
|
||||
Vector3f normalizedDir = new Vector3f(direction).normalize();
|
||||
|
||||
final Vector3f defaultAxis = new Vector3f(1, 0, 0);
|
||||
Quaternionf rotation = new Quaternionf().rotationTo(defaultAxis, normalizedDir);
|
||||
|
||||
Vector3f scale = new Vector3f(length, width, width);
|
||||
|
||||
Transformation transformation = new Transformation(new Vector3f(0, 0, 0), rotation, scale, new Quaternionf());
|
||||
display.setTransform(transformation);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user