Merge branch 'main' into Schematics/1.21

# Conflicts:
#	VelocityCore/build.gradle.kts
This commit is contained in:
2024-12-21 19:29:46 +01:00
77 changed files with 990 additions and 780 deletions
@@ -20,7 +20,6 @@
package de.steamwar.bausystem.features.region;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.Permission;
import de.steamwar.bausystem.config.BauServer;
import de.steamwar.bausystem.region.GlobalRegion;
import de.steamwar.bausystem.region.Region;
@@ -31,7 +30,6 @@ import de.steamwar.bausystem.region.utils.RegionExtensionType;
import de.steamwar.bausystem.region.utils.RegionType;
import de.steamwar.bausystem.utils.PasteBuilder;
import de.steamwar.command.SWCommand;
import de.steamwar.command.TypeValidator;
import de.steamwar.linkage.Linked;
import de.steamwar.linkage.LinkedInstance;
import de.steamwar.sql.Punishment;
@@ -40,7 +38,6 @@ import de.steamwar.sql.SteamwarUser;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import java.io.IOException;
import java.util.logging.Level;
@Linked
@@ -61,7 +58,7 @@ public class ResetCommand extends SWCommand {
PasteBuilder pasteBuilder = new PasteBuilder(new PasteBuilder.FileProvider(region.getResetFile(RegionType.NORMAL)))
.color(region.getPlain(Flag.COLOR, ColorMode.class).getColor());
region.reset(pasteBuilder, RegionType.NORMAL, RegionExtensionType.NORMAL);
for (Flag value : Flag.values()) {
for (Flag value : Flag.getResetFlags()) {
region.set(value, value.getDefaultValue());
}
RegionUtils.message(region, "REGION_RESET_RESETED");
@@ -21,41 +21,40 @@ package de.steamwar.bausystem.region.flags;
import de.steamwar.bausystem.region.flags.flagvalues.*;
import de.steamwar.bausystem.shared.EnumDisplay;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.EnumSet;
import java.util.Set;
import java.util.stream.Collectors;
@Getter
@AllArgsConstructor
public enum Flag implements EnumDisplay {
COLOR("FLAG_COLOR", ColorMode.class, ColorMode.YELLOW),
TNT("FLAG_TNT", TNTMode.class, TNTMode.ONLY_TB),
FIRE("FLAG_FIRE", FireMode.class, FireMode.ALLOW),
FREEZE("FLAG_FREEZE", FreezeMode.class, FreezeMode.INACTIVE),
PROTECT("FLAG_PROTECT", ProtectMode.class, ProtectMode.ACTIVE),
ITEMS("FLAG_ITEMS", ItemMode.class, ItemMode.INACTIVE),
NO_GRAVITY("FLAG_NO_GRAVITY", NoGravityMode.class, NoGravityMode.INACTIVE),
COLOR("FLAG_COLOR", ColorMode.class, ColorMode.YELLOW, false),
TNT("FLAG_TNT", TNTMode.class, TNTMode.ONLY_TB, true),
FIRE("FLAG_FIRE", FireMode.class, FireMode.ALLOW, true),
FREEZE("FLAG_FREEZE", FreezeMode.class, FreezeMode.INACTIVE, true),
PROTECT("FLAG_PROTECT", ProtectMode.class, ProtectMode.ACTIVE, true),
ITEMS("FLAG_ITEMS", ItemMode.class, ItemMode.INACTIVE, true),
NO_GRAVITY("FLAG_NO_GRAVITY", NoGravityMode.class, NoGravityMode.INACTIVE, true),
;
@Getter
private static final Set<Flag> flags;
@Getter
private static final Set<Flag> resetFlags;
static {
flags = EnumSet.allOf(Flag.class);
resetFlags = flags.stream().filter(flag -> flag.reset).collect(Collectors.toUnmodifiableSet());
}
private final String chatValue;
private final Class<? extends Value<?>> valueType;
private final Flag.Value<?> defaultValue;
private final Value<?>[] values;
<T extends Enum<T> & Value<T>> Flag(String chatValue, final Class<? extends Value<T>> valueType, final Flag.Value<T> defaultValue) {
this.chatValue = chatValue;
this.valueType = valueType;
this.defaultValue = defaultValue;
this.values = defaultValue.getValues();
}
private final boolean reset;
public Value<?> getFlagValueOf(final String name) {
return this.defaultValue.getValueOf(name);
@@ -43,7 +43,7 @@ public class EventFight implements Comparable<EventFight> {
private static final Statement setResult = table.update(Table.PRIMARY, "Ergebnis");
private static final Statement setFight = table.update(Table.PRIMARY, "Fight");
private static final Statement create = table.insertAll(true);
private static final Statement create = table.insertFields(true, "eventID", "startTime", "spielmodus", "map", "teamBlue", "teamRed", "spectatePort");
private static final Statement update = table.update(Table.PRIMARY, "startTime", "spielModus", "map", "teamBlue", "teamRed", "spectatePort");
private static final Statement delete = table.delete(Table.PRIMARY);
@@ -26,6 +26,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import java.util.Map;
@@ -72,16 +73,16 @@ public class BlockIdWrapper14 implements BlockIdWrapper {
private static final Class<?> entityTracker = Reflection.getClass("{nms.server.level}.PlayerChunkMap$EntityTracker");
private static final Reflection.MethodInvoker updatePlayer = Reflection.getMethod(entityTracker, Core.getVersion() > 15 ? "b" : "updatePlayer", entityPlayer);
@Override
public void trackEntity(Player player, int entity) {
Object tracker = trackers.get(entity);
public void trackEntity(Player player, Entity entity) {
Object tracker = trackers.get(entity.getEntityId());
if(tracker != null)
updatePlayer.invoke(tracker, getPlayer.invoke(player));
}
private static final Reflection.MethodInvoker clearPlayer = Reflection.getMethod(entityTracker, Core.getVersion() > 15 ? "a" : "clear", entityPlayer);
@Override
public void untrackEntity(Player player, int entity) {
Object tracker = trackers.get(entity);
public void untrackEntity(Player player, Entity entity) {
Object tracker = trackers.get(entity.getEntityId());
if(tracker != null)
clearPlayer.invoke(tracker, getPlayer.invoke(player));
}
@@ -24,6 +24,7 @@ plugins {
dependencies {
compileOnly(project(":SpigotCore", "default"))
compileOnly(project(":FightSystem:FightSystem_Core", "default"))
compileOnly(project(":FightSystem:FightSystem_14", "default"))
compileOnly(libs.spigotapi)
@@ -0,0 +1,42 @@
/*
* 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.fightsystem.utils;
import com.comphenix.tinyprotocol.Reflection;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import java.util.*;
public class BlockIdWrapper18 extends BlockIdWrapper14 {
private static final Reflection.FieldAccessor<Map> hiddenEntities = Reflection.getField(Reflection.getClass("{obc}.entity.CraftPlayer"), Map.class, 0, UUID.class, Set.class);
@Override
public void trackEntity(Player player, Entity entity) {
hiddenEntities.get(player).remove(entity.getUniqueId());
super.trackEntity(player, entity);
}
@Override
public void untrackEntity(Player player, Entity entity) {
hiddenEntities.get(player).put(entity.getUniqueId(), new HashSet<>(1));
super.untrackEntity(player, entity);
}
}
@@ -24,6 +24,7 @@ import de.steamwar.fightsystem.Config;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
public class BlockIdWrapper8 implements BlockIdWrapper {
@@ -57,16 +58,16 @@ public class BlockIdWrapper8 implements BlockIdWrapper {
private static final Reflection.MethodInvoker get = Reflection.getTypedMethod(intHashMap, "get", Object.class, int.class);
private static final Reflection.MethodInvoker updatePlayer = Reflection.getMethod(entityTrackerEntry, "updatePlayer", entityPlayer);
@Override
public void trackEntity(Player player, int entity) {
Object tracker = get.invoke(trackers, entity);
public void trackEntity(Player player, Entity entity) {
Object tracker = get.invoke(trackers, entity.getEntityId());
if(tracker != null)
updatePlayer.invoke(tracker, getPlayer.invoke(player));
}
private static final Reflection.MethodInvoker clearPlayer = Reflection.getMethod(entityTrackerEntry, "a", entityPlayer);
@Override
public void untrackEntity(Player player, int entity) {
Object tracker = get.invoke(trackers, entity);
public void untrackEntity(Player player, Entity entity) {
Object tracker = get.invoke(trackers, entity.getEntityId());
if(tracker != null)
clearPlayer.invoke(tracker, getPlayer.invoke(player));
}
@@ -83,7 +83,7 @@ public class Permanent implements Listener {
@EventHandler
public void onTpGM3(PlayerTeleportEvent e) {
if (e.getCause() == PlayerTeleportEvent.TeleportCause.SPECTATE) {
if (ArenaMode.AntiTest.contains(Config.mode) && e.getCause() == PlayerTeleportEvent.TeleportCause.SPECTATE) {
e.setCancelled(true);
FightSystem.getMessage().sendPrefixless("NO_TELEPORT", e.getPlayer(), ChatMessageType.ACTION_BAR);
e.getPlayer().kickPlayer(null);
@@ -26,6 +26,7 @@ import de.steamwar.core.WorldEditWrapper;
import de.steamwar.entity.REntity;
import de.steamwar.entity.REntityServer;
import de.steamwar.entity.RPlayer;
import de.steamwar.fightsystem.ArenaMode;
import de.steamwar.fightsystem.Config;
import de.steamwar.fightsystem.FightSystem;
import de.steamwar.fightsystem.countdown.Countdown;
@@ -244,6 +245,9 @@ public class PacketProcessor implements Listener {
SteamwarUser user = SteamwarUser.get(userId);
addREntity(entityId, new RPlayer(entityServer, user.getUUID(), user.getUserName(), Config.SpecSpawn));
team.addEntry(user.getUserName());
if(ArenaMode.Test.contains(Config.mode))
entities.get(entityId).setGlowing(true);
});
}
@@ -25,6 +25,7 @@ import de.steamwar.fightsystem.FightSystem;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
public interface BlockIdWrapper {
@@ -41,6 +42,6 @@ public interface BlockIdWrapper {
int blockToId(Block block);
void setBlock(World world, int x, int y, int z, int blockState);
void trackEntity(Player player, int entity);
void untrackEntity(Player player, int entity);
void trackEntity(Player player, Entity entity);
void untrackEntity(Player player, Entity entity);
}
@@ -35,24 +35,28 @@ import org.bukkit.entity.Player;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.logging.Level;
import java.util.stream.IntStream;
public class Hull {
private static final IntVector[] NO_BRANCHES = new IntVector[0];
private static boolean isOccluding(Material material) {
return material.isOccluding() || Config.HiddenBlocks.contains(material);
}
private final Region region;
private final boolean groundVisible;
private final IntVector[] directions;
private final BitSet occluding;
private final BitSet visibility;
private final Map<IntVector, Map<IntVector, BitSet>> blockVisibility = new HashMap<>();
private final Set<IntVector> uncoveredSurface = new HashSet<>();
private final HashMap<IntVector, BitSet> visibilityDirections = new HashMap<>(); // Contains the visible directions of each occluding visible block
private final HashSet<IntVector> uncoveredSurface = new HashSet<>();
private final HashSet<Player> players = new HashSet<>();
private final Set<Entity> entities = new HashSet<>();
private final Set<REntity> rentities = new HashSet<>();
private final HashSet<Entity> entities = new HashSet<>();
private final HashSet<REntity> rentities = new HashSet<>();
public Hull(FightTeam team) {
this.region = team.getSchemRegion();
@@ -60,38 +64,14 @@ public class Hull {
this.occluding = new BitSet(region.volume());
this.visibility = new BitSet(region.volume());
IntVector[] directions;
if (groundVisible) {
directions = new IntVector[]{
new IntVector(1, 0, 0),
new IntVector(-1, 0, 0),
new IntVector(0, 1, 0),
new IntVector(0, -1, 0),
new IntVector(0, 0, 1),
new IntVector(0, 0, -1)
};
} else {
directions = new IntVector[]{
new IntVector(1, 0, 0),
new IntVector(-1, 0, 0),
new IntVector(0, -1, 0),
new IntVector(0, 0, 1),
new IntVector(0, 0, -1)
};
}
IntVector primaryDirection = new IntVector(0, 0, team.isBlue() == (Config.BlueToRedZ > 0) ? -1 : 1);
directions = IntStream.range(0, 27)
.mapToObj(v -> new IntVector(v%3 -1, (v/3)%3 -1, v/9 -1))
.filter(v -> v.sqLength() == 1 || v.x*primaryDirection.x + v.y*primaryDirection.y + v.z*primaryDirection.z == 1) // Not pointing away from primary direction
.toArray(IntVector[]::new);
// Generate quadrants for each direction
for (IntVector direction : directions) {
Map<IntVector, BitSet> map = new HashMap<>();
for (int z = (direction.z == 0 ? -1 : 0); z <= 1; z += 2) {
for (int y = (direction.y == 0 ? -1 : 0); y <= 1; y += 2) {
for (int x = (direction.x == 0 ? -1 : 0); x <= 1; x += 2) {
map.put(new IntVector(x, y, z), new BitSet(region.volume()));
}
}
}
blockVisibility.put(direction, map);
}
for(IntVector direction : directions)
visibilityDirections.put(direction, new BitSet(region.volume()));
}
public boolean blockPrecise(Player player, int chunkX, int chunkY, int chunkZ) {
@@ -109,29 +89,29 @@ public class Hull {
public void addPlayer(Player player) {
if(players.add(player)) {
for(Entity entity : entities)
BlockIdWrapper.impl.untrackEntity(player, entity.getEntityId());
BlockIdWrapper.impl.untrackEntity(player, entity);
}
}
public void removePlayer(Player player, boolean activeRemoval) {
if(players.remove(player) && activeRemoval) {
for(Entity entity : entities)
BlockIdWrapper.impl.trackEntity(player, entity.getEntityId());
BlockIdWrapper.impl.trackEntity(player, entity);
// techhider triggers block change sending
}
}
public void checkEntity(Entity entity) {
Location location = entity.getLocation();
if(region.inRegion(location) && !visibility.get(new IntVector(location).toId(region))) { //TODO more precise
if(region.inRegion(location) && !visibility.get(new IntVector(location).toId(region))) {
if(entities.add(entity)) {
for(Player player : players)
BlockIdWrapper.impl.untrackEntity(player, entity.getEntityId());
BlockIdWrapper.impl.untrackEntity(player, entity);
}
} else {
if(entities.remove(entity)) {
for(Player player : players)
BlockIdWrapper.impl.trackEntity(player, entity.getEntityId());
BlockIdWrapper.impl.trackEntity(player, entity);
}
}
}
@@ -142,7 +122,7 @@ public class Hull {
public void checkREntity(REntity entity) {
Location location = new Location(Config.world, entity.getX(), entity.getY(), entity.getZ());
if(region.inRegion(location) && !visibility.get(new IntVector(location).toId(region))) { //TODO more precise
if(region.inRegion(location) && !visibility.get(new IntVector(location).toId(region))) {
if(rentities.add(entity))
entity.hide(true);
} else {
@@ -159,10 +139,8 @@ public class Hull {
visibility.clear();
occluding.clear();
uncoveredSurface.clear();
for (Map<IntVector, BitSet> direction : blockVisibility.values()) {
for (BitSet set : direction.values())
set.clear();
}
for(BitSet directionalVisibility : visibilityDirections.values())
directionalVisibility.clear();
long start = System.currentTimeMillis();
region.forEach((x, y, z) -> {
@@ -170,11 +148,7 @@ public class Hull {
if (isOccluding(Config.world.getBlockAt(x, y, z).getType()))
occluding.set(block.toId(region));
});
forEachBorder((root, direction) -> {
for (Map.Entry<IntVector, BitSet> quadrant : blockVisibility.get(direction).entrySet()) {
checkBlock(new NullList<>(), root, direction, quadrant.getKey(), quadrant.getValue());
}
});
forEachBorder((root, direction) -> uncoverBlocks(new NullList<>(), root, direction));
FightSystem.getPlugin().getLogger().log(Level.INFO, () -> "[HullHider] initialisation finished: " + (System.currentTimeMillis() - start) + " ms, visible blocks: " + visibility.cardinality());
}
@@ -187,41 +161,19 @@ public class Hull {
if (!occluding.get(id) || isOccluding(changedType))
return;
List<IntVector> uncovered = new ArrayList<>();
occluding.clear(id);
for (Map.Entry<IntVector, Map<IntVector, BitSet>> direction : blockVisibility.entrySet()) {
for (Map.Entry<IntVector, BitSet> quadrant : direction.getValue().entrySet()) {
if (quadrant.getValue().get(id)) {
quadrant.getValue().clear(id);
checkBlock(uncovered, root, direction.getKey(), quadrant.getKey(), quadrant.getValue());
}
}
}
if(uncovered.isEmpty())
if(!visibility.get(id))
return;
Set<IntVector> uncoveredSet = new HashSet<>(uncovered);
Iterator<Entity> it = entities.iterator();
while(it.hasNext()) {
Entity entity = it.next();
if(uncoveredSet.contains(new IntVector(entity.getLocation()))) { //TODO more precise
it.remove();
for(Player player : players)
BlockIdWrapper.impl.trackEntity(player, entity.getEntityId());
List<IntVector> uncovered = new ArrayList<>();
for(Map.Entry<IntVector, BitSet> directionalVisibility : visibilityDirections.entrySet()) {
if(directionalVisibility.getValue().get(id)) {
directionalVisibility.getValue().clear(id);
uncoverBlocks(uncovered, root, directionalVisibility.getKey());
}
}
Iterator<REntity> rit = rentities.iterator();
while(rit.hasNext()) {
REntity entity = rit.next();
if(uncoveredSet.contains(new IntVector(new Location(Config.world, entity.getX(), entity.getY(), entity.getZ())))) { //TODO more precise
rit.remove();
entity.hide(false);
}
}
uncoveredSurface.addAll(uncoveredSet);
uncoveredSurface.addAll(new HashSet<>(uncovered));
uncoveredSurface.remove(root);
}
@@ -266,15 +218,26 @@ public class Hull {
}
}
private void checkBlock(List<IntVector> uncovered, IntVector block, IntVector direction, IntVector quadrant, BitSet quadVisibility) {
private void uncoverBlocks(List<IntVector> uncovered, IntVector block, IntVector direction) {
uncoverBlocks(
uncovered, block, direction, visibilityDirections.get(direction),
direction.sqLength() == 1
? Arrays.stream(directions)
.filter(v -> v.sqLength() >= 2 && v.x*direction.x + v.y*direction.y + v.z*direction.z == 1)
.toArray(IntVector[]::new)
: NO_BRANCHES
);
}
private void uncoverBlocks(List<IntVector> uncovered, IntVector block, IntVector direction, BitSet directionalVisibility, IntVector[] branchDirections) {
if (block.notInRegion(region))
return;
int id = block.toId(region);
if (quadVisibility.get(id))
if(directionalVisibility.get(id))
return;
directionalVisibility.set(id);
quadVisibility.set(id);
if (!visibility.get(id)) {
visibility.set(id);
uncovered.add(block);
@@ -283,31 +246,9 @@ public class Hull {
if (occluding.get(id))
return;
IntVector neighbour = block.add(direction);
checkBlock(uncovered, neighbour, direction, quadrant, quadVisibility);
boolean neigbourTransparent = boundedNonOccluding(neighbour);
boolean diagonalReachable = false;
if (direction.x == 0 && (neigbourTransparent || boundedNonOccluding(block.add(quadrant.x, 0, 0)))) {
checkBlock(uncovered, neighbour.add(quadrant.x, 0, 0), direction, quadrant, quadVisibility);
diagonalReachable = boundedNonOccluding(neighbour.add(quadrant.x, 0, 0));
}
if (direction.y == 0 && (neigbourTransparent || boundedNonOccluding(block.add(0, quadrant.y, 0)))) {
checkBlock(uncovered, neighbour.add(0, quadrant.y, 0), direction, quadrant, quadVisibility);
diagonalReachable = diagonalReachable || boundedNonOccluding(neighbour.add(0, quadrant.y, 0));
}
if (direction.z == 0 && (neigbourTransparent || boundedNonOccluding(block.add(0, 0, quadrant.z)))) {
checkBlock(uncovered, neighbour.add(0, 0, quadrant.z), direction, quadrant, quadVisibility);
diagonalReachable = diagonalReachable || boundedNonOccluding(neighbour.add(0, 0, quadrant.z));
}
if (diagonalReachable)
checkBlock(uncovered, neighbour.add(quadrant), direction, quadrant, quadVisibility);
}
private boolean boundedNonOccluding(IntVector block) {
return !(block.notInRegion(region) || occluding.get(block.toId(region)));
uncoverBlocks(uncovered, block.add(direction), direction, directionalVisibility, branchDirections);
for(IntVector branchDirection : branchDirections)
uncoverBlocks(uncovered, block.add(branchDirection), branchDirection, visibilityDirections.get(branchDirection), NO_BRANCHES);
}
@@ -340,6 +281,10 @@ public class Hull {
return add(v.x, v.y, v.z);
}
public int sqLength() {
return x*x + y*y + z*z;
}
@Override
public int hashCode() {
return y << 24 ^ x << 12 ^ z;
+2
View File
@@ -32,4 +32,6 @@ tasks.shadowJar {
dependencies {
compileOnly(libs.paperapi21)
compileOnly(libs.nms21)
compileOnly(project(":SpigotCore"))
}
@@ -32,6 +32,7 @@ class KotlinCore : JavaPlugin() {
}
override fun onEnable() {
}
override fun onDisable() {
@@ -1,4 +1,23 @@
package de.steamwar.tntleague.inventory
/*
* 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.kotlin.inventory
import org.bukkit.event.inventory.InventoryClickEvent
import org.bukkit.event.inventory.InventoryCloseEvent
@@ -1,4 +1,23 @@
package de.steamwar.tntleague.util
/*
* 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.kotlin.util
import org.bukkit.Location
import org.bukkit.block.Block
@@ -82,7 +82,8 @@ UTIL_LOAD_ERROR=§cThe schematic could not be loaded
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:
UTIL_TYPE_PUNISHED=§cYou are not allowed to submit schematics: §f§l{0}
UTIL_TYPE_PUNISHED=§cYou are not allowed to submit schematics until §e{1}§7: §f§l{0}
UTIL_TYPE_PUNISHED_PERMA=§cYou are permanently prohibited from submitting schematics: §f§l{0}
UTIL_TYPE_NOT_OWN=§cYou can only submit your own schematics
UTIL_TYPE_DIR=§cYou cannot submit folders
UTIL_TYPE_NOT_ASSIGNABLE=§cSchematics cannot be changed for this type
@@ -90,6 +91,7 @@ UTIL_TYPE_ALREADY=§cThe Schematic already has this type
UTIL_TYPE_DONE=§aChange schematic type
UTIL_TYPE_FIGHT_ALREADY=§cYou have already submitted this schematic
UTIL_TYPE_AFTER_DEADLINE=§cSchematics of this type can no longer be submitted. Deadline was: {0}
UTIL_TYPE_TOO_MANY=§cYou have sent in too many Schematics
UTIL_TYPE_ERROR=§cThe Schematic is not compliant with the rules
UTIL_TYPE_EXTEND=§aThe preparation server is starting
UTIL_SUBMIT_TITLE=Extend Schematic
@@ -69,7 +69,8 @@ UTIL_LOAD_ERROR=§cDie Schematic konnte nicht geladen werden
UTIL_DOWNLOAD_PUNISHED=§cDu darf keine Schematics Downloaden: §f§l{0}
UTIL_DOWNLOAD_NOT_OWN=§cDu darfst nur deine eigenen Schematics herunterladen
UTIL_DOWNLOAD_LINK=Dein Download Link:
UTIL_TYPE_PUNISHED=§cDu darf keine Schematics einsenden: §f§l{0}
UTIL_TYPE_PUNISHED=§cDu darfst bis zum §e{1} §7keine Schematics einsenden: §f§l{0}
UTIL_TYPE_PUNISHED_PERMA=§cDu darfst keine Schematics mehr einsenden: §f§l{0}
UTIL_TYPE_NOT_OWN=§cDu kannst nur deine eigenen Schematics einsenden
UTIL_TYPE_DIR=§cDu kannst keine Ordner einsenden
UTIL_TYPE_NOT_ASSIGNABLE=§cZu diesem Typen können keine Schematics geändert werden
@@ -77,6 +78,7 @@ UTIL_TYPE_ALREADY=§cDie Schematic hat schon diesen Typen
UTIL_TYPE_DONE=§aSchematictyp geändert
UTIL_TYPE_FIGHT_ALREADY=§cDu hast diese Schematic bereits eingesendet
UTIL_TYPE_AFTER_DEADLINE=§cVon diesem Typen können keine Schematics mehr eingesendet werden. Einsendeschluss war: {0}
UTIL_TYPE_TOO_MANY=§cDu hast zu viele Schematics eingesendet
UTIL_TYPE_ERROR=§cDie Schematic ist nicht regelkonform
UTIL_TYPE_EXTEND=§aDer Vorbereitungsserver wird gestartet
UTIL_SUBMIT_TITLE=Schematic ausfahren
@@ -401,11 +401,6 @@ public class SchematicCommandUtils {
public static void changeType(Player player, SchematicNode node, SchematicType type, SchematicCommand.Extend extend) {
SteamwarUser user = getUser(player);
if (Punishment.isPunished(user,
Punishment.PunishmentType.NoSchemSubmitting,
punishment -> SchematicSystem.MESSAGE.send("UTIL_TYPE_PUNISHED", player, punishment.getReason()))) {
return;
}
if (node.getOwner() != user.getId()) {
SchematicSystem.MESSAGE.send("UTIL_TYPE_NOT_OWN", player);
return;
@@ -430,11 +425,26 @@ public class SchematicCommandUtils {
node.setSchemtype(type);
SchematicSystem.MESSAGE.send("UTIL_TYPE_DONE", player);
} else if (type.fightType()) {
if (Punishment.isPunished(user,
Punishment.PunishmentType.NoSchemSubmitting,
punishment -> SchematicSystem.MESSAGE.send(punishment.isPerma() ? "UTIL_TYPE_PUNISHED_PERMA" : "UTIL_TYPE_PUNISHED", player, punishment.getReason(), punishment.getEndTime()))) {
return;
}
if (node.getSchemtype().check()) {
SchematicSystem.MESSAGE.send("UTIL_TYPE_FIGHT_ALREADY", player);
return;
}
if (SchematicType.values().stream().filter(SchematicType::check)
.map(schematicType -> SchematicNode.getAllSchematicsOfType(user.getId(), schematicType.toDB()))
.map(List::size)
.reduce(Integer::sum)
.orElse(0) >= 3) {
SchematicSystem.MESSAGE.send("UTIL_TYPE_TOO_MANY", player);
return;
}
CheckSchemType checkSchemType = CheckSchemType.get(type);
if (checkSchemType.isAfterDeadline()) {
SchematicSystem.MESSAGE.send("UTIL_TYPE_AFTER_DEADLINE", player, checkSchemType.getDeadline());
+19
View File
@@ -1,3 +1,22 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2024 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
plugins {
steamwar.kotlin
}
@@ -1,19 +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.tntleague
import de.steamwar.message.Message
import de.steamwar.tntleague.command.AcceptCommand
import de.steamwar.tntleague.command.InviteCommand
import de.steamwar.tntleague.command.LeaveCommand
import de.steamwar.tntleague.command.RemoveCommand
import de.steamwar.tntleague.events.GlobalListener
import de.steamwar.tntleague.events.LobbyListener
import net.kyori.adventure.key.Key
import net.kyori.adventure.translation.GlobalTranslator
import net.kyori.adventure.translation.TranslationRegistry
import net.kyori.adventure.util.UTF8ResourceBundleControl
import de.steamwar.tntleague.game.TNTLeagueTeam
import org.bukkit.plugin.java.JavaPlugin
import java.util.*
lateinit var plugin: TNTLeague
lateinit var message: Message
class TNTLeague : JavaPlugin() {
init {
@@ -21,19 +38,7 @@ class TNTLeague : JavaPlugin() {
}
override fun onEnable() {
saveResource("config.yml", false)
saveDefaultConfig()
val registry = TranslationRegistry.create(Key.key("steamwar:tntleague"))
val bundleDe = ResourceBundle.getBundle("de.steamwar.tntleague.TNTLeague", Locale.GERMAN, UTF8ResourceBundleControl())
val bundleEn = ResourceBundle.getBundle("de.steamwar.tntleague.TNTLeague", Locale.US, UTF8ResourceBundleControl())
registry.defaultLocale(Locale.US)
registry.registerAll(Locale.GERMAN, bundleDe, true)
registry.registerAll(Locale.US, bundleEn, true)
GlobalTranslator.translator().addSource(registry)
message = Message("de.steamwar.tntleague.TNTLeague", classLoader)
server.pluginManager.registerEvents(LobbyListener, this)
server.pluginManager.registerEvents(GlobalListener, this)
@@ -46,3 +51,8 @@ class TNTLeague : JavaPlugin() {
LeaveCommand.register()
}
}
fun String.colorByTeam(team: TNTLeagueTeam?) = when (team) {
null -> "§7${this}"
else -> "§${team.color}${this}"
}
@@ -0,0 +1,49 @@
#
# 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/>.
#
PREFIX=§eTNT§7League§8»
JOIN=§e{0} §7joined the game!
JOIN_TEAM={0} §7joined the {1} §7team!
QUIT={0} §7left the game!
QUIT_TEAM={0} §7left the {1} §7team!
BLUE=Blue
RED=Red
SHUTDOWN=§7The server stops in §e{0} §7seconds!
TEAM_WIN=§aTeam {0} §awins!
NOT_ENOUGH_COINS=§cYou don't have enough coins to buy this item!
GAME_STARTING=§aThe game starts in §e{0} §aseconds!
GAME_START=
GAME_STARTED=§aThe game has started!
TIME_REMAINING=§e{0} §7minutes remaining!
GAME_ENDED=§cThe game has ended!
DRAW=§cThe game ended in a draw!
DEALER=Shopkeeper
DEALER_ITEM={0} {1}
DEALER_PRICE=
SCOREBOARD_TARGET=
SCOREBOARD_TIME=§7Time§8: §e{0}§8:§e{1}
SCOREBOARD_COINS=§7Coins§8: §e{0}
SCOREBOARD_TEAM=§7Team {0}§8: §e{1}
READY=§aReady
NOT_READY=§cNot ready
IS_READY=§aTeam {0} §ais ready!
IS_NOT_READY=§cTeam {0} §cis not ready!
INVITED={0} §ainvited you to join team {1}§7! *Click*
INVITED_HOVER=§7Click to join team {0}§7!
INVITED_PLAYER=§aInvited §e{0} §ato join your team!
@@ -0,0 +1,44 @@
#
# 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/>.
#
JOIN=§e{0} §7ist dem Spiel beigetreten!
JOIN_TEAM={0} §7ist Team {1} §7begetreten!
QUIT={0} §7hat das Spiel verlassen!
QUIT_TEAM={0} §7hat Team {1} §7verlassen!
BLUE=Blau
RED=Rot
SHUTDOWN=§7Der Server fährt in §e{0} §7Sekunden herunter!
TEAM_WIN=§aTeam {0} §agewinnt!
NOT_ENOUGH_COINS=§cDu hast nicht genug Coins, um dir das zu kaufen!
GAME_STARTING=§aDas Spiel beginnt in §e{0} §aSekunden!
GAME_STARTED=§aDas Spiel beginnt!
TIME_REMAINING=§7noch §e{0} §7Minuten!
GAME_ENDED=§cDas Spiel ist vorbei!
DRAW=§cKeiner hat gewonnen!
DEALER=Händler
DEALER_PRICE=§7Kosten: §e{0} Coins
SCOREBOARD_TARGET=§7Ziel§8: {0}
SCOREBOARD_TIME=§7Zeit§8: §e{0}§8:§e{1}
READY=§aBereit
NOT_READY=§cNicht bereit
IS_READY=§aTeam {0} §aist bereit!
IS_NOT_READY=§cTeam {0} §cist nicht bereit!
INVITED={0} §ahat dich in Team {1} §aeingeladen! *Klick*
INVITED_HOVER=§7Team {0} §7beitreten!
INVITED_PLAYER={0} §awurde eingeladen!
@@ -1,18 +0,0 @@
join={0} ist dem Spiel beigetreten!
joinTeam={0} ist dem {1} team begetreten!
quit={0} hat das Spiel verlassen!
blue=Blau
red=Rot
shutdown=Der Server fährt in {0} sekunden herunter!
teamWin=Team {0} gewinnt!
notEnoughCoins=Du hast nicht genug Coins um dir das zu kaufen!
gameStarting=Das Spiel beginnt in {0} Sekunden!
gameStart=Start in {0}
gameStarted=Das Spiel beginnt!
gameEnded=Das Spiel ist aus!
dealer=Händler
dealerItem=
dealerPrice=Kosten: {0} Coins
scoreboardTarget=Ziel: {0}
scoreboardTime=Zeit: {0}:{1}
scoreboardTeam=
@@ -1,37 +0,0 @@
join={0} joined the game!
joinTeam={0} joined the {1} team!
quit={0} left the game!
quitTeam={0} left the {1} team!
blue=Blue
red=Red
shutdown=The server stops in {0} seconds!
teamWin=Team {0} wins!
notEnoughCoins=You don't have enough coins to buy this item!
gameStarting=The game starts in {0} seconds!
gameStart=Starting in {0}
gameStarted=The game has started!
timeRemaining={0} minutes remaining!
gameEnded=The game has ended!
draw=The game ended in a draw!
chat={0}» {1}
dealer=Shopkeeper
dealerItem={0} {1}
dealerPrice=Price: {0} Coins
scoreboardTarget=Target: {0}
scoreboardTime=Time: {0}:{1}
scoreboardTeam=Team {0}: {1}
ready=Ready
notReady=Not ready
isReady=Team {0} is ready!
isNotReady=Team {0} is not ready!
invited={0} invited you to join the {1} team! *Click*
invitedHover=Click to join the {0} team!
invitedPlayer=Invited {0} to join your team!
@@ -21,10 +21,10 @@ package de.steamwar.tntleague.command
import de.steamwar.command.SWCommand
import de.steamwar.command.TypeValidator
import de.steamwar.tntleague.colorByTeam
import de.steamwar.tntleague.game.TNTLeagueGame
import de.steamwar.tntleague.util.*
import net.kyori.adventure.text.event.ClickEvent
import net.kyori.adventure.text.event.HoverEvent
import de.steamwar.tntleague.message
import net.md_5.bungee.api.chat.ClickEvent
import org.bukkit.entity.Player
object InviteCommand: SWCommand("invite") {
@@ -37,20 +37,15 @@ object InviteCommand: SWCommand("invite") {
val team = TNTLeagueGame.getTeam(sender)!!
team.invites.add(target)
target.sendMessage(translate("invited", sender.name.yellow(), translate(team.name).colorByTeam(team)).basic().clickEvent(
ClickEvent.callback {
if (target !in team.invites) return@callback
message
.send("INVITED", target, message.parse("INVITED_HOVER", target, team.name.colorByTeam(team)),
ClickEvent(ClickEvent.Action.RUN_COMMAND, "/accept " + sender.name), sender.name, team.name.colorByTeam(team), )
team.invites.remove(target)
team.opposite.invites.remove(target)
team.join(target)
})
.hoverEvent(HoverEvent.showText(translate("invitedHover", translate(team.name).colorByTeam(team)).green())))
sender.sendMessage(translate("invitedPlayer", target.name.yellow()).basic())
message.send("INVITED_PLAYER", sender, target.name)
}
@Validator("isLeader", local = false)
fun isLeader(): TypeValidator<Player> {
return TypeValidator<Player> { _, player, _ -> TNTLeagueGame.getTeam(player)?.leader == player}
}
}
}
@@ -26,5 +26,5 @@ import org.bukkit.entity.Player
object LeaveCommand: SWCommand("leave", "l") {
@Register
fun leave(player: Player) = TNTLeagueGame.getTeam(player)?.remove(player)
fun leave(player: Player) = TNTLeagueGame.getTeam(player)?.remove(player) ?: Unit
}
@@ -1,3 +1,22 @@
/*
* 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.tntleague.config
import de.steamwar.tntleague.plugin
@@ -1,15 +1,35 @@
/*
* 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.tntleague.config
import de.steamwar.tntleague.plugin
import de.steamwar.tntleague.util.Area
import de.steamwar.tntleague.util.translate
import de.steamwar.kotlin.util.Area
import net.kyori.adventure.text.Component
import org.bukkit.Bukkit
import org.bukkit.Location
import org.bukkit.Material
import org.bukkit.configuration.ConfigurationSection
import org.bukkit.configuration.file.YamlConfiguration
import org.bukkit.entity.Villager
import org.bukkit.entity.WanderingTrader
import java.io.File
import kotlin.properties.Delegates
val world by lazy { plugin.server.worlds.first()!! }
@@ -33,12 +53,25 @@ object TNTLeagueWorldConfig {
)
}
val blueTeam: TeamConfig = TeamConfig.fromConfig(config.getConfigurationSection("blueTeam")!!)
val redTeam: TeamConfig = TeamConfig.fromConfig(config.getConfigurationSection("redTeam")!!)
val lobby: Location = config.getLocation("lobby", blueTeam.spawnLocation.clone().add(redTeam.spawnLocation).multiply(0.5))!!
val targetMaterial: Material = Material.matchMaterial(config.getString("targetMaterial", "IRON_BLOCK")!!)!!
val minHeight: Int = config.getInt("minHeight", 0)
val target: Int = config.getInt("target", -1)
lateinit var blueTeam: TeamConfig
lateinit var redTeam: TeamConfig
lateinit var lobby: Location
lateinit var targetMaterial: Material
var minHeight by Delegates.notNull<Int>()
var target by Delegates.notNull<Int>()
init {
try {
blueTeam = TeamConfig.fromConfig(config.getConfigurationSection("blueTeam")!!)
redTeam = TeamConfig.fromConfig(config.getConfigurationSection("redTeam")!!)
lobby = config.getWorldLocation("lobby", blueTeam.spawnLocation.clone().add(redTeam.spawnLocation).multiply(0.5))
targetMaterial = Material.matchMaterial(config.getString("targetMaterial", "IRON_BLOCK")!!)!!
minHeight = config.getInt("minHeight", 0)
target = config.getInt("target", -1)
} catch (e: NullPointerException) {
Bukkit.shutdown()
}
}
@JvmRecord
data class TeamConfig(
@@ -49,11 +82,11 @@ object TNTLeagueWorldConfig {
) {
companion object {
fun fromConfig(config: ConfigurationSection): TeamConfig {
val spawnLocation = config.getLocation("spawn")!!
val dealerSpawn = config.getLocation("dealerSpawn")!!
val itemSpawn = config.getLocation("itemSpawn")!!
val targetPos1 = config.getLocation("targetMin")!!
val targetPos2 = config.getLocation("targetMax")!!
val spawnLocation = config.getWorldLocation("spawn")
val dealerSpawn = config.getWorldLocation("dealerSpawn")
val itemSpawn = config.getWorldLocation("itemSpawn")
val targetPos1 = config.getWorldLocation("targetMin")
val targetPos2 = config.getWorldLocation("targetMax")
spawnDealer(dealerSpawn)
@@ -62,7 +95,7 @@ object TNTLeagueWorldConfig {
private fun spawnDealer(loc: Location) = world.spawn(loc, WanderingTrader::class.java)
.apply {
customName(translate("dealer"))
customName(Component.text("Shop"))
isCustomNameVisible = false
isInvulnerable = true
isSilent = true
@@ -73,3 +106,19 @@ object TNTLeagueWorldConfig {
}
}
}
fun ConfigurationSection.getWorldLocation(s: String, default: Location? = null): Location {
val section = getConfigurationSection(s) ?: return default!!
val x = section.getDouble("x")
val y = section.getDouble("y")
val z = section.getDouble("z")
val pitch = section.getDouble("pitch")
val yaw = section.getDouble("yaw")
return Location(
plugin.server.worlds.first(),
x, y, z,
yaw.toFloat(), pitch.toFloat()
)
}
@@ -21,5 +21,4 @@ package de.steamwar.tntleague.events
import org.bukkit.event.Listener
object DummyListener: Listener {
}
object DummyListener: Listener
@@ -1,18 +1,39 @@
/*
* 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.tntleague.events
import de.steamwar.tntleague.colorByTeam
import de.steamwar.tntleague.config.TNTLeagueWorldConfig
import de.steamwar.tntleague.game.TNTLeagueGame
import de.steamwar.tntleague.game.TNTLeagueTeam
import de.steamwar.tntleague.inventory.SWInventoryHolder
import de.steamwar.kotlin.inventory.SWInventoryHolder
import de.steamwar.tntleague.message
import de.steamwar.tntleague.plugin
import de.steamwar.tntleague.util.*
import io.papermc.paper.event.player.AsyncChatEvent
import org.bukkit.Bukkit
import org.bukkit.GameMode
import org.bukkit.Material
import org.bukkit.event.EventHandler
import org.bukkit.event.EventPriority
import org.bukkit.event.Listener
import org.bukkit.event.entity.PlayerDeathEvent
import org.bukkit.event.inventory.CraftItemEvent
import org.bukkit.event.inventory.InventoryClickEvent
import org.bukkit.event.player.PlayerJoinEvent
import org.bukkit.event.player.PlayerMoveEvent
@@ -27,7 +48,7 @@ object GlobalListener: Listener {
with(e.player) {
teleport(TNTLeagueWorldConfig.lobby)
inventory.clear()
plugin.server.broadcast(translate("join", name.bold()).basic())
message.broadcast("JOIN", name)
isOp = false
gameMode = GameMode.SPECTATOR
respawnLocation = TNTLeagueWorldConfig.lobby
@@ -37,8 +58,17 @@ object GlobalListener: Listener {
@EventHandler(priority = EventPriority.HIGHEST)
fun onPlayerQuit(e: PlayerQuitEvent) {
e.quitMessage(null)
plugin.server.broadcast(translate("quit", e.player.name.bold().colorByTeam(TNTLeagueGame.getTeam(e.player))).basic())
message.broadcast("QUIT", e.player.name.colorByTeam(TNTLeagueGame.getTeam(e.player)))
TNTLeagueGame.playerLeave(e.player)
if (plugin.server.onlinePlayers.size == 1 && plugin.server.onlinePlayers.first() == e.player) {
plugin.server.shutdown()
}
}
@EventHandler
fun onPlayerCraft(e: CraftItemEvent) {
e.isCancelled = true
}
@EventHandler(priority = EventPriority.LOWEST)
@@ -67,6 +97,7 @@ object GlobalListener: Listener {
fun onPlayerDeath(e: PlayerDeathEvent) {
e.deathMessage(null)
e.drops.clear()
e.keepInventory = true
e.itemsToKeep.removeIf { it.type != Material.DIAMOND_PICKAXE }
}
@@ -78,11 +109,4 @@ object GlobalListener: Listener {
null -> e.respawnLocation = TNTLeagueWorldConfig.lobby
}
}
@EventHandler
fun onChat(e: AsyncChatEvent) {
e.renderer { source, sourceDisplayName, message, _ ->
translate("chat", sourceDisplayName.colorByTeam(TNTLeagueGame.getTeam(source)), message).basic()
}
}
}
@@ -1,3 +1,22 @@
/*
* 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.tntleague.events
import de.steamwar.scoreboard.SWScoreboard
@@ -13,12 +32,11 @@ import org.bukkit.entity.EntityType
import org.bukkit.event.EventHandler
import org.bukkit.event.Listener
import org.bukkit.event.entity.EntityExplodeEvent
import org.bukkit.event.entity.PlayerDeathEvent
import org.bukkit.event.player.PlayerAttemptPickupItemEvent
import org.bukkit.event.player.PlayerDropItemEvent
import org.bukkit.event.player.PlayerInteractEntityEvent
import org.bukkit.event.player.PlayerJoinEvent
import org.bukkit.event.player.PlayerMoveEvent
import org.bukkit.event.player.PlayerQuitEvent
object IngameListener: Listener {
@@ -26,7 +44,7 @@ object IngameListener: Listener {
fun onEntityInteract(e: PlayerInteractEntityEvent) {
if (e.player.gameMode == GameMode.SPECTATOR) return
if(e.rightClicked.type == EntityType.VILLAGER) {
if(e.rightClicked.type == EntityType.WANDERING_TRADER) {
e.isCancelled = true
e.player.openInventory(DealerInventory(e.player).getInventory())
}
@@ -63,6 +81,17 @@ object IngameListener: Listener {
}
}
@EventHandler
fun onPickupCoins(e: PlayerAttemptPickupItemEvent) {
if (e.item.itemStack.isSimilar(DealerInventory.coins)) {
TNTLeagueGame.getTeam(e.player)?.coins = e.item.itemStack.amount + (TNTLeagueGame.getTeam(e.player)?.coins ?: 0)
e.item.itemStack.amount = 0
e.isCancelled = true
e.flyAtPlayer = true
}
}
private fun getTeamByTargetLocation(location: Location): TNTLeagueTeam? =
when (location) {
in TNTLeagueWorldConfig.redTeam.target -> TNTLeagueGame.redTeam
@@ -1,22 +1,33 @@
/*
* 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.tntleague.events
import de.steamwar.tntleague.game.TNTLeagueGame
import de.steamwar.tntleague.plugin
import de.steamwar.tntleague.util.basic
import de.steamwar.tntleague.util.colorByTeam
import de.steamwar.tntleague.util.translate
import de.steamwar.tntleague.util.yellow
import io.papermc.paper.util.Tick
import org.bukkit.GameMode
import org.bukkit.entity.EntityType
import org.bukkit.event.EventHandler
import org.bukkit.event.EventPriority
import org.bukkit.event.Listener
import org.bukkit.event.block.Action
import org.bukkit.event.entity.EntityDamageEvent
import org.bukkit.event.inventory.InventoryClickEvent
import org.bukkit.event.player.PlayerDropItemEvent
import org.bukkit.event.player.PlayerInteractEvent
import org.bukkit.event.player.PlayerJoinEvent
import org.bukkit.event.player.PlayerQuitEvent
import org.bukkit.event.player.*
object LobbyListener: Listener {
@@ -30,8 +41,7 @@ object LobbyListener: Listener {
@EventHandler(priority = EventPriority.LOWEST)
fun onPlayerQuit(e: PlayerQuitEvent) {
val team = TNTLeagueGame.getTeam(e.player) ?: return
team.leave(e.player)
TNTLeagueGame.playerLeave(e.player)
}
@EventHandler
@@ -58,4 +68,13 @@ object LobbyListener: Listener {
e.isCancelled = true
}
}
@EventHandler
fun onEntityInteract(e: PlayerInteractEntityEvent) {
if (e.player.gameMode == GameMode.SPECTATOR) return
if(e.rightClicked.type == EntityType.WANDERING_TRADER) {
e.isCancelled = true
}
}
}
@@ -1,9 +1,30 @@
/*
* 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.tntleague.game
import de.steamwar.kotlin.util.Area
import de.steamwar.scoreboard.SWScoreboard
import de.steamwar.sql.Fight
import de.steamwar.sql.FightPlayer
import de.steamwar.sql.SteamwarUser
import de.steamwar.tntleague.colorByTeam
import de.steamwar.tntleague.config.TNTLeagueConfig
import de.steamwar.tntleague.config.TNTLeagueWorldConfig
import de.steamwar.tntleague.config.world
@@ -11,19 +32,16 @@ import de.steamwar.tntleague.events.DummyListener
import de.steamwar.tntleague.events.IngameListener
import de.steamwar.tntleague.events.LobbyListener
import de.steamwar.tntleague.inventory.DealerInventory
import de.steamwar.tntleague.message
import de.steamwar.tntleague.plugin
import de.steamwar.tntleague.util.*
import net.kyori.adventure.bossbar.BossBar
import net.kyori.adventure.sound.Sound
import org.bukkit.GameMode
import org.bukkit.Location
import org.bukkit.Material
import org.bukkit.block.data.type.TNT
import org.bukkit.entity.Entity
import org.bukkit.Sound
import org.bukkit.entity.Item
import org.bukkit.entity.Player
import org.bukkit.entity.TNTPrimed
import org.bukkit.entity.Villager
import org.bukkit.event.HandlerList
import org.bukkit.event.Listener
import org.bukkit.inventory.ItemStack
@@ -62,7 +80,7 @@ object TNTLeagueGame {
blueTeam.start()
redTeam.start()
plugin.server.broadcast(translate("gameStarted").success())
message.broadcast("GAME_STARTED")
val tnt = ItemStack(Material.TNT)
@@ -82,13 +100,18 @@ object TNTLeagueGame {
timerTask = plugin.server.scheduler.runTaskTimer(plugin, bukkit {
gameTimeRemaining--
if (gameTimeRemaining == 0) {
draw(WinReason.TIMEOUT)
if (blueTeam.damagedBlocks > redTeam.damagedBlocks)
win(blueTeam, WinReason.TIMEOUT)
else if (redTeam.damagedBlocks > blueTeam.damagedBlocks)
win(redTeam, WinReason.TIMEOUT)
else
draw(WinReason.TIMEOUT)
return@bukkit
}
if (gameTimeRemaining % 300 == 0) {
plugin.server.broadcast(translate("timeRemaining", (gameTimeRemaining / 60).toString().yellow()).basic())
plugin.server.onlinePlayers.forEach { it.playSound(Sound.sound(org.bukkit.Sound.BLOCK_NOTE_BLOCK_PLING.key, Sound.Source.MASTER, 1f, 1f)) }
message.broadcast("TIME_REMAINING", (gameTimeRemaining / 60))
plugin.server.onlinePlayers.forEach { it.playSound(it.location, Sound.BLOCK_NOTE_BLOCK_PLING, 1f, 1f) }
}
}, 20, 20)
}
@@ -102,10 +125,10 @@ object TNTLeagueGame {
plugin.server.onlinePlayers.forEach {
it.gameMode = GameMode.SPECTATOR
SWScoreboard.impl.removeScoreboard(it)
it.playSound(Sound.sound(org.bukkit.Sound.ENTITY_ENDER_DRAGON_DEATH.key, Sound.Source.MASTER, 1f, 1f))
it.playSound(it.location, Sound.ENTITY_ENDER_DRAGON_DEATH, 1f, 1f)
}
plugin.server.broadcast(translate("gameEnded").success())
message.broadcast("GAME_ENDED")
spawnerTask.cancel()
@@ -116,7 +139,7 @@ object TNTLeagueGame {
plugin.server.shutdown()
}
plugin.server.broadcast(translate("shutdown", shutdown.toString().yellow()).basic())
message.broadcast("SHUTDOWN", shutdown)
shutdown--
}, 20, 20)
@@ -135,19 +158,15 @@ object TNTLeagueGame {
state = GameState.STARTING
var countdown = TNTLeagueConfig.config.startDelay
plugin.server.broadcast(translate("gameStarting", countdown.toString().yellow()).basic())
val bar = BossBar.bossBar(translate("gameStart", countdown.toString().yellow()).gray(), (TNTLeagueConfig.config.startDelay - countdown) / TNTLeagueConfig.config.startDelay.toFloat(), BossBar.Color.GREEN, BossBar.Overlay.NOTCHED_10)
plugin.server.onlinePlayers.forEach { bar.addViewer(it) }
message.broadcast("GAME_STARTING", countdown.toString())
task = plugin.server.scheduler.scheduleSyncRepeatingTask(plugin, {
plugin.server.onlinePlayers.forEach { it.playSound(Sound.sound(org.bukkit.Sound.ENTITY_EXPERIENCE_ORB_PICKUP.key, Sound.Source.MASTER, 1f, 1f)) }
if (countdown-- == 0) {
plugin.server.onlinePlayers.forEach { it.hideBossBar(bar) }
plugin.server.onlinePlayers.forEach { it.playSound(it.location, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1f, 1f) }
if (--countdown == 0) {
plugin.server.onlinePlayers.forEach { it.level = 0 }
task = task?.also { plugin.server.scheduler.cancelTask(it) }.let { null }
setup()
} else {
bar.name(translate("gameStart", countdown.toString().yellow()).gray())
bar.progress((TNTLeagueConfig.config.startDelay - countdown) / TNTLeagueConfig.config.startDelay.toFloat())
plugin.server.onlinePlayers.filter { !it.activeBossBars().contains(bar) }.forEach { bar.addViewer(it) }
plugin.server.onlinePlayers.forEach { it.level = countdown }
}
}, 20, 20)
@@ -161,10 +180,7 @@ object TNTLeagueGame {
blueTeam.invites.remove(player)
redTeam.invites.remove(player)
getTeam(player)?.apply {
members.remove(player)
if (leader == player) {
win(this.opposite, WinReason.LEAVE)
}
remove(player)
}
}
@@ -173,7 +189,6 @@ object TNTLeagueGame {
if (state == GameState.STARTING) {
task = task?.also { plugin.server.scheduler.cancelTask(it) }.let { null }
plugin.server.onlinePlayers.forEach { p -> p.activeBossBars().forEach { it.removeViewer(p) } }
state = GameState.LOBBY
}
}
@@ -181,16 +196,14 @@ object TNTLeagueGame {
fun win(tntLeagueTeam: TNTLeagueTeam, reason: WinReason) {
if (state != GameState.RUNNING) return
end()
plugin.server.broadcast(translate("teamWin", translate(tntLeagueTeam.name).color(tntLeagueTeam.color)).success())
statistic(tntLeagueTeam, reason)
plugin.server.onlinePlayers.forEach { message.send("TEAM_WIN", it, message.parse(tntLeagueTeam.name, it).colorByTeam(tntLeagueTeam)) }
explode(tntLeagueTeam.opposite)
}
fun draw(reason: WinReason) {
if (state != GameState.RUNNING) return
end()
plugin.server.broadcast(translate("draw").success())
statistic(null, reason)
message.broadcast("DRAW")
}
fun explode(team: TNTLeagueTeam) {
@@ -204,32 +217,6 @@ object TNTLeagueGame {
}
}
private fun statistic(winTeam: TNTLeagueTeam?, reason: WinReason) {
val fightId = Fight.create(
"TNTLeague",
world.name,
start,
TNTLeagueConfig.config.gameTime - gameTimeRemaining,
SteamwarUser.get(blueTeam.leader!!.uniqueId).id,
SteamwarUser.get(redTeam.leader!!.uniqueId).id,
null,
null,
when (winTeam) {
blueTeam -> 1
redTeam -> 2
else -> 0
},
when (reason) {
WinReason.TIMEOUT -> "TIMEOUT"
WinReason.DESTROYED -> "DESTROYED"
WinReason.LEAVE -> "LEAVE"
}
)
addTeamMember(blueTeam, fightId)
addTeamMember(redTeam, fightId)
}
private fun addTeamMember(team: TNTLeagueTeam, fightId: Int) {
team.members.filter { team.leader != it }
.forEach {
@@ -1,18 +1,38 @@
/*
* 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.tntleague.game
import de.steamwar.tntleague.colorByTeam
import de.steamwar.tntleague.config.TNTLeagueWorldConfig
import de.steamwar.tntleague.config.targetedBlocks
import de.steamwar.tntleague.game.TNTLeagueGame.WinReason
import de.steamwar.tntleague.game.TNTLeagueGame.win
import de.steamwar.tntleague.message
import de.steamwar.tntleague.plugin
import de.steamwar.tntleague.util.*
import net.kyori.adventure.sound.Sound
import net.kyori.adventure.text.format.NamedTextColor
import net.kyori.adventure.text.format.TextColor
import net.kyori.adventure.text.Component
import org.bukkit.GameMode
import org.bukkit.Material
import org.bukkit.Sound
import org.bukkit.enchantments.Enchantment
import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack
import java.awt.Color.green
data class TNTLeagueTeam(val config: TNTLeagueWorldConfig.TeamConfig, private val team: Team) {
@@ -31,24 +51,18 @@ data class TNTLeagueTeam(val config: TNTLeagueWorldConfig.TeamConfig, private va
val invites = mutableListOf<Player>()
val name: String
get() = team.name.lowercase()
get() = team.name.uppercase()
val color: TextColor
val color: Char
get() = team.color
var isReady: Boolean = false
set(value) {
field = value
leader?.inventory?.setItem(4, readyItem())
leader?.playSound(Sound.sound(org.bukkit.Sound.BLOCK_NOTE_BLOCK_PLING.key, Sound.Source.MASTER, 1f, 1f))
leader?.let { it.playSound(it.location, Sound.BLOCK_NOTE_BLOCK_PLING, 1f, 1f) }
plugin.server.onlinePlayers.forEach { it.sendActionBar(translate(if (value) "isReady" else "isNotReady", translate(this.name).colorByTeam(this)).let { cmp ->
if (value) {
cmp.green()
} else {
cmp.red()
}
}) }
message.broadcastActionbar(if (value) "IS_READY" else "IS_NOT_READY", name.colorByTeam(this))
if (value && opposite.isReady) {
TNTLeagueGame.checkStart()
@@ -63,6 +77,8 @@ data class TNTLeagueTeam(val config: TNTLeagueWorldConfig.TeamConfig, private va
}
}
var coins: Int = 0
val opposite: TNTLeagueTeam
get() = when (team) {
Team.BLUE -> TNTLeagueGame.redTeam
@@ -76,7 +92,7 @@ data class TNTLeagueTeam(val config: TNTLeagueWorldConfig.TeamConfig, private va
teleport(config.spawnLocation)
gameMode = GameMode.ADVENTURE
inventory.clear()
plugin.server.broadcast(translate("joinTeam", name().colorByTeam(this@TNTLeagueTeam), translate(this@TNTLeagueTeam.name).colorByTeam(this@TNTLeagueTeam)).basic())
message.broadcast("JOIN_TEAM", name.colorByTeam(this@TNTLeagueTeam), this@TNTLeagueTeam.name.colorByTeam(this@TNTLeagueTeam))
}
if (leader == null) {
@@ -89,13 +105,13 @@ data class TNTLeagueTeam(val config: TNTLeagueWorldConfig.TeamConfig, private va
fun readyItem() = if (isReady) {
ItemStack.of(Material.LIME_DYE).apply {
itemMeta = itemMeta.apply {
displayName(translate("ready").green().translate(leader!!))
displayName(Component.text(message.parse("READY", leader!!)))
}
}
} else {
ItemStack.of(Material.RED_DYE).apply {
itemMeta = itemMeta.apply {
displayName(translate("notReady").red().translate(leader!!))
displayName(Component.text(message.parse("NOT_READY", leader!!)))
}
}
}
@@ -113,11 +129,8 @@ data class TNTLeagueTeam(val config: TNTLeagueWorldConfig.TeamConfig, private va
}
fun leave(player: Player) {
if (TNTLeagueGame.state == TNTLeagueGame.GameState.RUNNING) {
TNTLeagueGame.playerLeave(player)
} else {
members.remove(player)
members.remove(player)
if (TNTLeagueGame.state != TNTLeagueGame.GameState.RUNNING) {
if (members.isEmpty()) {
plugin.server.onlinePlayers.firstOrNull { it != player && TNTLeagueGame.getTeam(it) == null }?.run {
members.add(this)
@@ -125,6 +138,14 @@ data class TNTLeagueTeam(val config: TNTLeagueWorldConfig.TeamConfig, private va
}
if (leader == player) {
leader = members.firstOrNull()
if (leader == null && TNTLeagueGame.state == TNTLeagueGame.GameState.LOBBY) {
isReady = false
}
}
} else if (TNTLeagueGame.state == TNTLeagueGame.GameState.RUNNING) {
if (members.isEmpty()) {
win(this.opposite, WinReason.LEAVE)
}
}
}
@@ -135,12 +156,12 @@ data class TNTLeagueTeam(val config: TNTLeagueWorldConfig.TeamConfig, private va
teleport(TNTLeagueWorldConfig.lobby)
gameMode = GameMode.SPECTATOR
inventory.clear()
plugin.server.broadcast(translate("quitTeam", name().colorByTeam(this@TNTLeagueTeam), translate(this@TNTLeagueTeam.name).colorByTeam(this@TNTLeagueTeam)).basic())
message.broadcast("QUIT_TEAM", name.colorByTeam(this@TNTLeagueTeam), this@TNTLeagueTeam.name.colorByTeam(this@TNTLeagueTeam))
}
}
enum class Team(val color: TextColor) {
BLUE(NamedTextColor.BLUE),
RED(NamedTextColor.RED);
enum class Team(val color: Char) {
BLUE('9'),
RED('c');
}
}
@@ -1,14 +1,35 @@
/*
* 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.tntleague.inventory
import de.steamwar.kotlin.inventory.SWInventoryHolder
import de.steamwar.tntleague.config.TNTLeagueConfig
import de.steamwar.tntleague.game.TNTLeagueGame
import de.steamwar.tntleague.message
import de.steamwar.tntleague.plugin
import de.steamwar.tntleague.util.*
import net.kyori.adventure.sound.Sound
import net.kyori.adventure.text.Component
import net.kyori.adventure.text.format.Style
import net.kyori.adventure.text.format.NamedTextColor
import net.kyori.adventure.text.format.TextDecoration
import org.bukkit.Material
import org.bukkit.NamespacedKey
import org.bukkit.Sound
import org.bukkit.entity.Player
import org.bukkit.inventory.Inventory
import org.bukkit.inventory.ItemStack
@@ -16,7 +37,7 @@ import org.bukkit.persistence.PersistentDataType
import java.util.*
import kotlin.math.ceil
class DealerInventory(player: Player): SWInventoryHolder() {
class DealerInventory(val player: Player): SWInventoryHolder() {
init {
items.forEachIndexed { index, item ->
@@ -24,19 +45,21 @@ class DealerInventory(player: Player): SWInventoryHolder() {
val price = item.second.price * if (it.isShiftClick) 5 else 1
val amount = item.second.amount * if (it.isShiftClick) 5 else 1
if (!player.inventory.containsAtLeast(coins, price)) {
player.sendMessage(translate("notEnoughCoins").error())
player.playSound(Sound.sound(org.bukkit.Sound.ENTITY_VILLAGER_HURT.key, net.kyori.adventure.sound.Sound.Source.MASTER, 1f, 1f))
val team = TNTLeagueGame.getTeam(player) ?: return@to
if (team.coins < price) {
message.send("NOT_ENOUGH_COINS", player)
player.playSound(player, Sound.ENTITY_VILLAGER_HURT, 1f, 1f)
return@to
}
player.inventory.removeItem(coins.asQuantity(price))
team.coins -= price
player.inventory.addItem(ItemStack.of(item.first.type, amount))
}
}
}
override fun createInventory(): Inventory = plugin.server.createInventory(this, ceil(TNTLeagueConfig.config.prices.size / 9f).toInt() * 9, translate("dealer").reset())
override fun createInventory(): Inventory = plugin.server.createInventory(this, ceil(TNTLeagueConfig.config.prices.size / 9f).toInt() * 9, Component.text(message.parse("DEALER", player)))
companion object {
private val priceKey = NamespacedKey(plugin, "price")
@@ -45,7 +68,7 @@ class DealerInventory(player: Player): SWInventoryHolder() {
val coins = ItemStack(Material.RAW_GOLD).apply {
itemMeta = itemMeta.apply {
displayName(Component.text("Coins").bold().gold())
displayName(Component.text("Coins").color(NamedTextColor.GOLD))
persistentDataContainer.apply {
set(coinKey, PersistentDataType.BOOLEAN, true)
}
@@ -58,11 +81,13 @@ class DealerInventory(player: Player): SWInventoryHolder() {
prices.map { (material, price) ->
ItemStack(material).apply {
itemMeta = itemMeta.apply {
displayName(material.name.lowercase().replace("_", " ")
.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() }
.component().gray().appendSpace().append(price.amount.toString().component().yellow()))
displayName(Component.text(material.name.lowercase().replace("_", " ")
.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() })
.color(NamedTextColor.GRAY).appendSpace().append(Component.text(price.amount).color(NamedTextColor.YELLOW)))
amount = price.amount
lore(listOf(price.price.toString().component().yellow().bold().appendSpace().append(Component.text("Coins").yellow())))
lore(listOf(Component.text(price.price).color(NamedTextColor.YELLOW).decorate(TextDecoration.BOLD).appendSpace().append(Component.text("Coins").color(NamedTextColor.YELLOW))))
persistentDataContainer.apply {
set(priceKey, PersistentDataType.INTEGER, price.price)
set(amountKey, PersistentDataType.INTEGER, price.amount)
@@ -1,73 +0,0 @@
package de.steamwar.tntleague.util
import de.steamwar.tntleague.game.TNTLeagueTeam
import net.kyori.adventure.text.Component
import net.kyori.adventure.text.ComponentLike
import net.kyori.adventure.text.TranslatableComponent
import net.kyori.adventure.text.format.NamedTextColor
import net.kyori.adventure.text.format.Style
import net.kyori.adventure.text.format.TextDecoration
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer
import net.kyori.adventure.translation.GlobalTranslator
import org.bukkit.entity.Player
import java.util.Locale
val prefix = Component.text("Steam").yellow()
.append(Component.text("War").darkGray())
.appendSpace()
val tntLeaguePrefix = Component.text("TNT").color(NamedTextColor.DARK_RED)
.append(Component.text("League").color(NamedTextColor.GOLD))
val tntLeagueChatPrefix: Component = tntLeaguePrefix
.append(Component.text("»").darkGray())
.appendSpace()
fun TranslatableComponent.basic(): Component = tntLeagueChatPrefix.append(this.gray())
fun TranslatableComponent.error(): Component = tntLeagueChatPrefix.append(this.red())
fun TranslatableComponent.success(): Component = tntLeagueChatPrefix.append(this.green())
fun String.component(): Component = Component.text(this)
fun Component.bold(): Component = this.decorate(TextDecoration.BOLD)
fun String.bold(): Component = this.component().bold()
fun Component.yellow(): Component = this.color(NamedTextColor.YELLOW)
fun String.yellow(): Component = this.component().yellow()
fun Component.red(): Component = this.color(NamedTextColor.RED)
fun String.red(): Component = this.component().red()
fun Component.green(): Component = this.color(NamedTextColor.GREEN)
fun String.green(): Component = this.component().green()
fun Component.gray(): Component = this.color(NamedTextColor.GRAY)
fun String.gray(): Component = this.component().gray()
fun Component.darkGray(): Component = this.color(NamedTextColor.DARK_GRAY)
fun String.darkGray(): Component = this.component().darkGray()
fun Component.gold(): Component = this.color(NamedTextColor.GOLD)
fun translate(key: String, vararg args: ComponentLike): TranslatableComponent = Component.translatable(key, *args).decoration(TextDecoration.ITALIC, false)
fun Component.reset(): Component = this.style(Style.empty())
fun Component.colorByTeam(team: TNTLeagueTeam?) = when (team) {
null -> this.gray()
else -> this.color(team.color)
}
fun Component.translate(locale: Locale): Component = GlobalTranslator.render(this, locale)
fun Component.translate(p: Player): Component = this.translate(p.locale())
fun Component.toLegacy(): String = LegacyComponentSerializer.legacySection().serialize(this)
@@ -20,38 +20,46 @@
package de.steamwar.tntleague.util
import de.steamwar.scoreboard.ScoreboardCallback
import de.steamwar.tntleague.colorByTeam
import de.steamwar.tntleague.config.targetedBlocks
import de.steamwar.tntleague.game.TNTLeagueGame
import net.kyori.adventure.text.Component
import de.steamwar.tntleague.game.TNTLeagueTeam
import de.steamwar.tntleague.message
import org.bukkit.entity.Player
import kotlin.collections.HashMap
private val scoreboardTitle by lazy { tntLeaguePrefix.toLegacy() }
data class TNTLeagueScoreboard(val p: Player): ScoreboardCallback {
override fun getData(): HashMap<String, Int> {
val lines = mutableListOf<Component>()
val lines = mutableListOf<String>()
lines.add(Component.space().green())
lines.add("§1")
val minutes = TNTLeagueGame.gameTimeRemaining.floorDiv(60)
val seconds = TNTLeagueGame.gameTimeRemaining.rem(60).toString().padStart(2, '0')
lines.add(translate("scoreboardTime", minutes.toString().yellow(), seconds.yellow()).gray())
lines.add(message.parse("SCOREBOARD_TIME", p, minutes, seconds))
lines.add(Component.space().yellow())
lines.add("§2")
with(TNTLeagueGame.blueTeam) {
lines.add(translate("scoreboardTeam", translate(name).colorByTeam(this), (targetedBlocks - damagedBlocks).toString().yellow()).gray())
when (val team = TNTLeagueGame.getTeam(p)) {
is TNTLeagueTeam -> lines.add(message.parse("SCOREBOARD_COINS", p, team.coins))
else -> lines.add(message.parse("SCOREBOARD_COINS", p,
"§${TNTLeagueGame.blueTeam.color}${TNTLeagueGame.blueTeam.coins}§8:§${TNTLeagueGame.redTeam.color}${TNTLeagueGame.redTeam.coins}"))
}
lines.add("§3")
with(TNTLeagueGame.redTeam) {
lines.add(translate("scoreboardTeam", translate(name).colorByTeam(this), (targetedBlocks - damagedBlocks).toString().yellow()).gray())
lines.add(message.parse("SCOREBOARD_TEAM", p, message.parse(name, p).colorByTeam(this), targetedBlocks - damagedBlocks))
}
with(TNTLeagueGame.blueTeam) {
lines.add(message.parse("SCOREBOARD_TEAM", p, message.parse(name, p).colorByTeam(this), targetedBlocks - damagedBlocks))
}
lines.add(Component.space().gray())
lines.add("§4")
return lines
.foldIndexed(HashMap()) { index, acc, component -> acc.also { it[component.translate(p).toLegacy()] = index } }
.foldIndexed(HashMap()) { index, acc, component -> acc.also { it[component] = index } }
}
override fun getTitle(): String = scoreboardTitle
override fun getTitle(): String = message.parse("PREFIX", p).dropLast(1)
}
+7 -4
View File
@@ -4,7 +4,10 @@ main: de.steamwar.tntleague.TNTLeague
load: POSTWORLD
api-version: '1.21'
dependencies:
- name: SpigotCore
required: true
- name: KotlinCore
required: true
server:
SpigotCore:
required: true
load: BEFORE
KotlinCore:
required: true
load: BEFORE
@@ -29,7 +29,7 @@ public class Arenaserver extends Subserver {
private final boolean allowMerge;
public Arenaserver(String serverName, String mode, String map, boolean allowMerge, int port, ProcessBuilder processBuilder, Runnable shutdownCallback) {
super(Servertype.ARENA, serverName, port, processBuilder, shutdownCallback, null);
super(serverName, port, processBuilder, shutdownCallback, null);
this.mode = mode;
this.map = map;
this.allowMerge = allowMerge;
@@ -42,7 +42,7 @@ public class Bauserver extends Subserver {
}
public Bauserver(String serverName, UUID owner, int port, ProcessBuilder processBuilder, Runnable shutdownCallback, Consumer<Exception> failureCallback){
super(Servertype.BAUSERVER, serverName, port, processBuilder, shutdownCallback, failureCallback);
super(serverName, port, processBuilder, shutdownCallback, failureCallback);
this.owner = owner;
synchronized (servers) {
@@ -41,7 +41,7 @@ public class Builderserver extends Subserver {
}
public Builderserver(String serverName, String map, int port, ProcessBuilder processBuilder, Runnable shutdownCallback, Consumer<Exception> failureCallback){
super(Servertype.BUILDER, serverName, port, processBuilder, shutdownCallback, failureCallback);
super(serverName, port, processBuilder, shutdownCallback, failureCallback);
this.map = map;
synchronized (servers) {
@@ -1,26 +0,0 @@
/*
* 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.persistent;
public enum Servertype {
BAUSERVER,
ARENA,
BUILDER
}
@@ -38,9 +38,20 @@ import java.util.function.Predicate;
import java.util.logging.Level;
import java.util.logging.Logger;
@SuppressWarnings("unused")
public class Subserver {
public static boolean isArena(Subserver subserver) {
return subserver instanceof Arenaserver;
}
public static boolean isBuild(Subserver subserver) {
return subserver instanceof Bauserver;
}
public static boolean isBuilder(Subserver subserver) {
return subserver instanceof Builderserver;
}
private static final Component PREFIX = Component
.text("Steam").color(NamedTextColor.YELLOW)
.append(Component.text("War» ").color(NamedTextColor.DARK_GRAY));
@@ -84,8 +95,6 @@ public class Subserver {
private final ServerInfo server;
@Getter
private RegisteredServer registeredServer;
@Getter
private final Servertype type;
private final Thread thread;
@Getter
private boolean started;
@@ -94,13 +103,13 @@ public class Subserver {
@Getter
private final Map<Player, String> tablistNames = new HashMap<>();
protected Subserver(Servertype type, String serverName, int port, ProcessBuilder processBuilder, Runnable shutdownCallback, Consumer<Exception> failureCallback) {
protected Subserver(String serverName, int port, ProcessBuilder processBuilder, Runnable shutdownCallback, Consumer<Exception> failureCallback) {
this.started = false;
this.serverName = serverName;
this.type = type;
this.shutdownCallback = shutdownCallback;
this.failureCallback = failureCallback == null ? this::fatalError : failureCallback;
this.checkpoint = processBuilder.command().contains("criu");
this.thread = new Thread(this::run, "Subserver " + serverName);
try {
this.process = processBuilder.start();
@@ -112,7 +121,8 @@ public class Subserver {
this.server = new ServerInfo(serverName, address);
this.writer = new PrintWriter(process.getOutputStream(), true);
this.thread = new Thread(this::run, "Subserver " + serverName);
register();
this.thread.start();
}
@@ -146,7 +156,8 @@ public class Subserver {
process.destroyForcibly();
}
thread.join();
if(thread.isAlive())
thread.join();
} catch (InterruptedException e) {
logger.log(Level.SEVERE, "Subserver stop interrupted!", e);
Thread.currentThread().interrupt();
@@ -205,8 +216,6 @@ public class Subserver {
}
private void run() {
register();
Exception ex = null;
try {
if (checkpoint) {
+1 -2
View File
@@ -62,8 +62,7 @@ dependencies {
implementation(libs.msgpack)
implementation(libs.apolloapi)
implementation(libs.apollocommon)
implementation(libs.apolloprotos)
implementation(libs.nbt)
}
@@ -116,6 +116,8 @@ HELP_BAU_SET_BUILDER=§8/§ebuild setbuilder §8- §7Building, WorldEdit, BauSys
HELP_BAU_SET_BUILDER_HOVER=§eSets the Role to Builder
HELP_BAU_SET_SUPERVISOR=§8/§ebuild supervisor §8- §7Starting build server. Saving schematics
HELP_BAU_SET_SUPERVISOR_HOVER=§eSets the Role to Supervisor
HELP_BAU_STOP=§8/§ebuild stop §8- §7Stop your build server
HELP_BAU_STOP_HOVER=§eStop build server
HELP_BAU_DELETE=§8/§ebuild delete §8- §7Reset your entire build server
HELP_BAU_DELETE_HOVER=§eReset build server
HELP_BAU_TESTARENA=§8/§ebuild testarena §8- §7Start a test arena
@@ -235,6 +237,8 @@ BAU_DELMEMBER_USAGE=§8/§7build delmember §8[§eplayer§8]
BAU_DELMEMBER_SELFDEL=§cYou cannot remove yourself!
BAU_DELMEMBER_DELETED=§cPlayer was removed.
BAU_DELMEMBER_DELETED_TARGET=§cYou were removed from the world of §e{0}.
BAU_STOPPING=§7Stopping your build server. (May take up to a minute)
BAU_STOPPED=§aYour build server has been stopped.
BAU_DELETE_DELETED=§aYour world is being reset.
BAU_DELETE_GUI_NAME=§eDo you really want to delete the world?
BAU_DELETE_GUI_CANCEL=§cCancel
@@ -326,7 +330,7 @@ CHECK_DECLINED_TEAM=§7The schematic §e{0} §7from §e{1} §7is now declined be
#HistoricCommand
HISTORIC_BROADCAST=§7Historic §e{0} §7fight by §e{1}§8!
HISTORIC_BROADCAST_HOVER=§afight against §7{1}
HISTORIC_BROADCAST_HOVER=§afight against §7{0}
#JoinCommand
JOIN_PLAYER_BLOCK=§cYou currently cannot follow this player.
@@ -101,6 +101,8 @@ HELP_BAU_SET_BUILDER=§8/§ebau setbuilder §8- §7Bauen, WorldEdit, BauSystem F
HELP_BAU_SET_BUILDER_HOVER=§eSetzt die Rolle Builder
HELP_BAU_SET_SUPERVISOR=§8/§ebuild setsupervisor §8- §7Starten des Baus. Schematics erstellen
HELP_BAU_SET_SUPERVISOR_HOVER=§eSetzt die Rolle Supervisor
HELP_BAU_STOP=§8/§ebau stop §8- §7Stoppt deinen Bauserver
HELP_BAU_STOP_HOVER=§eStoppe Bauserver
HELP_BAU_DELETE=§8/§ebau delete §8- §7Setzt deine Bauwelt zurück
HELP_BAU_DELETE_HOVER=§eBauwelt zurücksetzen
HELP_BAU_TESTARENA=§8/§ebau testarena §8- §7Starte eine Testarena
@@ -218,6 +220,8 @@ BAU_DELMEMBER_USAGE=§8/§7bau delmember §8[§eSpieler§8]
BAU_DELMEMBER_SELFDEL=§cDu kannst dich nicht selbst entfernen!
BAU_DELMEMBER_DELETED=§cDer Spieler wurde entfernt.
BAU_DELMEMBER_DELETED_TARGET=§cDu wurdest von der Welt von §e{0} §centfernt.
BAU_STOPPING=§7Stoppe den Bauserver. (Kann bis zu einer Minute dauern)
BAU_STOPPED=§aDein Bauserver wurde gestoppt.
BAU_DELETE_DELETED=§aDeine Welt wird zurückgesetzt.
BAU_DELETE_GUI_NAME=§eWirklich Welt löschen?
BAU_DELETE_GUI_CANCEL=§cAbbrechen
@@ -308,7 +312,7 @@ CHECK_DECLINED_TEAM=§7Die Schematic §e{0} §7von §e{1} §7wurde aufgrund von
#HistoricCommand
HISTORIC_BROADCAST=§7Historischer §e{0}§8-§7Kampf von §e{1}§8!
HISTORIC_BROADCAST_HOVER=§aGegen §7{1} §ekämpfen
HISTORIC_BROADCAST_HOVER=§aGegen §7{0} §ekämpfen
#JoinCommand
JOIN_PLAYER_BLOCK=§cDu kannst diesem Spieler derzeit nicht folgen.
@@ -24,7 +24,6 @@ import com.velocitypowered.api.event.ResultedEvent;
import com.velocitypowered.api.event.connection.LoginEvent;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ServerConnection;
import de.steamwar.persistent.Servertype;
import de.steamwar.persistent.Subserver;
import de.steamwar.sql.SteamwarUser;
import de.steamwar.sql.UserPerm;
@@ -64,7 +63,7 @@ public interface Chatter {
static ChatterGroup globalChat() {
return new ChatterGroup(Stream.concat(Stream.of(Chatter.console()), allPlayers().filter(player -> {
Subserver subserver = Subserver.getSubserver(player);
return subserver == null || !(subserver.getType() == Servertype.ARENA && subserver.getServer() == player.getCurrentServer().map(ServerConnection::getServerInfo).orElse(null));
return !(Subserver.isArena(subserver) && subserver.getServer() == player.getCurrentServer().map(ServerConnection::getServerInfo).orElse(null));
}).map(Chatter::of)));
}
@@ -53,7 +53,7 @@ public class ErrorLogger extends AbstractAppender {
@Override
public void append(LogEvent event) {
if(event.getLevel().isLessSpecificThan(Level.WARN))
if(event.getLevel().intLevel() > Level.WARN.intLevel())
return;
String message = event.getMessage().getFormattedMessage();
@@ -70,6 +70,7 @@ public class ServerStarter {
private boolean checkpoint = false;
private ServerConstructor constructor = (serverName, port, builder, shutdownCallback, failureCallback) -> new Arenaserver(serverName, gameMode, fightMap, allowMerge, port, builder, shutdownCallback);
private Consumer<Subserver> callback = subserver -> {};
private Object responsible = new Object();
private final Set<Player> playersToSend = new HashSet<>();
private final Map<String, String> arguments = new HashMap<>();
@@ -84,6 +85,14 @@ public class ServerStarter {
directory = new File(SERVER_PATH, mode.getFolder());
arguments.put("config", mode.getConfig());
tempWorld(SERVER_PATH + mode.getFolder() + "/arenas/" + map);
startCondition = () -> {
if(playersToSend.stream().anyMatch(player -> Subserver.isArena(Subserver.getSubserver(player)))) {
playersToSend.forEach(player -> Chatter.of(player).system("FIGHT_IN_ARENA"));
return false;
}
return true;
};
return this;
}
@@ -245,6 +254,10 @@ public class ServerStarter {
public ServerStarter send(Player player) {
playersToSend.add(player);
if(!(responsible instanceof Player))
responsible = player;
return this;
}
@@ -253,47 +266,49 @@ public class ServerStarter {
return this;
}
public boolean start() {
if(!startCondition.getAsBoolean())
return false;
public void start() {
VelocityCore.schedule(() -> {
synchronized (responsible) {
if(!startCondition.getAsBoolean())
return;
int port = portrange.freePort();
String serverName = serverNameProvider.apply(port);
int port = portrange.freePort();
String serverName = serverNameProvider.apply(port);
if(node == null) {
node = Node.getNode();
if(node == null) {
for (Player p : playersToSend)
Chatter.of(p).system("SERVER_START_OVERLOAD");
if(node == null) {
node = Node.getNode();
if(node == null) {
for (Player p : playersToSend)
Chatter.of(p).system("SERVER_START_OVERLOAD");
return false;
return;
}
}
if(worldName == null)
worldName = serverToWorldName(serverName);
worldSetup.run();
arguments.put("logPath", worldName);
File checkpointDir = new File("/tmp/" + System.getProperty("user.name") + ".checkpoints/" + directory.getName() + "/" + worldName);
if(checkpoint)
arguments.put("checkpoint", checkpointDir.getPath());
if(checkpoint && checkpointDir.exists()) {
try(DataOutputStream out = new DataOutputStream(Files.newOutputStream(new File(checkpointDir, "port").toPath()))) {
out.writeInt(port);
} catch (IOException e) {
throw new SecurityException(e);
}
postStart(constructor.construct(serverName, port, node.prepareExecution(
"criu", "restore", "-D", checkpointDir.getPath(), "--auto-dedup", "--shell-job", "-v"
), worldCleanup, e -> regularStart(serverName, port)));
} else {
regularStart(serverName, port);
}
}
}
if(worldName == null)
worldName = serverToWorldName(serverName);
worldSetup.run();
arguments.put("logPath", worldName);
File checkpointDir = new File("/tmp/" + System.getProperty("user.name") + ".checkpoints/" + directory.getName() + "/" + worldName);
if(checkpoint)
arguments.put("checkpoint", checkpointDir.getPath());
if(checkpoint && checkpointDir.exists()) {
try(DataOutputStream out = new DataOutputStream(Files.newOutputStream(new File(checkpointDir, "port").toPath()))) {
out.writeInt(port);
} catch (IOException e) {
throw new SecurityException(e);
}
postStart(constructor.construct(serverName, port, node.prepareExecution(
"criu", "restore", "-D", checkpointDir.getPath(), "--auto-dedup", "--shell-job", "-v"
), worldCleanup, e -> regularStart(serverName, port)));
} else {
regularStart(serverName, port);
}
return true;
}).schedule();
}
private void regularStart(String serverName, int port) {
@@ -20,14 +20,13 @@
package de.steamwar.velocitycore.commands;
import com.velocitypowered.api.proxy.server.RegisteredServer;
import de.steamwar.persistent.Servertype;
import de.steamwar.persistent.Subserver;
import de.steamwar.velocitycore.VelocityCore;
import de.steamwar.command.PreviousArguments;
import de.steamwar.command.SWCommand;
import de.steamwar.command.TypeMapper;
import de.steamwar.messages.Chatter;
import de.steamwar.messages.PlayerChatter;
import de.steamwar.persistent.Subserver;
import de.steamwar.velocitycore.VelocityCore;
import java.util.Collection;
import java.util.List;
@@ -53,7 +52,7 @@ public class ArenaCommand extends SWCommand {
@Override
public boolean validate(Chatter sender, Subserver value, MessageSender messageSender) {
if (value == null || value.getType() != Servertype.ARENA) {
if (!Subserver.isArena(value)) {
sender.system("ARENA_NOT_FOUND");
return false;
}
@@ -64,7 +63,7 @@ public class ArenaCommand extends SWCommand {
public Collection<String> tabCompletes(Chatter sender, PreviousArguments previousArguments, String s) {
List<Subserver> subserverList = Subserver.getServerList();
synchronized (subserverList) {
return subserverList.stream().filter(subserver -> subserver.getType() == Servertype.ARENA).map(subserver -> subserver.getServer().getName()).toList();
return subserverList.stream().filter(Subserver::isArena).map(subserver -> subserver.getServer().getName()).toList();
}
}
};
@@ -197,6 +197,18 @@ public class BauCommand extends SWCommand {
};
}
@Register("stop")
public void stop(PlayerChatter sender) {
VelocityCore.schedule(() -> {
sender.system("BAU_STOPPING");
Bauserver subserver = Bauserver.get(sender.user().getUUID());
if(subserver != null)
subserver.stop();
sender.system("BAU_STOPPED");
}).schedule();
}
@Register("resetall")
@Register("delete")
public void delete(PlayerChatter sender, @OptionalValue(value = "", onlyUINIG = true) ServerVersion version) {
@@ -223,7 +235,7 @@ public class BauCommand extends SWCommand {
@Register("testarena")
public void testarena(PlayerChatter sender, @Mapper("nonHistoricArenaMode") @OptionalValue("") @AllowNull ArenaMode arenaMode, @Mapper("arenaMap") @OptionalValue("") @AllowNull String map) {
FightCommand.createArena(sender, "/bau testarena ", false, arenaMode, map, false, (chatter, mode, m) ->
VelocityCore.schedule(() -> new ServerStarter().test(mode, m, sender.getPlayer()).start()).schedule()
new ServerStarter().test(mode, m, sender.getPlayer()).start()
);
}
@@ -20,16 +20,15 @@
package de.steamwar.velocitycore.commands;
import com.velocitypowered.api.proxy.Player;
import de.steamwar.velocitycore.ArenaMode;
import de.steamwar.velocitycore.ServerStarter;
import de.steamwar.persistent.Servertype;
import de.steamwar.persistent.Subserver;
import de.steamwar.command.SWCommand;
import de.steamwar.command.TypeValidator;
import de.steamwar.messages.Chatter;
import de.steamwar.messages.Message;
import de.steamwar.messages.PlayerChatter;
import de.steamwar.persistent.Subserver;
import de.steamwar.sql.IgnoreSystem;
import de.steamwar.velocitycore.ArenaMode;
import de.steamwar.velocitycore.ServerStarter;
import net.kyori.adventure.text.event.ClickEvent;
import java.util.LinkedList;
@@ -84,8 +83,7 @@ public class ChallengeCommand extends SWCommand {
return false;
}
Subserver subserver = Subserver.getSubserver(value);
if (subserver != null && subserver.getType() == Servertype.ARENA) {
if (Subserver.isArena(Subserver.getSubserver(value))) {
messageSender.send("CHALLENGE_INARENA");
return false;
}
@@ -207,19 +207,15 @@ public class CheckCommand extends SWCommand {
this.startTime = Timestamp.from(Instant.now());
this.checkList = checkQuestions.get(schematic.getSchemtype()).listIterator();
VelocityCore.schedule(() -> {
ArenaMode mode = ArenaMode.getBySchemType(fightTypes.get(schematic.getSchemtype()));
if(!new ServerStarter().test(mode, mode.getRandomMap(), checker.getPlayer()).check(schematic.getId()).start()) {
remove();
return;
}
ArenaMode mode = ArenaMode.getBySchemType(fightTypes.get(schematic.getSchemtype()));
new ServerStarter().test(mode, mode.getRandomMap(), checker.getPlayer()).check(schematic.getId()).callback(subserver -> {
currentCheckers.put(checker.user().getUUID(), this);
currentSchems.put(schematic.getId(), this);
for(CheckedSchematic previous : CheckedSchematic.previousChecks(schematic))
checker.prefixless("CHECK_SCHEMATIC_PREVIOUS", previous.getEndTime(), SteamwarUser.get(previous.getValidator()).getUserName(), previous.getDeclineReason());
next();
}).schedule();
}).start();
}
private void next() {
@@ -30,6 +30,7 @@ import de.steamwar.command.TypeValidator;
import de.steamwar.messages.PlayerChatter;
import de.steamwar.sql.Punishment;
import de.steamwar.sql.SteamwarUser;
import lombok.Getter;
import java.io.File;
import java.net.InetSocketAddress;
@@ -39,7 +40,8 @@ import java.util.Map;
public class DevCommand extends SWCommand {
private final File devServerDir = new File("/configs/DevServer");
private final Map<String, RegisteredServer> devServers = new HashMap<>();
@Getter
private static final Map<String, RegisteredServer> devServers = new HashMap<>();
public DevCommand() {
super("dev");
@@ -20,16 +20,16 @@
package de.steamwar.velocitycore.commands;
import com.velocitypowered.api.proxy.Player;
import de.steamwar.velocitycore.*;
import de.steamwar.velocitycore.inventory.SWInventory;
import de.steamwar.velocitycore.inventory.SWItem;
import de.steamwar.command.SWCommand;
import de.steamwar.messages.Chatter;
import de.steamwar.messages.Message;
import de.steamwar.messages.PlayerChatter;
import de.steamwar.persistent.Arenaserver;
import de.steamwar.persistent.Servertype;
import de.steamwar.persistent.Subserver;
import de.steamwar.velocitycore.ArenaMode;
import de.steamwar.velocitycore.ServerStarter;
import de.steamwar.velocitycore.inventory.SWInventory;
import de.steamwar.velocitycore.inventory.SWItem;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.event.HoverEvent;
@@ -60,20 +60,7 @@ public class FightCommand extends SWCommand {
sender.sendMessage(start);
}
private static boolean alreadyInArena(PlayerChatter sender){
Subserver subserver = Subserver.getSubserver(sender.getPlayer());
if(subserver != null && subserver.getType() == Servertype.ARENA){
sender.system("FIGHT_IN_ARENA");
return true;
}
return false;
}
static void createArena(PlayerChatter sender, String precommand, boolean allowMerging, ArenaMode arenaMode, String map, boolean historic, FightCallback callback) {
if(alreadyInArena(sender))
return;
if (arenaMode == null) {
getModes(sender, precommand, historic);
return;
@@ -92,6 +92,7 @@ public class HelpCommand extends SWCommand {
"HELP_BAU_SET_SPECTATOR", "/build setSpectator ",
"HELP_BAU_SET_BUILDER", "/build setBuilder ",
"HELP_BAU_SET_SUPERVISOR", "/build setSupervisor ",
"HELP_BAU_STOP", "/build stop",
"HELP_BAU_DELETE", "/build delete ",
"HELP_BAU_TESTARENA", "/build testarena ",
"HELP_BAU_LOCK", "/build lock ",
@@ -35,7 +35,7 @@ public class HistoricCommand extends SWCommand {
@Register
public void historic(@Validator("arenaPlayer") PlayerChatter player, @Mapper("historicArenaMode") @OptionalValue("") @AllowNull ArenaMode arenaMode, @Mapper("arenaMap") @OptionalValue("") @AllowNull String map) {
FightCommand.createArena(player, "/historic ", true, arenaMode, map, true, (p, mode, m) -> new ServerStarter().arena(mode, m).blueLeader(p.getPlayer()).callback(
arena -> Chatter.broadcast().system("HISTORIC_BROADCAST", new Message("HISTORIC_BROADCAST_HOVER"), ClickEvent.runCommand("/arena " + arena.getServer().getName()), mode.getGameName(), p.getPlayer())
arena -> Chatter.broadcast().system("HISTORIC_BROADCAST", new Message("HISTORIC_BROADCAST_HOVER", p), ClickEvent.runCommand("/arena " + arena.getServer().getName()), mode.getGameName(), p.getPlayer())
).start());
}
}
@@ -21,11 +21,10 @@ package de.steamwar.velocitycore.commands;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ServerConnection;
import de.steamwar.persistent.Servertype;
import de.steamwar.persistent.Subserver;
import de.steamwar.velocitycore.VelocityCore;
import de.steamwar.command.SWCommand;
import de.steamwar.messages.Chatter;
import de.steamwar.persistent.Subserver;
import de.steamwar.velocitycore.VelocityCore;
import java.util.ArrayList;
import java.util.List;
@@ -46,8 +45,7 @@ public class ListCommand extends SWCommand {
if (pserver == null)
continue;
Subserver subserver = Subserver.getSubserver(pserver.getServerInfo());
if (subserver != null && subserver.getType() == Servertype.BAUSERVER) {
if (Subserver.isBuild(Subserver.getSubserver(pserver.getServerInfo()))) {
playerMap.computeIfAbsent("Bau", s -> new ArrayList<>()).add(player);
} else {
playerMap.computeIfAbsent(pserver.getServerInfo().getName(), s -> new ArrayList<>()).add(player);
@@ -55,15 +55,7 @@ public class SendCommand extends SWCommand {
if (name.contains(" ")) return false;
Subserver subserver = Subserver.getSubserver(serverInfo);
if (subserver == null) {
return true;
}
return switch (subserver.getType()) {
case ARENA -> true;
case BUILDER -> user.hasPerm(UserPerm.BUILD);
default -> false;
};
return subserver == null || Subserver.isArena(subserver) || (Subserver.isBuilder(subserver) && user.hasPerm(UserPerm.BUILD));
}
@Override
@@ -110,37 +110,31 @@ public class TpCommand extends SWCommand {
return;
}
switch (subserver.getType()) {
case ARENA:
if (PunishmentCommand.isPunishedWithMessage(sender, Punishment.PunishmentType.NoFightServer))
return;
break;
case BAUSERVER:
Bauserver bauserver = (Bauserver) subserver;
Player checker = VelocityCore.getProxy().getPlayer(bauserver.getOwner()).orElse(null);
if (checker != null && CheckCommand.isChecking(checker)) {
if (!sender.user().hasPerm(UserPerm.CHECK) && CheckCommand.getCheckingSchem(checker).getOwner() != sender.user().getId()) {
sender.system("JOIN_PLAYER_BLOCK");
return;
}
} else if (BauLock.isLocked(SteamwarUser.get(bauserver.getOwner()), sender.user())) {
sender.system("BAU_LOCKED_NOALLOWED");
Chatter.of(bauserver.getOwner()).system("BAU_LOCK_BLOCKED", sender);
return;
} else if (!bauserver.getOwner().equals(sender.user().getUUID()) && BauweltMember.getBauMember(bauserver.getOwner(), sender.user().getUUID()) == null) {
SubserverSystem.sendDeniedMessage(sender, bauserver.getOwner());
if(Subserver.isArena(subserver)) {
if (PunishmentCommand.isPunishedWithMessage(sender, Punishment.PunishmentType.NoFightServer))
return;
} else if(Subserver.isBuild(subserver)) {
Bauserver bauserver = (Bauserver) subserver;
Player checker = VelocityCore.getProxy().getPlayer(bauserver.getOwner()).orElse(null);
if (checker != null && CheckCommand.isChecking(checker)) {
if (!sender.user().hasPerm(UserPerm.CHECK) && CheckCommand.getCheckingSchem(checker).getOwner() != sender.user().getId()) {
sender.system("JOIN_PLAYER_BLOCK");
return;
}
break;
case BUILDER:
if(!sender.user().hasPerm(UserPerm.BUILD)) {
sender.system("JOIN_PLAYER_BLOCK");
return;
}
break;
} else if (BauLock.isLocked(SteamwarUser.get(bauserver.getOwner()), sender.user())) {
sender.system("BAU_LOCKED_NOALLOWED");
Chatter.of(bauserver.getOwner()).system("BAU_LOCK_BLOCKED", sender);
return;
} else if (!bauserver.getOwner().equals(sender.user().getUUID()) && BauweltMember.getBauMember(bauserver.getOwner(), sender.user().getUUID()) == null) {
SubserverSystem.sendDeniedMessage(sender, bauserver.getOwner());
sender.system("JOIN_PLAYER_BLOCK");
return;
}
} else if(Subserver.isBuilder(subserver)) {
if(!sender.user().hasPerm(UserPerm.BUILD)) {
sender.system("JOIN_PLAYER_BLOCK");
return;
}
}
SubserverSystem.sendPlayer(subserver, sender.getPlayer());
@@ -19,21 +19,22 @@
package de.steamwar.velocitycore.commands;
import de.steamwar.velocitycore.*;
import de.steamwar.velocitycore.inventory.SWInventory;
import de.steamwar.velocitycore.inventory.SWItem;
import de.steamwar.velocitycore.inventory.SWListInv;
import de.steamwar.velocitycore.inventory.SWStreamInv;
import de.steamwar.command.SWCommand;
import de.steamwar.command.TypeValidator;
import de.steamwar.messages.Chatter;
import de.steamwar.messages.Message;
import de.steamwar.messages.PlayerChatter;
import de.steamwar.persistent.Servertype;
import de.steamwar.persistent.Subserver;
import de.steamwar.sql.SteamwarUser;
import de.steamwar.sql.Tutorial;
import de.steamwar.sql.UserPerm;
import de.steamwar.velocitycore.ServerStarter;
import de.steamwar.velocitycore.SubserverSystem;
import de.steamwar.velocitycore.VelocityCore;
import de.steamwar.velocitycore.inventory.SWInventory;
import de.steamwar.velocitycore.inventory.SWItem;
import de.steamwar.velocitycore.inventory.SWListInv;
import de.steamwar.velocitycore.inventory.SWStreamInv;
import java.io.File;
import java.util.Arrays;
@@ -140,7 +141,7 @@ public class TutorialCommand extends SWCommand {
SteamwarUser user = sender.user();
File tempWorld = new File(ServerStarter.TEMP_WORLD_PATH, ServerStarter.serverToWorldName(ServerStarter.bauServerName(user)));
if(subserver == null || !subserver.isStarted() || subserver.getType() != Servertype.BAUSERVER || !tempWorld.exists()) {
if(!Subserver.isBuild(subserver) || !subserver.isStarted() || !tempWorld.exists()) {
sender.system("TUTORIAL_CREATE_MISSING");
return;
}
@@ -20,7 +20,6 @@
package de.steamwar.velocitycore.discord.channels;
import net.dv8tion.jda.api.interactions.callbacks.IReplyCallback;
import net.dv8tion.jda.api.interactions.components.ComponentInteraction;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
@@ -44,23 +43,24 @@ public class InteractionReply extends DiscordChannel {
private InteractionReply(IReplyCallback interaction) {
super(interaction.getUser());
this.interaction = interaction;
interaction.deferReply(true).queue();
}
@Override
public void sendMessage(Component msg) {
if(replied) {
super.sendMessage(msg);
if(!replied) {
messages.add(PlainTextComponentSerializer.plainText().serialize(msg));
return;
}
messages.add(PlainTextComponentSerializer.plainText().serialize(msg));
if(interaction.getHook().isExpired())
super.sendMessage(msg);
else
interaction.getHook().sendMessage(PlainTextComponentSerializer.plainText().serialize(msg)).queue();
}
public void submit() {
(messages.isEmpty() ?
interaction.deferReply() :
interaction.reply(String.join("\n", messages))
).setEphemeral(true).queue();
interaction.getHook().sendMessage(String.join("\n", messages)).queue();
replied = true;
}
}
@@ -43,7 +43,7 @@ public class DiscordAlert {
if(discordId == null)
return;
User user = DiscordBot.getInstance().getJda().getUserById(discordId);
User user = DiscordBot.getInstance().getJda().retrieveUserById(discordId).complete();
if(user == null)
return;
@@ -32,7 +32,6 @@ import de.steamwar.messages.ChatterGroup;
import de.steamwar.messages.Message;
import de.steamwar.messages.PlayerChatter;
import de.steamwar.network.packets.server.PingPacket;
import de.steamwar.persistent.Servertype;
import de.steamwar.persistent.Subserver;
import de.steamwar.sql.*;
import de.steamwar.velocitycore.ArenaMode;
@@ -110,7 +109,7 @@ public class ChatListener extends BasicListener {
return;
Subserver subserver = Subserver.getSubserver(player);
if(subserver != null && subserver.getType() == Servertype.ARENA && subserver.getServer() == player.getCurrentServer().orElseThrow().getServerInfo()) {
if(Subserver.isArena(subserver) && subserver.getServer() == player.getCurrentServer().orElseThrow().getServerInfo()) {
localChat(Chatter.of(player), message);
} else if (message.startsWith("+")) {
localChat(Chatter.of(player), message.substring(1));
@@ -24,13 +24,12 @@ import com.velocitypowered.api.event.connection.DisconnectEvent;
import com.velocitypowered.api.event.connection.PostLoginEvent;
import com.velocitypowered.api.event.player.ServerConnectedEvent;
import com.velocitypowered.api.proxy.Player;
import de.steamwar.persistent.Bauserver;
import de.steamwar.persistent.Servertype;
import de.steamwar.persistent.Subserver;
import de.steamwar.velocitycore.commands.CheckCommand;
import de.steamwar.messages.Chatter;
import de.steamwar.persistent.Bauserver;
import de.steamwar.persistent.Subserver;
import de.steamwar.sql.SchematicNode;
import de.steamwar.sql.SchematicType;
import de.steamwar.velocitycore.commands.CheckCommand;
import java.util.ArrayList;
import java.util.List;
@@ -56,11 +55,7 @@ public class CheckListener extends BasicListener {
Player player = e.getPlayer();
if(CheckCommand.isChecking(player)){
Subserver server = Subserver.getSubserver(e.getServer().getServerInfo());
if(
server == null ||
server.getType() != Servertype.BAUSERVER ||
((Bauserver)server).getOwner() != player.getUniqueId()
)
if(!Subserver.isBuild(server) || ((Bauserver)server).getOwner() != player.getUniqueId())
CheckCommand.abort(player);
}
}
@@ -27,7 +27,6 @@ import com.velocitypowered.api.permission.Tristate;
import com.velocitypowered.api.proxy.Player;
import de.steamwar.messages.Chatter;
import de.steamwar.messages.Message;
import de.steamwar.persistent.Servertype;
import de.steamwar.persistent.Subserver;
import de.steamwar.sql.SteamwarUser;
import de.steamwar.sql.UserPerm;
@@ -77,7 +76,7 @@ public class ConnectionListener extends BasicListener {
CheckCommand.sendReminder(chatter);
for(Subserver subserver : Subserver.getServerList()) {
if(subserver.getType() == Servertype.ARENA) {
if(Subserver.isArena(subserver)) {
chatter.system("JOIN_ARENA", new Message("JOIN_ARENA_HOVER"), ClickEvent.runCommand("/arena " + subserver.getServer().getName()), subserver.getServer().getName());
}
}
@@ -19,7 +19,6 @@
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;
@@ -32,12 +31,12 @@ import com.velocitypowered.api.proxy.messages.ChannelMessageSource;
import com.velocitypowered.api.proxy.messages.LegacyChannelIdentifier;
import com.velocitypowered.api.proxy.messages.MinecraftChannelIdentifier;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import de.steamwar.messages.Chatter;
import de.steamwar.network.packets.NetworkPacket;
import de.steamwar.velocitycore.VelocityCore;
import de.steamwar.velocitycore.commands.TeamCommand;
import de.steamwar.velocitycore.mods.*;
import de.steamwar.velocitycore.network.ServerMetaInfo;
import de.steamwar.messages.Chatter;
import de.steamwar.network.packets.NetworkPacket;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import net.kyori.adventure.text.Component;
@@ -106,24 +105,24 @@ public class PluginMessage extends BasicListener {
for(String channel : Arrays.asList(
"fabric:container/open", "fabric:registry/sync/direct", "fabric:registry/sync",
"fabric-screen-handler-api-v1:open_screen",
"fabric-screen-handler-api-v1:open_screen", "fabric:attachment_sync_v1",
FML.CHANNEL, "FML|MP", "FML", "FORGE",
"fml:loginwrapper", "fml:handshake", "fml:play",
"forge:tier_sorting", "forge:split", "forge:login", "forge:handshake",
"labymod3:main", "labymod:neo",
"labymod3:main", "labymod:neo", "labymod:voicechat", "labymod:germanminer",
"feather:client/frag",
Alpine.HANDSHAKE, Alpine.PLAY,
"lunarclient:pm", "transfer:channel", "apollo:json", //https://lunarclient.dev/apollo/developers/modules/transfer (Lunarclient channels)
"sw:hotkeys",
"floodgate:form", "floodgate:transfer", "floodgate:packet",
"floodgate:form", "floodgate:w", "floodgate:packet", "floodgate:transfer", "erosion:msg",
"Replay|Restrict", "replaymod:restrict",
"WDL|CONTROL", "wdl:control",
"tpshud:handshake", "tpshud:tps", //https://github.com/mooziii/tpshud-fabric/tree/main
"methane_server:statepacket", //https://modrinth.com/mod/methane
"servux:structures", //https://modrinth.com/mod/servux
"architectury:spawn_entity_packet", //https://modrinth.com/mod/architectury-api
"jei:channel", "jei:cheat_permission", //https://modrinth.com/mod/jei
"owo:local_packet", "owo:sync_screen_handler_properties", //https://modrinth.com/mod/owo-lib
@@ -134,9 +133,9 @@ public class PluginMessage extends BasicListener {
"plasmo:voice/v2/installed", "plasmo:voice/v2", //https://modrinth.com/plugin/plasmo-voice (Voice chat)
"inventorysorter:sync_blacklist_packet", //https://github.com/cpw/inventorysorter (needs server side component to work)
"emi:ping", "emi:command", "emi:chess", //https://github.com/emilyploszaj/emi/
"fancymenu:execute_command", "fancymenu:packet_bridge", //https://github.com/Keksuccino/FancyMenu (Custom menus)
"fancymenu:execute_command", "fancymenu:packet_bridge", "minecraft:fancymenu_packet_bridge", //https://github.com/Keksuccino/FancyMenu (Custom menus)
"itemswapper:enableshulker", "itemswapper:enablerefill", //https://github.com/tr7zw/ItemSwapper/tree/main (Easier inventory item swapping)
"jade:show_overlay", "jade:receive_data", "jade:server_ping", //https://github.com/Snownee/Jade (Information over block/entity under crosshair)
"jade:show_overlay", "jade:receive_data", "jade:server_ping", "jade:server_ping_v1", //https://github.com/Snownee/Jade (Information over block/entity under crosshair)
"bclib:hello_client", "bclib:request_files", "bclib:send_files", "bclib:chunker", //https://github.com/quiqueck/BCLib (Library for additional dimensions)
"roughlyenoughitems:ci_msg", "roughlyenoughitems:request_tags_s2c", "roughlyenoughitems:og_not_enough", //https://github.com/shedaniel/RoughlyEnoughItems (Crafting recipe helper)
"essentialclient:chunkdebug", "essentialclient:clientscript", "essentialclient:gamerule", //https://github.com/senseiwells/EssentialClient (Carpet mod extension)
@@ -153,17 +152,16 @@ public class PluginMessage extends BasicListener {
"craftingtweaks:hello", "craftingtweaks:sync_config", //https://github.com/TwelveIterationMods/CraftingTweaks (Additional Crafting UI)
"create:main", //https://github.com/Creators-of-Create/Create (Additional redstone blocks mod)
"dummmmmmy:0", "dummmmmmy:1", "dummmmmmy:2", //https://github.com/MehVahdJukaar/DuMmmMmmy (Adding dummy target item)
"easyanvils:1/0", "easyanvils:1/2", //https://github.com/Fuzss/easyanvils (Anvil handling improvements)
"easymagic:1/0", "easymagic.main:0", //https://github.com/Fuzss/easymagic (Enchantment table handling improvements)
"easyanvils:1/0", "easyanvils:1/2", "easyanvils:play", //https://github.com/Fuzss/easyanvils (Anvil handling improvements)
"easymagic:1/0", "easymagic.main:0", "easymagic:play", //https://github.com/Fuzss/easymagic (Enchantment table handling improvements)
"enhancedvisuals:main0", "enhancedvisuals:main1", "enhancedvisuals:main2", //https://github.com/CreativeMD/EnhancedVisuals (Visual effects)
"fallingtree:configuration-packet", //https://github.com/RakambdaOrg/FallingTree (Serverside tree cutting enhancements)
"forgeconfigscreens:play/0", "forgeconfigscreens:play/1", //https://github.com/Fuzss/forgeconfigscreens (Config GUI)
"fwaystones:void_totem_revive", "fwaystones:sync_player", "fwaystones:waystone_packet", //https://github.com/LordDeatHunter/FabricWaystones (Adds new block - waystone)
"fzzy_config:sync_config_packet", //https://github.com/fzzyhmstrs/fconfig (Synchronizing configuation library)
"graveyard:spawn_entity", //https://github.com/finallion/The-Graveyard-FORGE (Adding graveyard themed blocks, items and mobs)
"immersive_weathering:0", //https://github.com/AstralOrdana/Immersive-Weathering (Adds additional random block transitions)
"kiwi:sync_cosmetic", //github.com/Snownee/Kiwi (General purpose library)
"libgui:screen_messag", "libgui:screen_message_s2c", //https://github.com/cottonmc/libgui (Ingame GUI library)
"libgui:screen_messag", "libgui:screen_message", "libgui:screen_message_s2c", //https://github.com/cottonmc/libgui (Ingame GUI library)
"libjf-config-network", "libjf-config-network-v0:request", "libjf-config-network-v0:response", //https://git.frohnmeyer-wds.de/JfMods/LibJF (General purpose library)
"libz:set_mouse_position", "libz:sync_config", //https://github.com/Globox1997/LibZ (General purpose library)
"moonlight:0", "moonlight:1", "moonlight:2", "moonlight:3", "moonlight:4", "moonlight:5", //https://github.com/MehVahdJukaar/Moonlight (General purpose library)
@@ -186,6 +184,15 @@ public class PluginMessage extends BasicListener {
"walkietalkie:buttonpressedresponse", //https://github.com/Flaton1/walkie-talkie-mod (Simple voice chat walkietalkie addon)
"whereisit:s2c_founditem", "whereisit:found_item_s2c", //https://modrinth.com/mod/where-is-it (needs server side component to work)
"wildfire_gender:hurt", "wildfire_gender:sync", //https://github.com/WildfireRomeo/WildfireFemaleGenderMod (Female player model)
"cancelblockupdate:channel", //https://github.com/Phoupraw/CancelBlockUpdate/ (Server side block update suppression)
"replayvoicechat:entity_sound", "replayvoicechat:locational_sound", "replayvoicechat:static_sound", //https://github.com/henkelmax/replay-voice-chat (Record simple voice chat with replay mod)
"adventure:registered_arg_mappings",
"better-suggestions:entity_scores_response", "better-suggestions:entity_tags_response", //https://github.com/shurik204/better-suggestions (Better command tab completion)
"farmingforblockheads:chicken_nest_effect", "farmingforblockheads:market_categories", //https://github.com/TwelveIterationMods/FarmingForBlockheads (Improved farming with new blocks)
//https://modrinth.com/mod/servux
"servux:structures", "servux:entity_data", "servux:hud_metadata", "servux:debug_service",
"servux:tweaks",
//https://github.com/ZsoltMolnarrr/SpellEngine (Magic library)
"spell_engine:config_sync", "spell_engine:particle_effects", "spell_engine:spell_animation",
@@ -219,6 +226,8 @@ public class PluginMessage extends BasicListener {
//https://github.com/CreativeMD/CreativeCore (General purpose library)
"creativecore:main0", "creativecore:main1", "creativecore:main2", "creativecore:main3",
"creativecore:main4", "creativecore:main5", "creativecore:main6", "creativecore:main7",
"creativecore:0s", "creativecore:1s", "creativecore:2s", "creativecore:3s", "creativecore:4s",
"creativecore:5s", "creativecore:6s", "creativecore:7s",
//https://github.com/Ladysnake/Cardinal-Components-API (General purpose library)
"cardinal-components:block_entity_sync", "cardinal-components:chunk_sync",
@@ -273,19 +282,21 @@ public class PluginMessage extends BasicListener {
"minecells:elevator_destroyed", "minecells:spawn_rune_particles", "minecells:sync_minecells_data",
//https://modrinth.com/mod/appleskin (Additional food bar information)
"appleskin:exhaustion_sync", "appleskin:saturation_sync",
"appleskin:exhaustion_sync", "appleskin:saturation_sync", "appleskin:natural_regeneration",
"appleskin:saturation", "appleskin:exhaustion",
//https://modrinth.com/mod/puzzles-lib (General purpose library)
"puzzleslib:1/0", "puzzleslib:1/1", "puzzleslib:1/2",
"puzzleslib:play", "puzzleslib:1/0", "puzzleslib:1/1", "puzzleslib:1/2",
"puzzleslib.main:0", "puzzleslib.main:1", "puzzleslib:play/0",
//https://github.com/Fuzss/puzzlesapi (General purpose library extension)
"puzzlesapi:1/1", "puzzlesapi:1/2", "puzzlesapi:1/5", "puzzlesapi:2/1", "puzzlesapi:2/2",
//https://github.com/bernie-g/geckolib
"geckolib:block_entity_anim_trigger_sync", "geckolib:entity_anim_trigger_sync",
"geckolib:block_entity_anim_data_sync", "geckolib:anim_data_sync",
"geckolib:entity_anim_data_sync", "geckolib:anim_trigger_sync",
"geckolib:entity_data_sync", "geckolib:blockentity_anim_trigger", "geckolib:singleton_data_sync",
"geckolib:block_entity_anim_data_sync", "geckolib:anim_data_sync", "geckolib:entity_anim_trigger",
"geckolib:entity_anim_data_sync", "geckolib:anim_trigger_sync", "geckolib:singleton_anim_trigger",
"geckolib:blockentity_data_sync",
//https://github.com/Noxcrew/noxesium (MC Championship helper)
"noxesium:server_rules",
@@ -294,25 +305,55 @@ public class PluginMessage extends BasicListener {
"noxesium-v1:stop_sound", "noxesium-v1:start_sound", "noxesium-v1:modify_sound",
"noxesium-v2:reset", "noxesium-v2:change_server_rules", "noxesium-v2:server_info",
"noxesium-v2:mcc_server", "noxesium-v2:mcc_game_state", "noxesium-v2:reset_server_rules",
"noxesium-v2:stop_sound", "noxesium-v2:start_sound", "noxesium-v2:modify_sound"
"noxesium-v2:stop_sound", "noxesium-v2:start_sound", "noxesium-v2:modify_sound",
"noxesium-v2:change_extra_entity_data", "noxesium-v2:reset_extra_entity_data",
//https://github.com/Up-Mods/OkZoomer (Zoom mod, deprecated dysfunctional control options)
"ok_zoomer:force_classic_mode", "ok_zoomer:acknowledge_mod", "ok_zoomer:force_spyglass_overlay",
"ok_zoomer:force_spyglass", "ok_zoomer:disable_zoom_scrolling", "ok_zoomer:disable_zoom",
"ok_zoomer:force_zoom_divisor",
//https://github.com/fzzyhmstrs/fconfig (Synchronizing configuation library)
"fzzy_config:sync_config_packet", "fzzy_config:config_perms_s2c", "fzzy_config:config_sync_s2c",
"fzzy_config:config_update_s2c", "fzzy_config:dynamic_id_s2c", "fzzy_config:setting_forward",
//https://github.com/TwelveIterationMods/CookingForBlockheads (Improved cooking with new blocks)
"cookingforblockheads:available_craftables_list", "cookingforblockheads:selection_recipes_list",
"cookingforblockheads:synced_effect",
//https://github.com/tom5454/CustomPlayerModels (Custom player models)
"cpm_net:get_skin", "cpm_net:hello", "cpm_net:plugin", "cpm_net:rec_evt", "cpm_net:rec_sfy",
"cpm_net:set_scl", "cpm_net:set_skin", "cpm_net:srv_anim",
//https://github.com/FrozenBlock/FrozenLib (General purpose library)
"frozenlib:config_sync_packet", "frozenlib:cooldown_change_packet", "frozenlib:cooldown_change_packet",
"frozenlib:fading_distance_sound_packet", "frozenlib:flyby_sound_packet", "frozenlib:wind_sync_packet",
"frozenlib:forced_cooldown_packet", "frozenlib:local_player_sound_packet",
"frozenlib:local_sound_packet", "frozenlib:moving_fading_restriction_sound_packet",
"frozenlib:moving_restriction_sound_packet", "frozenlib:remove_entity_screen_shakes_packet",
"frozenlib:remove_screen_shakes_packet", "frozenlib:screen_shake_entity_packet",
"frozenlib:screen_shake_packet", "frozenlib:spotting_icon_packet", "frozenlib:wind_disturbance_packet",
"frozenlib:spotting_icon_remove_packet", "frozenlib:starting_moving_restriction_looping_sound_packet"
))
channelRegisterHandlers.put(channel, player -> {});
channelRegisterHandlers.put(ApolloManager.PLUGIN_MESSAGE_CHANNEL, lunar::sendRestrictions);
channelRegisterHandlers.put(Lunar.CHANNEL, lunar::sendRestrictions);
channelRegisterHandlers.put(Feather.CHANNEL, new Feather()::sendRestrictions);
channelRegisterHandlers.put("openboatutils:settings", player -> send(player, "openboatutils:settings", new byte[] { 0, 0 })); //https://github.com/o7Moon/OpenBoatUtils/wiki/Packets (Reset packet)
channelRegisterHandlers.put("itemswapper:disable", player -> send(player, "itemswapper:disable", new byte[]{ 0 })); //https://github.com/tr7zw/ItemSwapper/blob/main/src/main/java/dev/tr7zw/itemswapper/packets/DisableModPayload.java
channelRegisterHandlers.put("xaerominimap:main", player -> player.sendMessage(Component.text("§n§o§m§i§n§i§m§a§p"))); //https://www.curseforge.com/minecraft/mc-mods/xaeros-minimap
channelRegisterHandlers.put("litemoretica:init_easy_place", player -> Chatter.disconnect(player).prefixless("MOD_YELLOW_SING", "litematica")); //https://github.com/Earthcomputer/litemoretica/tree/master
channelRegisterHandlers.put("litemoretica:init_ea", player -> Chatter.disconnect(player).prefixless("MOD_YELLOW_SING", "litematica")); //https://github.com/Earthcomputer/litemoretica/tree/master
channelRegisterHandlers.put("servux:litematics", player -> Chatter.disconnect(player).prefixless("MOD_YELLOW_SING", "litematica")); //https://github.com/maruohon/litematica/blob/pre-rewrite/fabric/1.21.1-masa/src/main/java/fi/dy/masa/litematica/network/ServuxLitematicaHandler.java
channelRegisterHandlers.put("voxelmap:settings", player -> Chatter.disconnect(player).prefixless("MOD_YELLOW_SING", "voxelmap")); //https://modrinth.com/mod/voxelmap-updated undocumented
channelRegisterHandlers.put("inventoryessentials:hello", player -> Chatter.disconnect(player).prefixless("MOD_YELLOW_SING", "InventoryEssentials")); //https://github.com/TwelveIterationMods/InventoryEssentials
channelRegisterHandlers.put(Controlify.CHANNEL, new Controlify()::onRegister);
for(String channel : Arrays.asList(
"worldinfo:world_id", // JourneyMap and VoxelMap
"journeymap:version", "journeymap:admin_req", "journeymap:mp_options_req", "journeymap:waypoint",
"journeymap:player_loc", "journeymap:admin_save", "journeymap:teleport_req", "journeymap:common",
"journeymap:perm_req"
"journeymap:perm_req", "journeymap:chunk_overlay", "journeymap:remove_player"
))
channelRegisterHandlers.put(channel, player -> Chatter.disconnect(player).prefixless("MOD_YELLOW_SING", "minimap"));
@@ -325,13 +366,14 @@ public class PluginMessage extends BasicListener {
"axiom:enable", "axiom:initialize_hotbars",
"axiom:response_chunk_data", "axiom:register_world_properties", "axiom:set_world_property",
"axiom:ack_world_properties", "axiom:restrictions", "axiom:marker_data", "axiom:marker_nbt_response",
"axiom:custom_blocks", "axiom:editor_warning", "axiom:blueprint_manifest", "axiom:response_blueprint"
"axiom:custom_blocks", "axiom:editor_warning", "axiom:blueprint_manifest", "axiom:response_blueprint",
"axiom:annotation_update"
);
registerBiDirPassthrough("axiom:handle_big_payload", "axiom:set_editor_views");
for(String channel : Arrays.asList(
"axiom:hello", "axiom:set_gamemode", "axiom:set_fly_speed", "axiom:set_world_time",
"axiom:set_world_property", "axiom:set_block", "axiom:set_hotbar_slot", "axiom:switch_active_hotbar",
"axiom:teleport", "axiom:request_chunk_data", "axiom:spawn_entity",
"axiom:teleport", "axiom:request_chunk_data", "axiom:spawn_entity", "axiom:response_entity_data",
"axiom:manipulate_entity", "axiom:delete_entity", "axiom:marker_nbt_request", "axiom:set_buffer"
)) {
channelRegisterHandlers.put(channel, player -> {});
@@ -343,7 +385,8 @@ public class PluginMessage extends BasicListener {
"watut:nbt", //https://github.com/Corosauce/WATUT
"bclib:hello_server",
"vivecraft:data", //https://github.com/Vivecraft/VivecraftMod https://github.com/jrbudda/Vivecraft_Spigot_Extensions https://github.com/Techjar/Vivecraft_BungeeCord_Extensions (VR support)
"badpackets:channel_sync" //https://github.com/badasintended/badpackets (Forge fabric translation layer)
"badpackets:channel_sync", //https://github.com/badasintended/badpackets (Forge fabric translation layer)
"hero-api:mouse-packet", "hero-api:mouse-scroll" //TODO https://github.com/NoRiskClient Mit Superhelden-Mod?
)) {
channelRegisterHandlers.put(channel, player -> {});
register(channel, false, directional(UNKNOWN, DROP));
@@ -372,7 +415,8 @@ public class PluginMessage extends BasicListener {
"fwaystones:request_player_waystone_update",
"openboatutils:settings", //https://github.com/o7Moon/OpenBoatUtils
"block-event-separator:handshake", //https://github.com/SpaceWalkerRS/block-event-separator (Separating block events)
"oth3r-sit:settings_v1.1" //https://github.com/Oth3r/Sit (Sitting mod)
"oth3r-sit:settings_v1.1", //https://github.com/Oth3r/Sit (Sitting mod)
"carryon:key_pressed" //https://github.com/Tschipp/CarryOn/blob/1.21/Common/src/main/java/tschipp/carryon/networking/serverbound/ServerboundCarryKeyPressedPacket.java
))
register(channel, false, directional(UNKNOWN, DROP));
@@ -390,7 +434,7 @@ public class PluginMessage extends BasicListener {
register("WDL|INIT", true, directional(UNKNOWN, wdl::handlePluginMessage));
register("wdl:init", true, directional(UNKNOWN, wdl::handlePluginMessage));
register(ApolloManager.PLUGIN_MESSAGE_CHANNEL, true, async(lunar::handlePluginMessage));
register(Lunar.CHANNEL, true, async(lunar::handlePluginMessage));
register(Alpine.HANDSHAKE, false, directional(UNKNOWN, new Alpine()::handleHandshakeMessage));
register("LMC", true, directional(UNKNOWN, async(labyMod::handlePluginMessage)));
register("labymod3:main", true, directional(UNKNOWN, async(labyMod::handlePluginMessage)));
@@ -19,112 +19,79 @@
package de.steamwar.velocitycore.mods;
import com.lunarclient.apollo.ApolloManager;
import com.lunarclient.apollo.libs.protobuf.Any;
import com.lunarclient.apollo.libs.protobuf.InvalidProtocolBufferException;
import com.lunarclient.apollo.libs.protobuf.Message;
import com.lunarclient.apollo.mods.impl.*;
import com.lunarclient.apollo.module.ApolloModuleManager;
import com.lunarclient.apollo.module.ApolloModuleManagerImpl;
import com.lunarclient.apollo.module.modsetting.ModSettingModule;
import com.lunarclient.apollo.network.NetworkOptions;
import com.lunarclient.apollo.option.Options;
import com.lunarclient.apollo.player.AbstractApolloPlayer;
import com.google.protobuf.Any;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.Value;
import com.lunarclient.apollo.configurable.v1.ConfigurableSettings;
import com.lunarclient.apollo.configurable.v1.OverrideConfigurableSettingsMessage;
import com.lunarclient.apollo.player.v1.ModMessage;
import com.lunarclient.apollo.player.v1.PlayerHandshakeMessage;
import com.velocitypowered.api.event.connection.PluginMessageEvent;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.messages.MinecraftChannelIdentifier;
import de.steamwar.velocitycore.VelocityCore;
import de.steamwar.sql.Mod;
import lombok.AllArgsConstructor;
import de.steamwar.velocitycore.VelocityCore;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.function.Consumer;
import java.util.logging.Level;
public class Lunar {
// https://lunarclient.dev/apollo/introduction
// https://github.com/LunarClient/Apollo
private final ApolloModuleManager manager = new ApolloModuleManagerImpl().addModule(ModSettingModule.class);
public static final String CHANNEL = "lunar:apollo";
public Lunar() { //TODO seems defunct
Options modSettings = manager.getModule(ModSettingModule.class).getOptions();
modSettings.set(ModReplaymod.ENABLED, false); // TODO check if restrictions working
modSettings.set(ModFreelook.ENABLED, false);
modSettings.set(ModHypixelMod.ENABLED, false);
modSettings.set(ModMinimap.ENABLED, false);
modSettings.set(ModNametag.ENABLED, false);
modSettings.set(ModTeamView.ENABLED, false);
modSettings.set(ModTntCountdown.ENABLED, false);
modSettings.set(ModToggleSneak.TOGGLE_SNEAK_CONTAINER, false);
private final byte[] packet;
public Lunar() {
ConfigurableSettings.Builder builder = ConfigurableSettings.newBuilder()
.setApolloModule("mod_setting")
.setEnable(true);
for(String property : List.of(
"freelook.enabled", "hypixel-mod.enabled", "minimap.enabled", "nametag.enabled", "replaymod.enabled",
"team-view.enabled", "tnt-countdown.enabled", "toggle-sneak.toggle-sneak-container"
))
builder.putProperties(property, Value.newBuilder().setBoolValue(false).build());
packet = Any.pack(OverrideConfigurableSettingsMessage.newBuilder().addConfigurableSettings(builder).build()).toByteArray();
}
public void sendRestrictions(Player player) {
NetworkOptions.sendOptions(manager.getModules(), true, new SWApolloPlayer(player));
player.sendPluginMessage(MinecraftChannelIdentifier.from(CHANNEL), packet);
}
public void handlePluginMessage(PluginMessageEvent event) {
Player player = (Player) event.getSource();
Any packet;
try {
packet = Any.parseFrom(event.getData());
Any packet = Any.parseFrom(event.getData());
if(packet.is(PlayerHandshakeMessage.class))
handle((Player) event.getSource(), packet.unpack(PlayerHandshakeMessage.class));
} catch (InvalidProtocolBufferException e) {
throw new SecurityException(e);
}
}
handle(PlayerHandshakeMessage.class, packet, handshake -> {
List<Mod> mods = new ArrayList<>();
private void handle(Player player, PlayerHandshakeMessage packet) {
List<Mod> mods = new ArrayList<>();
for(ModMessage mod : handshake.getInstalledModsList()) {
switch(mod.getType()) {
case TYPE_FABRIC_INTERNAL, TYPE_FORGE_INTERNAL:
// Controlled with ModSettings
break;
case TYPE_FABRIC_EXTERNAL:
mods.add(Mod.getOrCreate(mod.getName(), Mod.Platform.FABRIC));
break;
case TYPE_FORGE_EXTERNAL:
mods.add(Mod.getOrCreate(mod.getName(), Mod.Platform.FORGE));
break;
default:
VelocityCore.getLogger().log(Level.INFO, () -> player.getUsername() + " uses Lunar mod with unknown type " + mod);
break;
}
for(ModMessage mod : packet.getInstalledModsList()) {
switch(mod.getType()) {
case TYPE_FABRIC_INTERNAL, TYPE_FORGE_INTERNAL:
// Controlled with ModSettings
break;
case TYPE_FABRIC_EXTERNAL:
mods.add(Mod.getOrCreate(mod.getName(), Mod.Platform.FABRIC));
break;
case TYPE_FORGE_EXTERNAL:
mods.add(Mod.getOrCreate(mod.getName(), Mod.Platform.FORGE));
break;
default:
VelocityCore.getLogger().log(Level.INFO, () -> player.getUsername() + " uses Lunar mod with unknown type " + mod);
break;
}
ModUtils.handleMods(player, mods);
});
}
private <T extends Message> void handle(Class<T> type, Any packet, Consumer<T> handler) {
try {
handler.accept(packet.unpack(type));
} catch (InvalidProtocolBufferException ignored) { /*ignored*/ }
}
@AllArgsConstructor
private static class SWApolloPlayer extends AbstractApolloPlayer {
private final Player player;
@Override
public void sendPacket(Message message) {
sendPacket(Any.pack(message).toByteArray());
}
@Override
public void sendPacket(byte[] bytes) {
player.sendPluginMessage(MinecraftChannelIdentifier.from(ApolloManager.PLUGIN_MESSAGE_CHANNEL), bytes);
}
@Override public UUID getUniqueId() { return player.getUniqueId(); }
@Override public String getName() { return player.getUsername(); }
@Override public boolean hasPermission(String s) { return player.hasPermission(s); }
@Override public Object getPlayer() { return player; }
ModUtils.handleMods(player, mods);
}
}
@@ -26,6 +26,7 @@ import de.steamwar.persistent.Bauserver;
import de.steamwar.persistent.Builderserver;
import de.steamwar.velocitycore.VelocityCore;
import de.steamwar.persistent.Subserver;
import de.steamwar.velocitycore.commands.DevCommand;
import de.steamwar.velocitycore.listeners.BasicListener;
import de.steamwar.velocitycore.listeners.PluginMessage;
@@ -56,7 +57,7 @@ public class ReplayMod extends BasicListener {
return;
Subserver subserver = Subserver.getSubserver(player.getCurrentServer().orElseThrow().getServerInfo());
if(subserver instanceof Builderserver || (subserver instanceof Bauserver bauserver && bauserver.getOwner().equals(player.getUniqueId())))
if(subserver instanceof Builderserver || (subserver instanceof Bauserver bauserver && bauserver.getOwner().equals(player.getUniqueId())) || DevCommand.getDevServers().containsValue(player.getCurrentServer().orElseThrow().getServer()))
return;
PluginMessage.send(player, "Replay|Restrict", "replaymod:restrict", restrict);
@@ -172,8 +172,10 @@ public class Tablist extends ChannelInboundHandlerAdapter {
sendTabPacket(current, null);
current.clear();
if(connection != null)
if(connection != null) {
connection.getConnection().getChannel().pipeline().remove(this);
connection = null;
}
}
@Override
@@ -22,10 +22,9 @@ package de.steamwar.velocitycore.tablist;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ServerConnection;
import com.velocitypowered.api.proxy.server.RegisteredServer;
import de.steamwar.persistent.Servertype;
import de.steamwar.messages.Chatter;
import de.steamwar.persistent.Subserver;
import de.steamwar.velocitycore.VelocityCore;
import de.steamwar.messages.Chatter;
import java.util.ArrayList;
import java.util.HashMap;
@@ -38,9 +37,8 @@ public class TablistBuild implements TablistPart {
private final Map<RegisteredServer, List<Item>> players = new HashMap<>();
public TablistBuild() {
for (RegisteredServer server : VelocityCore.getProxy().getAllServers()){
Subserver subserver = Subserver.getSubserver(server.getServerInfo());
if(server.getPlayersConnected().isEmpty() || subserver == null || subserver.getType() != Servertype.BAUSERVER)
for (RegisteredServer server : VelocityCore.getProxy().getAllServers()) {
if(server.getPlayersConnected().isEmpty() || !Subserver.isBuild(Subserver.getSubserver(server.getServerInfo())))
continue;
servers.add(server);
@@ -27,7 +27,6 @@ import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.server.RegisteredServer;
import de.steamwar.network.packets.common.FightInfoPacket;
import de.steamwar.persistent.Servertype;
import de.steamwar.persistent.Storage;
import de.steamwar.persistent.Subserver;
import de.steamwar.velocitycore.VelocityCore;
@@ -100,7 +99,7 @@ public class TablistManager extends BasicListener {
Subserver subserver = Subserver.getSubserver(server.getServerInfo());
if (fightInfos.containsKey(server))
subservers.add(new TablistServer(server, fightInfos.get(server)));
else if (subserver == null || subserver.getType() != Servertype.BAUSERVER)
else if (!Subserver.isBuild(subserver))
subservers.add(new TablistServer(server));
}
subservers.add(new TablistBuild());
@@ -23,12 +23,11 @@ import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ServerConnection;
import com.velocitypowered.api.proxy.server.RegisteredServer;
import com.velocitypowered.api.util.GameProfile;
import de.steamwar.persistent.Servertype;
import de.steamwar.persistent.Subserver;
import de.steamwar.velocitycore.VelocityCore;
import de.steamwar.messages.Chatter;
import de.steamwar.network.packets.common.FightInfoPacket;
import de.steamwar.persistent.Subserver;
import de.steamwar.sql.SteamwarUser;
import de.steamwar.velocitycore.VelocityCore;
import java.util.ArrayList;
import java.util.Collection;
@@ -94,8 +93,7 @@ public class TablistServer implements TablistPart {
return players.stream().map(item -> {
Player p = VelocityCore.getProxy().getPlayer(item.getUuid()).orElse(null);
if (p == null) return item;
Subserver subserver = Subserver.getSubserver(p.getCurrentServer().map(ServerConnection::getServerInfo).orElse(null));
if (subserver != null && subserver.getType() == Servertype.ARENA) return item;
if (Subserver.isArena(Subserver.getSubserver(p.getCurrentServer().map(ServerConnection::getServerInfo).orElse(null)))) return item;
if (SteamwarUser.get(p.getUniqueId()).getTeam() != team) return item;
return new Item(p, true);
});
@@ -37,6 +37,9 @@ class Groups {
private var groups: GroupsData = if (kGroupsFile.exists()) {
Cbor.decodeFromByteArray(kGroupsFile.readBytes())
} else {
if (!kGroupsFile.parentFile.exists()) {
kGroupsFile.parentFile.mkdirs()
}
kGroupsFile.createNewFile()
kGroupsFile.writeBytes(Cbor.encodeToByteArray(GroupsData(mutableListOf())))
@@ -234,7 +234,7 @@ fun Route.configureEventsRoute() {
}
}
suspend fun ApplicationCall.receiveEvent(fieldName: String = "event"): Event? {
suspend fun ApplicationCall.receiveEvent(fieldName: String = "id"): Event? {
val eventId = parameters[fieldName]?.toIntOrNull()
if (eventId == null) {
respond(HttpStatusCode.BadRequest, ResponseError("Invalid event ID"))
+3 -4
View File
@@ -107,8 +107,6 @@ dependencyResolutionManagement {
library("netty", "io.netty:netty-all:4.1.68.Final")
library("junit", "junit:junit:4.13.2")
library("hamcrest", "org.hamcrest:hamcrest:2.2")
library("jda", "net.dv8tion:JDA:5.2.0")
library("msgpack", "org.msgpack:msgpack-core:0.9.8")
library("classindex", "org.atteo.classindex:classindex:3.13")
library("spigotapi", "org.spigotmc:spigot-api:1.20-R0.1-SNAPSHOT")
@@ -140,8 +138,9 @@ dependencyResolutionManagement {
library("velocity", "de.steamwar:velocity:RELEASE")
library("velocityapi", "com.velocitypowered:velocity-api:3.3.0-SNAPSHOT")
library("apolloapi", "com.lunarclient:apollo-api:1.1.0")
library("apollocommon", "com.lunarclient:apollo-common:1.1.0")
library("jda", "net.dv8tion:JDA:5.2.0")
library("msgpack", "org.msgpack:msgpack-core:0.9.8")
library("apolloprotos", "com.lunarclient:apollo-protos:1.0-SNAPSHOT")
library("logback", "ch.qos.logback:logback-classic:1.5.6")
+6 -2
View File
@@ -7,7 +7,8 @@ artifacts:
"/binarys/fightsystem.jar": "FightSystem/build/libs/FightSystem-all.jar"
"/binarys/FightSystem_Standalone.jar": "FightSystem/FightSystem_Standalone/build/libs/FightSystem_Standalone-all.jar"
# KotlinCore !!
"/binarys/kotlincore.jar": "KotlinCore/build/libs/KotlinCore-all.jar"
"/binarys/tntleague.jar": "TNTLeague/build/libs/TNTLeague.jar"
"/binarys/lobbysystem2.0.jar": "LobbySystem/build/libs/LobbySystem.jar"
@@ -29,4 +30,7 @@ artifacts:
"/binarys/VelocityCore.jar": "VelocityCore/build/libs/VelocityCore-all.jar"
"/binarys/deployarena.py": "VelocityCore/deployarena.py"
"/binarys/website-api.jar": "WebsiteBackend/build/libs/WebsiteBackend-all.jar"
"/binarys/website-api.jar": "WebsiteBackend/build/libs/WebsiteBackend-all.jar"
release:
- "sudo systemctl restart api.service"