Merge branch 'main' into Backend/init

This commit is contained in:
2024-08-23 11:40:04 +02:00
13 changed files with 268 additions and 59 deletions
@@ -72,7 +72,7 @@ import java.util.function.Consumer;
import java.util.logging.Level;
import java.util.stream.Collectors;
public class BauSystem extends JavaPlugin implements Listener {
public class BauSystem extends JavaPlugin {
// This should be treated as final!
public static Message MESSAGE;
@@ -20,6 +20,7 @@
package de.steamwar.bausystem.features.world;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.core.CRIUWakeupEvent;
import de.steamwar.core.CheckpointUtils;
import de.steamwar.linkage.Linked;
import org.bukkit.Bukkit;
@@ -69,4 +70,9 @@ public class AFKStopperListener implements Listener {
if(Bukkit.getOnlinePlayers().isEmpty() || (Bukkit.getOnlinePlayers().size() == 1 && Bukkit.getOnlinePlayers().contains(event.getPlayer())))
CheckpointUtils.freeze();
}
@EventHandler
public void onCRIUWakeup(CRIUWakeupEvent event) {
lastMovementTime = System.currentTimeMillis();
}
}
@@ -21,6 +21,7 @@ package de.steamwar.bausystem.features.world;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.config.BauServer;
import de.steamwar.core.CRIUWakeupEvent;
import de.steamwar.linkage.Linked;
import de.steamwar.sql.BauweltMember;
import de.steamwar.sql.SteamwarUser;
@@ -32,7 +33,6 @@ import org.bukkit.event.player.PlayerJoinEvent;
@Linked
public class AntiBauAddMemberFix implements Listener {
@EventHandler(priority = EventPriority.LOW)
public void onPlayerJoin(PlayerJoinEvent event) {
if (BauSystem.DEV_SERVER) return;
@@ -44,4 +44,9 @@ public class AntiBauAddMemberFix implements Listener {
throw new SecurityException("The player " + event.getPlayer().getName() + " joined on the server of " + SteamwarUser.get(BauServer.getInstance().getOwnerID()).getUserName() + " without being added!");
}
}
@EventHandler
public void onCRIUWakeup(CRIUWakeupEvent event) {
BauweltMember.clear();
}
}
@@ -0,0 +1,92 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2024 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.world;
import com.sk89q.worldedit.regions.RegionSelector;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.shared.Pair;
import de.steamwar.bausystem.utils.WorldEditUtils;
import de.steamwar.linkage.Linked;
import de.steamwar.linkage.MinVersion;
import de.steamwar.sql.SteamwarUser;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.checkerframework.checker.units.qual.min;
import java.io.*;
import java.util.List;
import java.util.logging.Level;
import java.util.stream.Collectors;
@Linked
@MinVersion(18)
public class WorldEditSelectionSaver implements Listener {
private File WORLD_EDIT_SELECTIONS = new File(Bukkit.getWorlds().get(0).getWorldFolder(), "world_edit_selections");
{
WORLD_EDIT_SELECTIONS.mkdir();
}
@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
SteamwarUser steamwarUser = SteamwarUser.get(event.getPlayer().getUniqueId());
File file = new File(WORLD_EDIT_SELECTIONS, Integer.toString(steamwarUser.getId()));
if (!file.exists()) return;
try {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
Class<? extends RegionSelector> clazz = (Class<? extends RegionSelector>) Class.forName(bufferedReader.readLine());
List<Location> locations = bufferedReader.lines()
.map(s -> s.split(" "))
.map(strings -> strings.length != 3 ? null : new Location(event.getPlayer().getWorld(), Integer.parseInt(strings[0]), Integer.parseInt(strings[1]), Integer.parseInt(strings[2])))
.collect(Collectors.toList());
WorldEditUtils.setVertices(event.getPlayer(), clazz, locations);
} catch (IOException | ClassNotFoundException e) {
BauSystem.getInstance().getLogger().log(Level.SEVERE, e.getMessage(), e);
file.delete();
}
}
@EventHandler
public void onPlayerQuit(PlayerQuitEvent event) {
SteamwarUser steamwarUser = SteamwarUser.get(event.getPlayer().getUniqueId());
Pair<Class<? extends RegionSelector>, List<Location>> data = WorldEditUtils.getVertices(event.getPlayer());
File file = new File(WORLD_EDIT_SELECTIONS, Integer.toString(steamwarUser.getId()));
try {
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)));
bufferedWriter.write(data.getKey().getTypeName());
for (Location location : data.getValue()) {
if (location == null) {
bufferedWriter.write("\n");
} else {
bufferedWriter.write("\n" + location.getBlockX() + " " + location.getBlockY() + " " + location.getBlockZ());
}
}
bufferedWriter.close();
} catch (IOException e) {
BauSystem.getInstance().getLogger().log(Level.SEVERE, e.getMessage(), e);
file.delete();
}
}
}
@@ -19,17 +19,21 @@
package de.steamwar.bausystem.utils;
import com.comphenix.tinyprotocol.Reflection;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.IncompleteRegionException;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.extension.factory.PatternFactory;
import com.sk89q.worldedit.extension.platform.permission.ActorSelectorLimits;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.internal.registry.InputParser;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.RegionSelector;
import com.sk89q.worldedit.regions.selector.limit.SelectorLimits;
import de.steamwar.bausystem.shared.Pair;
import lombok.SneakyThrows;
import lombok.experimental.UtilityClass;
@@ -37,6 +41,9 @@ import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Player;
import java.util.List;
import java.util.stream.Collectors;
@UtilityClass
public class WorldEditUtils {
@@ -77,6 +84,40 @@ public class WorldEditUtils {
return WorldEdit.getInstance().getPatternFactory();
}
public Pair<Class<? extends RegionSelector>, List<Location>> getVertices(Player player) {
RegionSelector regionSelector = WorldEdit.getInstance()
.getSessionManager()
.get(BukkitAdapter.adapt(player))
.getRegionSelector(BukkitAdapter.adapt(player.getWorld()));
return new Pair<>(regionSelector.getClass(), regionSelector.getVertices()
.stream()
.map(blockVector3 -> blockVector3 == null ? null : adapt(player.getWorld(), blockVector3))
.collect(Collectors.toList()));
}
public void setVertices(Player player, Class<? extends RegionSelector> clazz, List<Location> vertices) {
LocalSession localSession = WorldEdit.getInstance()
.getSessionManager()
.get(BukkitAdapter.adapt(player));
Reflection.ConstructorInvoker constructorInvoker = Reflection.getConstructor(clazz, com.sk89q.worldedit.world.World.class);
RegionSelector regionSelector = (RegionSelector) constructorInvoker.invoke(BukkitAdapter.adapt(player.getWorld()));
localSession.setRegionSelector(BukkitAdapter.adapt(player.getWorld()), regionSelector);
if (vertices.isEmpty()) return;
SelectorLimits selectorLimits = ActorSelectorLimits.forActor(BukkitAdapter.adapt(player));
for (int i = 0; i < vertices.size(); i++) {
Location location = vertices.get(i);
if (location == null) continue;
if (i == 0) {
regionSelector.selectPrimary(BukkitAdapter.adapt(location).toBlockPoint(), selectorLimits);
} else {
regionSelector.selectSecondary(BukkitAdapter.adapt(location).toBlockPoint(), selectorLimits);
}
}
}
public Pair<Location, Location> getSelection(Player player) {
RegionSelector regionSelector = WorldEdit.getInstance()
.getSessionManager()
@@ -111,11 +111,11 @@ public abstract class SpecialItem {
}
public static ItemStack getRandomItem() {
if (Config.MissileChance == 0 || consecutiveSupportItems > 1) {
consecutiveSupportItems = 0;
if (Config.MissileChance == 0) {
return supportItems.get(random.nextInt(supportItems.size())).getItem();
}
if (Config.MissileChance == 1) {
if (Config.MissileChance == 1 || consecutiveSupportItems > 1) {
consecutiveSupportItems = 0;
return missileItems.get(random.nextInt(missileItems.size())).getItem();
}
@@ -0,0 +1,36 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2024 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.core;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
public class CRIUSleepEvent extends Event {
private static final HandlerList handlers = new HandlerList();
@Override
public HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
}
@@ -0,0 +1,36 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2024 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.core;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
public class CRIUWakeupEvent extends Event {
private static final HandlerList handlers = new HandlerList();
@Override
public HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
}
@@ -22,7 +22,6 @@ package de.steamwar.core;
import com.comphenix.tinyprotocol.Reflection;
import com.comphenix.tinyprotocol.TinyProtocol;
import com.viaversion.viaversion.api.Via;
import de.steamwar.sql.BauweltMember;
import de.steamwar.sql.internal.Statement;
import io.netty.channel.ChannelFuture;
import org.bukkit.Bukkit;
@@ -94,6 +93,7 @@ public class CheckpointUtils {
private static final Reflection.FieldAccessor<List> channelFutures = Reflection.getField(TinyProtocol.serverConnection, List.class, 0, ChannelFuture.class);
private static final Reflection.MethodInvoker 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();
@@ -141,7 +141,7 @@ public class CheckpointUtils {
}
Via.getManager().getInjector().inject();
BauweltMember.clear();
Bukkit.getPluginManager().callEvent(new CRIUWakeupEvent());
Core.getInstance().getLogger().log(Level.INFO, "Checkpoint restored");
}
}
@@ -130,7 +130,6 @@ USAGE_ALERT=§8/§7alert §8[§emessage§8]
USAGE_IGNORE=§8/§7ignore §8[§eplayer§8]
#ModListener
CLIENT_DISALLOWED=Attempted use of client {0}
MOD_RED_SING=Attempted use of mod {0}
MOD_RED_PLUR=Attempted use of mods:\n{0}
MOD_YELLOW_SING=§7Deactivate the mod §e{0}§7 to continue playing on §eSteam§8War§7.
@@ -115,7 +115,6 @@ USAGE_ALERT=§8/§7alert §8[§eNachricht§8]
USAGE_IGNORE=§8/§7ignore §8[§eSpieler§8]
#ModListener
CLIENT_DISALLOWED=Versuchte Benutzung des Clients {0}
MOD_RED_SING=Versuchte Benutzung des Mods {0}
MOD_RED_PLUR=Versuchte Benutzung der Mods:\n{0}
MOD_YELLOW_SING=§7Deaktiviere den Mod §e{0}§7, um weiter auf §eSteam§8War §7spielen zu können.
@@ -22,9 +22,12 @@ package de.steamwar.velocitycore.listeners;
import com.lunarclient.apollo.ApolloManager;
import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.connection.PluginMessageEvent;
import com.velocitypowered.api.event.player.PlayerChannelRegisterEvent;
import com.velocitypowered.api.event.player.PlayerClientBrandEvent;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ServerConnection;
import com.velocitypowered.api.proxy.messages.ChannelIdentifier;
import com.velocitypowered.api.proxy.messages.ChannelMessageSource;
import com.velocitypowered.api.proxy.messages.LegacyChannelIdentifier;
import com.velocitypowered.api.proxy.messages.MinecraftChannelIdentifier;
@@ -373,11 +376,11 @@ public class PluginMessage extends BasicListener {
))
register(channel, false, directional(UNKNOWN, DROP));
register("REGISTER", false, directional(this::serverRegistersChannel, this::clientRegistersChannel));
register("minecraft:register", false, directional(this::serverRegistersChannel, this::clientRegistersChannel));
register("REGISTER", false, directional(this::serverRegistersChannel, UNKNOWN));
register("minecraft:register", false, directional(this::serverRegistersChannel, UNKNOWN));
register("MC|Brand", false, directional(this::steamWarBrand, this::userBrand));
register("minecraft:brand", false, directional(this::steamWarBrand, this::userBrand));
register("MC|Brand", false, directional(this::steamWarBrand, UNKNOWN));
register("minecraft:brand", false, directional(this::steamWarBrand, UNKNOWN));
//Needs to be registered cause paper refuses to send PluginMessages on unregistered channels...
register("sw:bridge", true, directional(onlySWSource(async(event -> NetworkPacket.handle(new ServerMetaInfo((ServerConnection) event.getSource()), event.getData()))), UNKNOWN));
@@ -401,6 +404,15 @@ public class PluginMessage extends BasicListener {
// Hackclientlike modsuppressor for labymod: https://github.com/Neocraftr/LabyMod-NeoEssentials (Potentially recognizable from NO Addons/NO Mods?) https://github.com/Neocraftr/LabyMod-NeoEssentials/blob/master/src/main/java/de/neocraftr/neoessentials/utils/BytecodeMethods.java
}
@Subscribe
public void onClientChannelRegister(PlayerChannelRegisterEvent event) {
Player player = event.getPlayer();
for(ChannelIdentifier channel : event.getChannels()) {
channelRegisterHandlers.getOrDefault(channel.getId(), p -> VelocityCore.getLogger().log(Level.WARNING, () -> p.getUsername() + " registered unknown channel " + channel)).accept(player);
}
}
@Subscribe
public void onPluginMessage(PluginMessageEvent event) {
event.setResult(PluginMessageEvent.ForwardResult.handled());
@@ -412,6 +424,20 @@ public class PluginMessage extends BasicListener {
}
}
@Subscribe
public void onClientBrand(PlayerClientBrandEvent event) {
Player player = event.getPlayer();
String brand = event.getBrand();
boolean lunarclient = brand.startsWith("lunarclient:");
VelocityCore.getLogger().log(knownBrands.contains(brand) || lunarclient ? Level.INFO : Level.WARNING, () -> player.getUsername() + " joins with brand: " + brand);
if(lunarclient)
lunar.sendRestrictions(player);
if(brand.equals("badlion"))
badlion.sendRestrictions(player);
}
private void registerPassthroughToClient(String... channels) {
for(String channel : channels) {
channelRegisterHandlers.put(channel, player -> {});
@@ -437,16 +463,6 @@ public class PluginMessage extends BasicListener {
VelocityCore.getProxy().getChannelRegistrar().register(channel.indexOf(':') != -1 ? MinecraftChannelIdentifier.from(channel) : new LegacyChannelIdentifier(channel));
}
private void clientRegistersChannel(PluginMessageEvent event) {
Player player = (Player) event.getSource();
for(String channel : new String(event.getData()).split("\0")) {
channelRegisterHandlers.getOrDefault(channel, p -> VelocityCore.getLogger().log(Level.WARNING, () -> p.getUsername() + " registered unknown channel " + channel)).accept(player);
}
PASS_THROUGH.handle(event);
}
private void serverRegistersChannel(PluginMessageEvent event) {
Player player = (Player) event.getTarget();
@@ -455,22 +471,6 @@ public class PluginMessage extends BasicListener {
send(player, "REGISTER", "minecraft:register", String.join("\0", channels).getBytes());
}
private void userBrand(PluginMessageEvent event) {
Player player = (Player) event.getSource();
ByteBuf buf = Unpooled.wrappedBuffer(event.getData());
String brand = ProtocolUtils.readString(buf);
boolean lunarclient = brand.startsWith("lunarclient:");
VelocityCore.getLogger().log(knownBrands.contains(brand) || lunarclient ? Level.INFO : Level.WARNING, () -> player.getUsername() + " joins with brand: " + brand);
if(lunarclient)
lunar.sendRestrictions(player);
if(brand.equals("badlion"))
badlion.sendRestrictions(player);
PASS_THROUGH.handle(event);
}
private void steamWarBrand(PluginMessageEvent event) {
Player player = (Player) event.getTarget();
String brand = Chatter.of(player).parseToLegacy("STEAMWAR_BRAND", "Velocity", player.getCurrentServer().map(serverConnection -> serverConnection.getServerInfo().getName()).orElse(""), new String(event.getData(), 1, event.getData().length - 1));
@@ -22,39 +22,34 @@ package de.steamwar.velocitycore.mods;
import com.google.gson.JsonObject;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.messages.MinecraftChannelIdentifier;
import de.steamwar.messages.Chatter;
public class Badlion {
// https://github.com/BadlionClient/BadlionClientModAPI
private final byte[] packet;
public Badlion() { //TODO check if working or (json) modsDisallowed wrapper necessary
public Badlion() {
JsonObject disabled = new JsonObject();
disabled.addProperty("disabled", true);
JsonObject json = new JsonObject();
json.add("Clear Glass", disabled);
json.add("ClearWater", disabled);
json.add("FOV Changer", disabled);
json.add("Hitboxes", disabled);
json.add("LevelHead", disabled);
json.add("MiniMap", disabled);
json.add("MLG Cobweb", disabled);
json.add("Replay", disabled); //TODO check if ReplayMod restrictions work
json.add("Schematica", disabled);
json.add("ToggleSneak", disabled);
json.add("ToggleSprint", disabled);
json.add("TNT Time", disabled);
JsonObject modsDisallowed = new JsonObject();
modsDisallowed.add("Clear Glass", disabled);
modsDisallowed.add("ClearWater", disabled);
modsDisallowed.add("FOV Changer", disabled);
modsDisallowed.add("Hitboxes", disabled);
modsDisallowed.add("LevelHead", disabled);
modsDisallowed.add("MiniMap", disabled);
modsDisallowed.add("MLG Cobweb", disabled);
modsDisallowed.add("Replay", disabled);
modsDisallowed.add("Schematica", disabled);
modsDisallowed.add("ToggleSneak", disabled);
modsDisallowed.add("ToggleSprint", disabled);
modsDisallowed.add("TNT Time", disabled);
packet = json.toString().getBytes();
packet = modsDisallowed.toString().getBytes();
}
public void sendRestrictions(Player player) {
// TODO: Remove when Badlion is fixed, or we fixed the Badlion packet
Chatter sender = Chatter.of(player);
player.disconnect(sender.parse("CLIENT_DISALLOWED", "Badlion"));
player.sendPluginMessage(MinecraftChannelIdentifier.from("badlion:mods"), packet);
}
}