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; package de.steamwar.bausystem.features.region;
import de.steamwar.bausystem.BauSystem; import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.Permission;
import de.steamwar.bausystem.config.BauServer; import de.steamwar.bausystem.config.BauServer;
import de.steamwar.bausystem.region.GlobalRegion; import de.steamwar.bausystem.region.GlobalRegion;
import de.steamwar.bausystem.region.Region; 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.region.utils.RegionType;
import de.steamwar.bausystem.utils.PasteBuilder; import de.steamwar.bausystem.utils.PasteBuilder;
import de.steamwar.command.SWCommand; import de.steamwar.command.SWCommand;
import de.steamwar.command.TypeValidator;
import de.steamwar.linkage.Linked; import de.steamwar.linkage.Linked;
import de.steamwar.linkage.LinkedInstance; import de.steamwar.linkage.LinkedInstance;
import de.steamwar.sql.Punishment; import de.steamwar.sql.Punishment;
@@ -40,7 +38,6 @@ import de.steamwar.sql.SteamwarUser;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.io.IOException;
import java.util.logging.Level; import java.util.logging.Level;
@Linked @Linked
@@ -61,7 +58,7 @@ public class ResetCommand extends SWCommand {
PasteBuilder pasteBuilder = new PasteBuilder(new PasteBuilder.FileProvider(region.getResetFile(RegionType.NORMAL))) PasteBuilder pasteBuilder = new PasteBuilder(new PasteBuilder.FileProvider(region.getResetFile(RegionType.NORMAL)))
.color(region.getPlain(Flag.COLOR, ColorMode.class).getColor()); .color(region.getPlain(Flag.COLOR, ColorMode.class).getColor());
region.reset(pasteBuilder, RegionType.NORMAL, RegionExtensionType.NORMAL); region.reset(pasteBuilder, RegionType.NORMAL, RegionExtensionType.NORMAL);
for (Flag value : Flag.values()) { for (Flag value : Flag.getResetFlags()) {
region.set(value, value.getDefaultValue()); region.set(value, value.getDefaultValue());
} }
RegionUtils.message(region, "REGION_RESET_RESETED"); 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.region.flags.flagvalues.*;
import de.steamwar.bausystem.shared.EnumDisplay; import de.steamwar.bausystem.shared.EnumDisplay;
import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors;
@Getter @Getter
@AllArgsConstructor
public enum Flag implements EnumDisplay { public enum Flag implements EnumDisplay {
COLOR("FLAG_COLOR", ColorMode.class, ColorMode.YELLOW), COLOR("FLAG_COLOR", ColorMode.class, ColorMode.YELLOW, false),
TNT("FLAG_TNT", TNTMode.class, TNTMode.ONLY_TB), TNT("FLAG_TNT", TNTMode.class, TNTMode.ONLY_TB, true),
FIRE("FLAG_FIRE", FireMode.class, FireMode.ALLOW), FIRE("FLAG_FIRE", FireMode.class, FireMode.ALLOW, true),
FREEZE("FLAG_FREEZE", FreezeMode.class, FreezeMode.INACTIVE), FREEZE("FLAG_FREEZE", FreezeMode.class, FreezeMode.INACTIVE, true),
PROTECT("FLAG_PROTECT", ProtectMode.class, ProtectMode.ACTIVE), PROTECT("FLAG_PROTECT", ProtectMode.class, ProtectMode.ACTIVE, true),
ITEMS("FLAG_ITEMS", ItemMode.class, ItemMode.INACTIVE), ITEMS("FLAG_ITEMS", ItemMode.class, ItemMode.INACTIVE, true),
NO_GRAVITY("FLAG_NO_GRAVITY", NoGravityMode.class, NoGravityMode.INACTIVE), NO_GRAVITY("FLAG_NO_GRAVITY", NoGravityMode.class, NoGravityMode.INACTIVE, true),
; ;
@Getter @Getter
private static final Set<Flag> flags; private static final Set<Flag> flags;
@Getter
private static final Set<Flag> resetFlags;
static { static {
flags = EnumSet.allOf(Flag.class); flags = EnumSet.allOf(Flag.class);
resetFlags = flags.stream().filter(flag -> flag.reset).collect(Collectors.toUnmodifiableSet());
} }
private final String chatValue; private final String chatValue;
private final Class<? extends Value<?>> valueType; private final Class<? extends Value<?>> valueType;
private final Flag.Value<?> defaultValue; private final Flag.Value<?> defaultValue;
private final Value<?>[] values; private final boolean reset;
<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();
}
public Value<?> getFlagValueOf(final String name) { public Value<?> getFlagValueOf(final String name) {
return this.defaultValue.getValueOf(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 setResult = table.update(Table.PRIMARY, "Ergebnis");
private static final Statement setFight = table.update(Table.PRIMARY, "Fight"); 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 update = table.update(Table.PRIMARY, "startTime", "spielModus", "map", "teamBlue", "teamRed", "spectatePort");
private static final Statement delete = table.delete(Table.PRIMARY); 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.Material;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.util.Map; 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 Class<?> entityTracker = Reflection.getClass("{nms.server.level}.PlayerChunkMap$EntityTracker");
private static final Reflection.MethodInvoker updatePlayer = Reflection.getMethod(entityTracker, Core.getVersion() > 15 ? "b" : "updatePlayer", entityPlayer); private static final Reflection.MethodInvoker updatePlayer = Reflection.getMethod(entityTracker, Core.getVersion() > 15 ? "b" : "updatePlayer", entityPlayer);
@Override @Override
public void trackEntity(Player player, int entity) { public void trackEntity(Player player, Entity entity) {
Object tracker = trackers.get(entity); Object tracker = trackers.get(entity.getEntityId());
if(tracker != null) if(tracker != null)
updatePlayer.invoke(tracker, getPlayer.invoke(player)); updatePlayer.invoke(tracker, getPlayer.invoke(player));
} }
private static final Reflection.MethodInvoker clearPlayer = Reflection.getMethod(entityTracker, Core.getVersion() > 15 ? "a" : "clear", entityPlayer); private static final Reflection.MethodInvoker clearPlayer = Reflection.getMethod(entityTracker, Core.getVersion() > 15 ? "a" : "clear", entityPlayer);
@Override @Override
public void untrackEntity(Player player, int entity) { public void untrackEntity(Player player, Entity entity) {
Object tracker = trackers.get(entity); Object tracker = trackers.get(entity.getEntityId());
if(tracker != null) if(tracker != null)
clearPlayer.invoke(tracker, getPlayer.invoke(player)); clearPlayer.invoke(tracker, getPlayer.invoke(player));
} }
@@ -24,6 +24,7 @@ plugins {
dependencies { dependencies {
compileOnly(project(":SpigotCore", "default")) compileOnly(project(":SpigotCore", "default"))
compileOnly(project(":FightSystem:FightSystem_Core", "default")) compileOnly(project(":FightSystem:FightSystem_Core", "default"))
compileOnly(project(":FightSystem:FightSystem_14", "default"))
compileOnly(libs.spigotapi) 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.Material;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
public class BlockIdWrapper8 implements BlockIdWrapper { 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 get = Reflection.getTypedMethod(intHashMap, "get", Object.class, int.class);
private static final Reflection.MethodInvoker updatePlayer = Reflection.getMethod(entityTrackerEntry, "updatePlayer", entityPlayer); private static final Reflection.MethodInvoker updatePlayer = Reflection.getMethod(entityTrackerEntry, "updatePlayer", entityPlayer);
@Override @Override
public void trackEntity(Player player, int entity) { public void trackEntity(Player player, Entity entity) {
Object tracker = get.invoke(trackers, entity); Object tracker = get.invoke(trackers, entity.getEntityId());
if(tracker != null) if(tracker != null)
updatePlayer.invoke(tracker, getPlayer.invoke(player)); updatePlayer.invoke(tracker, getPlayer.invoke(player));
} }
private static final Reflection.MethodInvoker clearPlayer = Reflection.getMethod(entityTrackerEntry, "a", entityPlayer); private static final Reflection.MethodInvoker clearPlayer = Reflection.getMethod(entityTrackerEntry, "a", entityPlayer);
@Override @Override
public void untrackEntity(Player player, int entity) { public void untrackEntity(Player player, Entity entity) {
Object tracker = get.invoke(trackers, entity); Object tracker = get.invoke(trackers, entity.getEntityId());
if(tracker != null) if(tracker != null)
clearPlayer.invoke(tracker, getPlayer.invoke(player)); clearPlayer.invoke(tracker, getPlayer.invoke(player));
} }
@@ -83,7 +83,7 @@ public class Permanent implements Listener {
@EventHandler @EventHandler
public void onTpGM3(PlayerTeleportEvent e) { 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); e.setCancelled(true);
FightSystem.getMessage().sendPrefixless("NO_TELEPORT", e.getPlayer(), ChatMessageType.ACTION_BAR); FightSystem.getMessage().sendPrefixless("NO_TELEPORT", e.getPlayer(), ChatMessageType.ACTION_BAR);
e.getPlayer().kickPlayer(null); e.getPlayer().kickPlayer(null);
@@ -26,6 +26,7 @@ import de.steamwar.core.WorldEditWrapper;
import de.steamwar.entity.REntity; import de.steamwar.entity.REntity;
import de.steamwar.entity.REntityServer; import de.steamwar.entity.REntityServer;
import de.steamwar.entity.RPlayer; import de.steamwar.entity.RPlayer;
import de.steamwar.fightsystem.ArenaMode;
import de.steamwar.fightsystem.Config; import de.steamwar.fightsystem.Config;
import de.steamwar.fightsystem.FightSystem; import de.steamwar.fightsystem.FightSystem;
import de.steamwar.fightsystem.countdown.Countdown; import de.steamwar.fightsystem.countdown.Countdown;
@@ -244,6 +245,9 @@ public class PacketProcessor implements Listener {
SteamwarUser user = SteamwarUser.get(userId); SteamwarUser user = SteamwarUser.get(userId);
addREntity(entityId, new RPlayer(entityServer, user.getUUID(), user.getUserName(), Config.SpecSpawn)); addREntity(entityId, new RPlayer(entityServer, user.getUUID(), user.getUserName(), Config.SpecSpawn));
team.addEntry(user.getUserName()); 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.Material;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
public interface BlockIdWrapper { public interface BlockIdWrapper {
@@ -41,6 +42,6 @@ public interface BlockIdWrapper {
int blockToId(Block block); int blockToId(Block block);
void setBlock(World world, int x, int y, int z, int blockState); void setBlock(World world, int x, int y, int z, int blockState);
void trackEntity(Player player, int entity); void trackEntity(Player player, Entity entity);
void untrackEntity(Player player, int entity); void untrackEntity(Player player, Entity entity);
} }
@@ -35,24 +35,28 @@ import org.bukkit.entity.Player;
import java.util.*; import java.util.*;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.stream.IntStream;
public class Hull { public class Hull {
private static final IntVector[] NO_BRANCHES = new IntVector[0];
private static boolean isOccluding(Material material) { private static boolean isOccluding(Material material) {
return material.isOccluding() || Config.HiddenBlocks.contains(material); return material.isOccluding() || Config.HiddenBlocks.contains(material);
} }
private final Region region; private final Region region;
private final boolean groundVisible; private final boolean groundVisible;
private final IntVector[] directions;
private final BitSet occluding; private final BitSet occluding;
private final BitSet visibility; private final BitSet visibility;
private final Map<IntVector, Map<IntVector, BitSet>> blockVisibility = new HashMap<>(); private final HashMap<IntVector, BitSet> visibilityDirections = new HashMap<>(); // Contains the visible directions of each occluding visible block
private final Set<IntVector> uncoveredSurface = new HashSet<>(); private final HashSet<IntVector> uncoveredSurface = new HashSet<>();
private final HashSet<Player> players = new HashSet<>(); private final HashSet<Player> players = new HashSet<>();
private final Set<Entity> entities = new HashSet<>(); private final HashSet<Entity> entities = new HashSet<>();
private final Set<REntity> rentities = new HashSet<>(); private final HashSet<REntity> rentities = new HashSet<>();
public Hull(FightTeam team) { public Hull(FightTeam team) {
this.region = team.getSchemRegion(); this.region = team.getSchemRegion();
@@ -60,38 +64,14 @@ public class Hull {
this.occluding = new BitSet(region.volume()); this.occluding = new BitSet(region.volume());
this.visibility = new BitSet(region.volume()); this.visibility = new BitSet(region.volume());
IntVector[] directions; IntVector primaryDirection = new IntVector(0, 0, team.isBlue() == (Config.BlueToRedZ > 0) ? -1 : 1);
if (groundVisible) { directions = IntStream.range(0, 27)
directions = new IntVector[]{ .mapToObj(v -> new IntVector(v%3 -1, (v/3)%3 -1, v/9 -1))
new IntVector(1, 0, 0), .filter(v -> v.sqLength() == 1 || v.x*primaryDirection.x + v.y*primaryDirection.y + v.z*primaryDirection.z == 1) // Not pointing away from primary direction
new IntVector(-1, 0, 0), .toArray(IntVector[]::new);
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)
};
}
// Generate quadrants for each direction for(IntVector direction : directions)
for (IntVector direction : directions) { visibilityDirections.put(direction, new BitSet(region.volume()));
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);
}
} }
public boolean blockPrecise(Player player, int chunkX, int chunkY, int chunkZ) { public boolean blockPrecise(Player player, int chunkX, int chunkY, int chunkZ) {
@@ -109,29 +89,29 @@ public class Hull {
public void addPlayer(Player player) { public void addPlayer(Player player) {
if(players.add(player)) { if(players.add(player)) {
for(Entity entity : entities) for(Entity entity : entities)
BlockIdWrapper.impl.untrackEntity(player, entity.getEntityId()); BlockIdWrapper.impl.untrackEntity(player, entity);
} }
} }
public void removePlayer(Player player, boolean activeRemoval) { public void removePlayer(Player player, boolean activeRemoval) {
if(players.remove(player) && activeRemoval) { if(players.remove(player) && activeRemoval) {
for(Entity entity : entities) for(Entity entity : entities)
BlockIdWrapper.impl.trackEntity(player, entity.getEntityId()); BlockIdWrapper.impl.trackEntity(player, entity);
// techhider triggers block change sending // techhider triggers block change sending
} }
} }
public void checkEntity(Entity entity) { public void checkEntity(Entity entity) {
Location location = entity.getLocation(); 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)) { if(entities.add(entity)) {
for(Player player : players) for(Player player : players)
BlockIdWrapper.impl.untrackEntity(player, entity.getEntityId()); BlockIdWrapper.impl.untrackEntity(player, entity);
} }
} else { } else {
if(entities.remove(entity)) { if(entities.remove(entity)) {
for(Player player : players) 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) { public void checkREntity(REntity entity) {
Location location = new Location(Config.world, entity.getX(), entity.getY(), entity.getZ()); 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)) if(rentities.add(entity))
entity.hide(true); entity.hide(true);
} else { } else {
@@ -159,10 +139,8 @@ public class Hull {
visibility.clear(); visibility.clear();
occluding.clear(); occluding.clear();
uncoveredSurface.clear(); uncoveredSurface.clear();
for (Map<IntVector, BitSet> direction : blockVisibility.values()) { for(BitSet directionalVisibility : visibilityDirections.values())
for (BitSet set : direction.values()) directionalVisibility.clear();
set.clear();
}
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
region.forEach((x, y, z) -> { region.forEach((x, y, z) -> {
@@ -170,11 +148,7 @@ public class Hull {
if (isOccluding(Config.world.getBlockAt(x, y, z).getType())) if (isOccluding(Config.world.getBlockAt(x, y, z).getType()))
occluding.set(block.toId(region)); occluding.set(block.toId(region));
}); });
forEachBorder((root, direction) -> { forEachBorder((root, direction) -> uncoverBlocks(new NullList<>(), root, direction));
for (Map.Entry<IntVector, BitSet> quadrant : blockVisibility.get(direction).entrySet()) {
checkBlock(new NullList<>(), root, direction, quadrant.getKey(), quadrant.getValue());
}
});
FightSystem.getPlugin().getLogger().log(Level.INFO, () -> "[HullHider] initialisation finished: " + (System.currentTimeMillis() - start) + " ms, visible blocks: " + visibility.cardinality()); 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)) if (!occluding.get(id) || isOccluding(changedType))
return; return;
List<IntVector> uncovered = new ArrayList<>();
occluding.clear(id); occluding.clear(id);
for (Map.Entry<IntVector, Map<IntVector, BitSet>> direction : blockVisibility.entrySet()) { if(!visibility.get(id))
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())
return; return;
Set<IntVector> uncoveredSet = new HashSet<>(uncovered); List<IntVector> uncovered = new ArrayList<>();
Iterator<Entity> it = entities.iterator(); for(Map.Entry<IntVector, BitSet> directionalVisibility : visibilityDirections.entrySet()) {
while(it.hasNext()) { if(directionalVisibility.getValue().get(id)) {
Entity entity = it.next(); directionalVisibility.getValue().clear(id);
if(uncoveredSet.contains(new IntVector(entity.getLocation()))) { //TODO more precise uncoverBlocks(uncovered, root, directionalVisibility.getKey());
it.remove();
for(Player player : players)
BlockIdWrapper.impl.trackEntity(player, entity.getEntityId());
} }
} }
Iterator<REntity> rit = rentities.iterator(); uncoveredSurface.addAll(new HashSet<>(uncovered));
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.remove(root); 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)) if (block.notInRegion(region))
return; return;
int id = block.toId(region); int id = block.toId(region);
if (quadVisibility.get(id)) if(directionalVisibility.get(id))
return; return;
directionalVisibility.set(id);
quadVisibility.set(id);
if (!visibility.get(id)) { if (!visibility.get(id)) {
visibility.set(id); visibility.set(id);
uncovered.add(block); uncovered.add(block);
@@ -283,31 +246,9 @@ public class Hull {
if (occluding.get(id)) if (occluding.get(id))
return; return;
IntVector neighbour = block.add(direction); uncoverBlocks(uncovered, block.add(direction), direction, directionalVisibility, branchDirections);
checkBlock(uncovered, neighbour, direction, quadrant, quadVisibility); for(IntVector branchDirection : branchDirections)
boolean neigbourTransparent = boundedNonOccluding(neighbour); uncoverBlocks(uncovered, block.add(branchDirection), branchDirection, visibilityDirections.get(branchDirection), NO_BRANCHES);
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)));
} }
@@ -340,6 +281,10 @@ public class Hull {
return add(v.x, v.y, v.z); return add(v.x, v.y, v.z);
} }
public int sqLength() {
return x*x + y*y + z*z;
}
@Override @Override
public int hashCode() { public int hashCode() {
return y << 24 ^ x << 12 ^ z; return y << 24 ^ x << 12 ^ z;
+2
View File
@@ -32,4 +32,6 @@ tasks.shadowJar {
dependencies { dependencies {
compileOnly(libs.paperapi21) compileOnly(libs.paperapi21)
compileOnly(libs.nms21)
compileOnly(project(":SpigotCore"))
} }
@@ -32,6 +32,7 @@ class KotlinCore : JavaPlugin() {
} }
override fun onEnable() { override fun onEnable() {
} }
override fun onDisable() { 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.InventoryClickEvent
import org.bukkit.event.inventory.InventoryCloseEvent 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.Location
import org.bukkit.block.Block 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_PUNISHED=§cYou are not allowed to download schematics: §f§l{0}
UTIL_DOWNLOAD_NOT_OWN=§cYou may download only your own schematics UTIL_DOWNLOAD_NOT_OWN=§cYou may download only your own schematics
UTIL_DOWNLOAD_LINK=Your download link: 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_NOT_OWN=§cYou can only submit your own schematics
UTIL_TYPE_DIR=§cYou cannot submit folders UTIL_TYPE_DIR=§cYou cannot submit folders
UTIL_TYPE_NOT_ASSIGNABLE=§cSchematics cannot be changed for this type 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_DONE=§aChange schematic type
UTIL_TYPE_FIGHT_ALREADY=§cYou have already submitted this schematic 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_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_ERROR=§cThe Schematic is not compliant with the rules
UTIL_TYPE_EXTEND=§aThe preparation server is starting UTIL_TYPE_EXTEND=§aThe preparation server is starting
UTIL_SUBMIT_TITLE=Extend Schematic 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_PUNISHED=§cDu darf keine Schematics Downloaden: §f§l{0}
UTIL_DOWNLOAD_NOT_OWN=§cDu darfst nur deine eigenen Schematics herunterladen UTIL_DOWNLOAD_NOT_OWN=§cDu darfst nur deine eigenen Schematics herunterladen
UTIL_DOWNLOAD_LINK=Dein Download Link: 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_NOT_OWN=§cDu kannst nur deine eigenen Schematics einsenden
UTIL_TYPE_DIR=§cDu kannst keine Ordner einsenden UTIL_TYPE_DIR=§cDu kannst keine Ordner einsenden
UTIL_TYPE_NOT_ASSIGNABLE=§cZu diesem Typen können keine Schematics geändert werden 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_DONE=§aSchematictyp geändert
UTIL_TYPE_FIGHT_ALREADY=§cDu hast diese Schematic bereits eingesendet 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_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_ERROR=§cDie Schematic ist nicht regelkonform
UTIL_TYPE_EXTEND=§aDer Vorbereitungsserver wird gestartet UTIL_TYPE_EXTEND=§aDer Vorbereitungsserver wird gestartet
UTIL_SUBMIT_TITLE=Schematic ausfahren 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) { public static void changeType(Player player, SchematicNode node, SchematicType type, SchematicCommand.Extend extend) {
SteamwarUser user = getUser(player); 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()) { if (node.getOwner() != user.getId()) {
SchematicSystem.MESSAGE.send("UTIL_TYPE_NOT_OWN", player); SchematicSystem.MESSAGE.send("UTIL_TYPE_NOT_OWN", player);
return; return;
@@ -430,11 +425,26 @@ public class SchematicCommandUtils {
node.setSchemtype(type); node.setSchemtype(type);
SchematicSystem.MESSAGE.send("UTIL_TYPE_DONE", player); SchematicSystem.MESSAGE.send("UTIL_TYPE_DONE", player);
} else if (type.fightType()) { } 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()) { if (node.getSchemtype().check()) {
SchematicSystem.MESSAGE.send("UTIL_TYPE_FIGHT_ALREADY", player); SchematicSystem.MESSAGE.send("UTIL_TYPE_FIGHT_ALREADY", player);
return; 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); CheckSchemType checkSchemType = CheckSchemType.get(type);
if (checkSchemType.isAfterDeadline()) { if (checkSchemType.isAfterDeadline()) {
SchematicSystem.MESSAGE.send("UTIL_TYPE_AFTER_DEADLINE", player, checkSchemType.getDeadline()); 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 { plugins {
steamwar.kotlin 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 package de.steamwar.tntleague
import de.steamwar.message.Message
import de.steamwar.tntleague.command.AcceptCommand import de.steamwar.tntleague.command.AcceptCommand
import de.steamwar.tntleague.command.InviteCommand import de.steamwar.tntleague.command.InviteCommand
import de.steamwar.tntleague.command.LeaveCommand import de.steamwar.tntleague.command.LeaveCommand
import de.steamwar.tntleague.command.RemoveCommand import de.steamwar.tntleague.command.RemoveCommand
import de.steamwar.tntleague.events.GlobalListener import de.steamwar.tntleague.events.GlobalListener
import de.steamwar.tntleague.events.LobbyListener import de.steamwar.tntleague.events.LobbyListener
import net.kyori.adventure.key.Key import de.steamwar.tntleague.game.TNTLeagueTeam
import net.kyori.adventure.translation.GlobalTranslator
import net.kyori.adventure.translation.TranslationRegistry
import net.kyori.adventure.util.UTF8ResourceBundleControl
import org.bukkit.plugin.java.JavaPlugin import org.bukkit.plugin.java.JavaPlugin
import java.util.*
lateinit var plugin: TNTLeague lateinit var plugin: TNTLeague
lateinit var message: Message
class TNTLeague : JavaPlugin() { class TNTLeague : JavaPlugin() {
init { init {
@@ -21,19 +38,7 @@ class TNTLeague : JavaPlugin() {
} }
override fun onEnable() { override fun onEnable() {
saveResource("config.yml", false) message = Message("de.steamwar.tntleague.TNTLeague", classLoader)
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)
server.pluginManager.registerEvents(LobbyListener, this) server.pluginManager.registerEvents(LobbyListener, this)
server.pluginManager.registerEvents(GlobalListener, this) server.pluginManager.registerEvents(GlobalListener, this)
@@ -46,3 +51,8 @@ class TNTLeague : JavaPlugin() {
LeaveCommand.register() 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.SWCommand
import de.steamwar.command.TypeValidator import de.steamwar.command.TypeValidator
import de.steamwar.tntleague.colorByTeam
import de.steamwar.tntleague.game.TNTLeagueGame import de.steamwar.tntleague.game.TNTLeagueGame
import de.steamwar.tntleague.util.* import de.steamwar.tntleague.message
import net.kyori.adventure.text.event.ClickEvent import net.md_5.bungee.api.chat.ClickEvent
import net.kyori.adventure.text.event.HoverEvent
import org.bukkit.entity.Player import org.bukkit.entity.Player
object InviteCommand: SWCommand("invite") { object InviteCommand: SWCommand("invite") {
@@ -37,20 +37,15 @@ object InviteCommand: SWCommand("invite") {
val team = TNTLeagueGame.getTeam(sender)!! val team = TNTLeagueGame.getTeam(sender)!!
team.invites.add(target) team.invites.add(target)
target.sendMessage(translate("invited", sender.name.yellow(), translate(team.name).colorByTeam(team)).basic().clickEvent( message
ClickEvent.callback { .send("INVITED", target, message.parse("INVITED_HOVER", target, team.name.colorByTeam(team)),
if (target !in team.invites) return@callback ClickEvent(ClickEvent.Action.RUN_COMMAND, "/accept " + sender.name), sender.name, team.name.colorByTeam(team), )
team.invites.remove(target) message.send("INVITED_PLAYER", sender, target.name)
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())
} }
@Validator("isLeader", local = false) @Validator("isLeader", local = false)
fun isLeader(): TypeValidator<Player> { fun isLeader(): TypeValidator<Player> {
return TypeValidator<Player> { _, player, _ -> TNTLeagueGame.getTeam(player)?.leader == player} return TypeValidator<Player> { _, player, _ -> TNTLeagueGame.getTeam(player)?.leader == player}
} }
} }
@@ -26,5 +26,5 @@ import org.bukkit.entity.Player
object LeaveCommand: SWCommand("leave", "l") { object LeaveCommand: SWCommand("leave", "l") {
@Register @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 package de.steamwar.tntleague.config
import de.steamwar.tntleague.plugin 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 package de.steamwar.tntleague.config
import de.steamwar.tntleague.plugin import de.steamwar.tntleague.plugin
import de.steamwar.tntleague.util.Area import de.steamwar.kotlin.util.Area
import de.steamwar.tntleague.util.translate import net.kyori.adventure.text.Component
import org.bukkit.Bukkit
import org.bukkit.Location import org.bukkit.Location
import org.bukkit.Material import org.bukkit.Material
import org.bukkit.configuration.ConfigurationSection import org.bukkit.configuration.ConfigurationSection
import org.bukkit.configuration.file.YamlConfiguration import org.bukkit.configuration.file.YamlConfiguration
import org.bukkit.entity.Villager
import org.bukkit.entity.WanderingTrader import org.bukkit.entity.WanderingTrader
import java.io.File import java.io.File
import kotlin.properties.Delegates
val world by lazy { plugin.server.worlds.first()!! } val world by lazy { plugin.server.worlds.first()!! }
@@ -33,12 +53,25 @@ object TNTLeagueWorldConfig {
) )
} }
val blueTeam: TeamConfig = TeamConfig.fromConfig(config.getConfigurationSection("blueTeam")!!) lateinit var blueTeam: TeamConfig
val redTeam: TeamConfig = TeamConfig.fromConfig(config.getConfigurationSection("redTeam")!!) lateinit var redTeam: TeamConfig
val lobby: Location = config.getLocation("lobby", blueTeam.spawnLocation.clone().add(redTeam.spawnLocation).multiply(0.5))!! lateinit var lobby: Location
val targetMaterial: Material = Material.matchMaterial(config.getString("targetMaterial", "IRON_BLOCK")!!)!! lateinit var targetMaterial: Material
val minHeight: Int = config.getInt("minHeight", 0) var minHeight by Delegates.notNull<Int>()
val target: Int = config.getInt("target", -1) 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 @JvmRecord
data class TeamConfig( data class TeamConfig(
@@ -49,11 +82,11 @@ object TNTLeagueWorldConfig {
) { ) {
companion object { companion object {
fun fromConfig(config: ConfigurationSection): TeamConfig { fun fromConfig(config: ConfigurationSection): TeamConfig {
val spawnLocation = config.getLocation("spawn")!! val spawnLocation = config.getWorldLocation("spawn")
val dealerSpawn = config.getLocation("dealerSpawn")!! val dealerSpawn = config.getWorldLocation("dealerSpawn")
val itemSpawn = config.getLocation("itemSpawn")!! val itemSpawn = config.getWorldLocation("itemSpawn")
val targetPos1 = config.getLocation("targetMin")!! val targetPos1 = config.getWorldLocation("targetMin")
val targetPos2 = config.getLocation("targetMax")!! val targetPos2 = config.getWorldLocation("targetMax")
spawnDealer(dealerSpawn) spawnDealer(dealerSpawn)
@@ -62,7 +95,7 @@ object TNTLeagueWorldConfig {
private fun spawnDealer(loc: Location) = world.spawn(loc, WanderingTrader::class.java) private fun spawnDealer(loc: Location) = world.spawn(loc, WanderingTrader::class.java)
.apply { .apply {
customName(translate("dealer")) customName(Component.text("Shop"))
isCustomNameVisible = false isCustomNameVisible = false
isInvulnerable = true isInvulnerable = true
isSilent = 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 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 package de.steamwar.tntleague.events
import de.steamwar.tntleague.colorByTeam
import de.steamwar.tntleague.config.TNTLeagueWorldConfig import de.steamwar.tntleague.config.TNTLeagueWorldConfig
import de.steamwar.tntleague.game.TNTLeagueGame import de.steamwar.tntleague.game.TNTLeagueGame
import de.steamwar.tntleague.game.TNTLeagueTeam 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.plugin
import de.steamwar.tntleague.util.* import org.bukkit.Bukkit
import io.papermc.paper.event.player.AsyncChatEvent
import org.bukkit.GameMode import org.bukkit.GameMode
import org.bukkit.Material import org.bukkit.Material
import org.bukkit.event.EventHandler import org.bukkit.event.EventHandler
import org.bukkit.event.EventPriority import org.bukkit.event.EventPriority
import org.bukkit.event.Listener import org.bukkit.event.Listener
import org.bukkit.event.entity.PlayerDeathEvent import org.bukkit.event.entity.PlayerDeathEvent
import org.bukkit.event.inventory.CraftItemEvent
import org.bukkit.event.inventory.InventoryClickEvent import org.bukkit.event.inventory.InventoryClickEvent
import org.bukkit.event.player.PlayerJoinEvent import org.bukkit.event.player.PlayerJoinEvent
import org.bukkit.event.player.PlayerMoveEvent import org.bukkit.event.player.PlayerMoveEvent
@@ -27,7 +48,7 @@ object GlobalListener: Listener {
with(e.player) { with(e.player) {
teleport(TNTLeagueWorldConfig.lobby) teleport(TNTLeagueWorldConfig.lobby)
inventory.clear() inventory.clear()
plugin.server.broadcast(translate("join", name.bold()).basic()) message.broadcast("JOIN", name)
isOp = false isOp = false
gameMode = GameMode.SPECTATOR gameMode = GameMode.SPECTATOR
respawnLocation = TNTLeagueWorldConfig.lobby respawnLocation = TNTLeagueWorldConfig.lobby
@@ -37,8 +58,17 @@ object GlobalListener: Listener {
@EventHandler(priority = EventPriority.HIGHEST) @EventHandler(priority = EventPriority.HIGHEST)
fun onPlayerQuit(e: PlayerQuitEvent) { fun onPlayerQuit(e: PlayerQuitEvent) {
e.quitMessage(null) 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) 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) @EventHandler(priority = EventPriority.LOWEST)
@@ -67,6 +97,7 @@ object GlobalListener: Listener {
fun onPlayerDeath(e: PlayerDeathEvent) { fun onPlayerDeath(e: PlayerDeathEvent) {
e.deathMessage(null) e.deathMessage(null)
e.drops.clear() e.drops.clear()
e.keepInventory = true
e.itemsToKeep.removeIf { it.type != Material.DIAMOND_PICKAXE } e.itemsToKeep.removeIf { it.type != Material.DIAMOND_PICKAXE }
} }
@@ -78,11 +109,4 @@ object GlobalListener: Listener {
null -> e.respawnLocation = TNTLeagueWorldConfig.lobby 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 package de.steamwar.tntleague.events
import de.steamwar.scoreboard.SWScoreboard import de.steamwar.scoreboard.SWScoreboard
@@ -13,12 +32,11 @@ import org.bukkit.entity.EntityType
import org.bukkit.event.EventHandler import org.bukkit.event.EventHandler
import org.bukkit.event.Listener import org.bukkit.event.Listener
import org.bukkit.event.entity.EntityExplodeEvent 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.PlayerDropItemEvent
import org.bukkit.event.player.PlayerInteractEntityEvent import org.bukkit.event.player.PlayerInteractEntityEvent
import org.bukkit.event.player.PlayerJoinEvent import org.bukkit.event.player.PlayerJoinEvent
import org.bukkit.event.player.PlayerMoveEvent import org.bukkit.event.player.PlayerMoveEvent
import org.bukkit.event.player.PlayerQuitEvent
object IngameListener: Listener { object IngameListener: Listener {
@@ -26,7 +44,7 @@ object IngameListener: Listener {
fun onEntityInteract(e: PlayerInteractEntityEvent) { fun onEntityInteract(e: PlayerInteractEntityEvent) {
if (e.player.gameMode == GameMode.SPECTATOR) return if (e.player.gameMode == GameMode.SPECTATOR) return
if(e.rightClicked.type == EntityType.VILLAGER) { if(e.rightClicked.type == EntityType.WANDERING_TRADER) {
e.isCancelled = true e.isCancelled = true
e.player.openInventory(DealerInventory(e.player).getInventory()) 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? = private fun getTeamByTargetLocation(location: Location): TNTLeagueTeam? =
when (location) { when (location) {
in TNTLeagueWorldConfig.redTeam.target -> TNTLeagueGame.redTeam 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 package de.steamwar.tntleague.events
import de.steamwar.tntleague.game.TNTLeagueGame import de.steamwar.tntleague.game.TNTLeagueGame
import de.steamwar.tntleague.plugin import org.bukkit.GameMode
import de.steamwar.tntleague.util.basic import org.bukkit.entity.EntityType
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.event.EventHandler import org.bukkit.event.EventHandler
import org.bukkit.event.EventPriority import org.bukkit.event.EventPriority
import org.bukkit.event.Listener import org.bukkit.event.Listener
import org.bukkit.event.block.Action
import org.bukkit.event.entity.EntityDamageEvent import org.bukkit.event.entity.EntityDamageEvent
import org.bukkit.event.inventory.InventoryClickEvent import org.bukkit.event.inventory.InventoryClickEvent
import org.bukkit.event.player.PlayerDropItemEvent import org.bukkit.event.player.*
import org.bukkit.event.player.PlayerInteractEvent
import org.bukkit.event.player.PlayerJoinEvent
import org.bukkit.event.player.PlayerQuitEvent
object LobbyListener: Listener { object LobbyListener: Listener {
@@ -30,8 +41,7 @@ object LobbyListener: Listener {
@EventHandler(priority = EventPriority.LOWEST) @EventHandler(priority = EventPriority.LOWEST)
fun onPlayerQuit(e: PlayerQuitEvent) { fun onPlayerQuit(e: PlayerQuitEvent) {
val team = TNTLeagueGame.getTeam(e.player) ?: return TNTLeagueGame.playerLeave(e.player)
team.leave(e.player)
} }
@EventHandler @EventHandler
@@ -58,4 +68,13 @@ object LobbyListener: Listener {
e.isCancelled = true 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 package de.steamwar.tntleague.game
import de.steamwar.kotlin.util.Area
import de.steamwar.scoreboard.SWScoreboard import de.steamwar.scoreboard.SWScoreboard
import de.steamwar.sql.Fight import de.steamwar.sql.Fight
import de.steamwar.sql.FightPlayer import de.steamwar.sql.FightPlayer
import de.steamwar.sql.SteamwarUser import de.steamwar.sql.SteamwarUser
import de.steamwar.tntleague.colorByTeam
import de.steamwar.tntleague.config.TNTLeagueConfig import de.steamwar.tntleague.config.TNTLeagueConfig
import de.steamwar.tntleague.config.TNTLeagueWorldConfig import de.steamwar.tntleague.config.TNTLeagueWorldConfig
import de.steamwar.tntleague.config.world 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.IngameListener
import de.steamwar.tntleague.events.LobbyListener import de.steamwar.tntleague.events.LobbyListener
import de.steamwar.tntleague.inventory.DealerInventory import de.steamwar.tntleague.inventory.DealerInventory
import de.steamwar.tntleague.message
import de.steamwar.tntleague.plugin import de.steamwar.tntleague.plugin
import de.steamwar.tntleague.util.* import de.steamwar.tntleague.util.*
import net.kyori.adventure.bossbar.BossBar
import net.kyori.adventure.sound.Sound
import org.bukkit.GameMode import org.bukkit.GameMode
import org.bukkit.Location import org.bukkit.Location
import org.bukkit.Material import org.bukkit.Material
import org.bukkit.block.data.type.TNT import org.bukkit.Sound
import org.bukkit.entity.Entity
import org.bukkit.entity.Item import org.bukkit.entity.Item
import org.bukkit.entity.Player import org.bukkit.entity.Player
import org.bukkit.entity.TNTPrimed import org.bukkit.entity.TNTPrimed
import org.bukkit.entity.Villager
import org.bukkit.event.HandlerList import org.bukkit.event.HandlerList
import org.bukkit.event.Listener import org.bukkit.event.Listener
import org.bukkit.inventory.ItemStack import org.bukkit.inventory.ItemStack
@@ -62,7 +80,7 @@ object TNTLeagueGame {
blueTeam.start() blueTeam.start()
redTeam.start() redTeam.start()
plugin.server.broadcast(translate("gameStarted").success()) message.broadcast("GAME_STARTED")
val tnt = ItemStack(Material.TNT) val tnt = ItemStack(Material.TNT)
@@ -82,13 +100,18 @@ object TNTLeagueGame {
timerTask = plugin.server.scheduler.runTaskTimer(plugin, bukkit { timerTask = plugin.server.scheduler.runTaskTimer(plugin, bukkit {
gameTimeRemaining-- gameTimeRemaining--
if (gameTimeRemaining == 0) { 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 return@bukkit
} }
if (gameTimeRemaining % 300 == 0) { if (gameTimeRemaining % 300 == 0) {
plugin.server.broadcast(translate("timeRemaining", (gameTimeRemaining / 60).toString().yellow()).basic()) message.broadcast("TIME_REMAINING", (gameTimeRemaining / 60))
plugin.server.onlinePlayers.forEach { it.playSound(Sound.sound(org.bukkit.Sound.BLOCK_NOTE_BLOCK_PLING.key, Sound.Source.MASTER, 1f, 1f)) } plugin.server.onlinePlayers.forEach { it.playSound(it.location, Sound.BLOCK_NOTE_BLOCK_PLING, 1f, 1f) }
} }
}, 20, 20) }, 20, 20)
} }
@@ -102,10 +125,10 @@ object TNTLeagueGame {
plugin.server.onlinePlayers.forEach { plugin.server.onlinePlayers.forEach {
it.gameMode = GameMode.SPECTATOR it.gameMode = GameMode.SPECTATOR
SWScoreboard.impl.removeScoreboard(it) 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() spawnerTask.cancel()
@@ -116,7 +139,7 @@ object TNTLeagueGame {
plugin.server.shutdown() plugin.server.shutdown()
} }
plugin.server.broadcast(translate("shutdown", shutdown.toString().yellow()).basic()) message.broadcast("SHUTDOWN", shutdown)
shutdown-- shutdown--
}, 20, 20) }, 20, 20)
@@ -135,19 +158,15 @@ object TNTLeagueGame {
state = GameState.STARTING state = GameState.STARTING
var countdown = TNTLeagueConfig.config.startDelay var countdown = TNTLeagueConfig.config.startDelay
plugin.server.broadcast(translate("gameStarting", countdown.toString().yellow()).basic()) message.broadcast("GAME_STARTING", countdown.toString())
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) }
task = plugin.server.scheduler.scheduleSyncRepeatingTask(plugin, { 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)) } plugin.server.onlinePlayers.forEach { it.playSound(it.location, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1f, 1f) }
if (countdown-- == 0) { if (--countdown == 0) {
plugin.server.onlinePlayers.forEach { it.hideBossBar(bar) } plugin.server.onlinePlayers.forEach { it.level = 0 }
task = task?.also { plugin.server.scheduler.cancelTask(it) }.let { null } task = task?.also { plugin.server.scheduler.cancelTask(it) }.let { null }
setup() setup()
} else { } else {
bar.name(translate("gameStart", countdown.toString().yellow()).gray()) plugin.server.onlinePlayers.forEach { it.level = countdown }
bar.progress((TNTLeagueConfig.config.startDelay - countdown) / TNTLeagueConfig.config.startDelay.toFloat())
plugin.server.onlinePlayers.filter { !it.activeBossBars().contains(bar) }.forEach { bar.addViewer(it) }
} }
}, 20, 20) }, 20, 20)
@@ -161,10 +180,7 @@ object TNTLeagueGame {
blueTeam.invites.remove(player) blueTeam.invites.remove(player)
redTeam.invites.remove(player) redTeam.invites.remove(player)
getTeam(player)?.apply { getTeam(player)?.apply {
members.remove(player) remove(player)
if (leader == player) {
win(this.opposite, WinReason.LEAVE)
}
} }
} }
@@ -173,7 +189,6 @@ object TNTLeagueGame {
if (state == GameState.STARTING) { if (state == GameState.STARTING) {
task = task?.also { plugin.server.scheduler.cancelTask(it) }.let { null } task = task?.also { plugin.server.scheduler.cancelTask(it) }.let { null }
plugin.server.onlinePlayers.forEach { p -> p.activeBossBars().forEach { it.removeViewer(p) } }
state = GameState.LOBBY state = GameState.LOBBY
} }
} }
@@ -181,16 +196,14 @@ object TNTLeagueGame {
fun win(tntLeagueTeam: TNTLeagueTeam, reason: WinReason) { fun win(tntLeagueTeam: TNTLeagueTeam, reason: WinReason) {
if (state != GameState.RUNNING) return if (state != GameState.RUNNING) return
end() end()
plugin.server.broadcast(translate("teamWin", translate(tntLeagueTeam.name).color(tntLeagueTeam.color)).success()) plugin.server.onlinePlayers.forEach { message.send("TEAM_WIN", it, message.parse(tntLeagueTeam.name, it).colorByTeam(tntLeagueTeam)) }
statistic(tntLeagueTeam, reason)
explode(tntLeagueTeam.opposite) explode(tntLeagueTeam.opposite)
} }
fun draw(reason: WinReason) { fun draw(reason: WinReason) {
if (state != GameState.RUNNING) return if (state != GameState.RUNNING) return
end() end()
plugin.server.broadcast(translate("draw").success()) message.broadcast("DRAW")
statistic(null, reason)
} }
fun explode(team: TNTLeagueTeam) { 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) { private fun addTeamMember(team: TNTLeagueTeam, fightId: Int) {
team.members.filter { team.leader != it } team.members.filter { team.leader != it }
.forEach { .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 package de.steamwar.tntleague.game
import de.steamwar.tntleague.colorByTeam
import de.steamwar.tntleague.config.TNTLeagueWorldConfig import de.steamwar.tntleague.config.TNTLeagueWorldConfig
import de.steamwar.tntleague.config.targetedBlocks 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.plugin
import de.steamwar.tntleague.util.* import net.kyori.adventure.text.Component
import net.kyori.adventure.sound.Sound
import net.kyori.adventure.text.format.NamedTextColor
import net.kyori.adventure.text.format.TextColor
import org.bukkit.GameMode import org.bukkit.GameMode
import org.bukkit.Material import org.bukkit.Material
import org.bukkit.Sound
import org.bukkit.enchantments.Enchantment import org.bukkit.enchantments.Enchantment
import org.bukkit.entity.Player import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack import org.bukkit.inventory.ItemStack
import java.awt.Color.green
data class TNTLeagueTeam(val config: TNTLeagueWorldConfig.TeamConfig, private val team: Team) { 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 invites = mutableListOf<Player>()
val name: String val name: String
get() = team.name.lowercase() get() = team.name.uppercase()
val color: TextColor val color: Char
get() = team.color get() = team.color
var isReady: Boolean = false var isReady: Boolean = false
set(value) { set(value) {
field = value field = value
leader?.inventory?.setItem(4, readyItem()) 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 -> message.broadcastActionbar(if (value) "IS_READY" else "IS_NOT_READY", name.colorByTeam(this))
if (value) {
cmp.green()
} else {
cmp.red()
}
}) }
if (value && opposite.isReady) { if (value && opposite.isReady) {
TNTLeagueGame.checkStart() TNTLeagueGame.checkStart()
@@ -63,6 +77,8 @@ data class TNTLeagueTeam(val config: TNTLeagueWorldConfig.TeamConfig, private va
} }
} }
var coins: Int = 0
val opposite: TNTLeagueTeam val opposite: TNTLeagueTeam
get() = when (team) { get() = when (team) {
Team.BLUE -> TNTLeagueGame.redTeam Team.BLUE -> TNTLeagueGame.redTeam
@@ -76,7 +92,7 @@ data class TNTLeagueTeam(val config: TNTLeagueWorldConfig.TeamConfig, private va
teleport(config.spawnLocation) teleport(config.spawnLocation)
gameMode = GameMode.ADVENTURE gameMode = GameMode.ADVENTURE
inventory.clear() 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) { if (leader == null) {
@@ -89,13 +105,13 @@ data class TNTLeagueTeam(val config: TNTLeagueWorldConfig.TeamConfig, private va
fun readyItem() = if (isReady) { fun readyItem() = if (isReady) {
ItemStack.of(Material.LIME_DYE).apply { ItemStack.of(Material.LIME_DYE).apply {
itemMeta = itemMeta.apply { itemMeta = itemMeta.apply {
displayName(translate("ready").green().translate(leader!!)) displayName(Component.text(message.parse("READY", leader!!)))
} }
} }
} else { } else {
ItemStack.of(Material.RED_DYE).apply { ItemStack.of(Material.RED_DYE).apply {
itemMeta = itemMeta.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) { fun leave(player: Player) {
if (TNTLeagueGame.state == TNTLeagueGame.GameState.RUNNING) { members.remove(player)
TNTLeagueGame.playerLeave(player) if (TNTLeagueGame.state != TNTLeagueGame.GameState.RUNNING) {
} else {
members.remove(player)
if (members.isEmpty()) { if (members.isEmpty()) {
plugin.server.onlinePlayers.firstOrNull { it != player && TNTLeagueGame.getTeam(it) == null }?.run { plugin.server.onlinePlayers.firstOrNull { it != player && TNTLeagueGame.getTeam(it) == null }?.run {
members.add(this) members.add(this)
@@ -125,6 +138,14 @@ data class TNTLeagueTeam(val config: TNTLeagueWorldConfig.TeamConfig, private va
} }
if (leader == player) { if (leader == player) {
leader = members.firstOrNull() 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) teleport(TNTLeagueWorldConfig.lobby)
gameMode = GameMode.SPECTATOR gameMode = GameMode.SPECTATOR
inventory.clear() 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) { enum class Team(val color: Char) {
BLUE(NamedTextColor.BLUE), BLUE('9'),
RED(NamedTextColor.RED); 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 package de.steamwar.tntleague.inventory
import de.steamwar.kotlin.inventory.SWInventoryHolder
import de.steamwar.tntleague.config.TNTLeagueConfig 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.plugin
import de.steamwar.tntleague.util.*
import net.kyori.adventure.sound.Sound
import net.kyori.adventure.text.Component 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 net.kyori.adventure.text.format.TextDecoration
import org.bukkit.Material import org.bukkit.Material
import org.bukkit.NamespacedKey import org.bukkit.NamespacedKey
import org.bukkit.Sound
import org.bukkit.entity.Player import org.bukkit.entity.Player
import org.bukkit.inventory.Inventory import org.bukkit.inventory.Inventory
import org.bukkit.inventory.ItemStack import org.bukkit.inventory.ItemStack
@@ -16,7 +37,7 @@ import org.bukkit.persistence.PersistentDataType
import java.util.* import java.util.*
import kotlin.math.ceil import kotlin.math.ceil
class DealerInventory(player: Player): SWInventoryHolder() { class DealerInventory(val player: Player): SWInventoryHolder() {
init { init {
items.forEachIndexed { index, item -> 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 price = item.second.price * if (it.isShiftClick) 5 else 1
val amount = item.second.amount * if (it.isShiftClick) 5 else 1 val amount = item.second.amount * if (it.isShiftClick) 5 else 1
if (!player.inventory.containsAtLeast(coins, price)) { val team = TNTLeagueGame.getTeam(player) ?: return@to
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)) if (team.coins < price) {
message.send("NOT_ENOUGH_COINS", player)
player.playSound(player, Sound.ENTITY_VILLAGER_HURT, 1f, 1f)
return@to return@to
} }
player.inventory.removeItem(coins.asQuantity(price)) team.coins -= price
player.inventory.addItem(ItemStack.of(item.first.type, amount)) 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 { companion object {
private val priceKey = NamespacedKey(plugin, "price") private val priceKey = NamespacedKey(plugin, "price")
@@ -45,7 +68,7 @@ class DealerInventory(player: Player): SWInventoryHolder() {
val coins = ItemStack(Material.RAW_GOLD).apply { val coins = ItemStack(Material.RAW_GOLD).apply {
itemMeta = itemMeta.apply { itemMeta = itemMeta.apply {
displayName(Component.text("Coins").bold().gold()) displayName(Component.text("Coins").color(NamedTextColor.GOLD))
persistentDataContainer.apply { persistentDataContainer.apply {
set(coinKey, PersistentDataType.BOOLEAN, true) set(coinKey, PersistentDataType.BOOLEAN, true)
} }
@@ -58,11 +81,13 @@ class DealerInventory(player: Player): SWInventoryHolder() {
prices.map { (material, price) -> prices.map { (material, price) ->
ItemStack(material).apply { ItemStack(material).apply {
itemMeta = itemMeta.apply { itemMeta = itemMeta.apply {
displayName(material.name.lowercase().replace("_", " ") displayName(Component.text(material.name.lowercase().replace("_", " ")
.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() } .replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() })
.component().gray().appendSpace().append(price.amount.toString().component().yellow())) .color(NamedTextColor.GRAY).appendSpace().append(Component.text(price.amount).color(NamedTextColor.YELLOW)))
amount = price.amount 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 { persistentDataContainer.apply {
set(priceKey, PersistentDataType.INTEGER, price.price) set(priceKey, PersistentDataType.INTEGER, price.price)
set(amountKey, PersistentDataType.INTEGER, price.amount) 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 package de.steamwar.tntleague.util
import de.steamwar.scoreboard.ScoreboardCallback import de.steamwar.scoreboard.ScoreboardCallback
import de.steamwar.tntleague.colorByTeam
import de.steamwar.tntleague.config.targetedBlocks import de.steamwar.tntleague.config.targetedBlocks
import de.steamwar.tntleague.game.TNTLeagueGame 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 org.bukkit.entity.Player
import kotlin.collections.HashMap import kotlin.collections.HashMap
private val scoreboardTitle by lazy { tntLeaguePrefix.toLegacy() }
data class TNTLeagueScoreboard(val p: Player): ScoreboardCallback { data class TNTLeagueScoreboard(val p: Player): ScoreboardCallback {
override fun getData(): HashMap<String, Int> { 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 minutes = TNTLeagueGame.gameTimeRemaining.floorDiv(60)
val seconds = TNTLeagueGame.gameTimeRemaining.rem(60).toString().padStart(2, '0') 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) { when (val team = TNTLeagueGame.getTeam(p)) {
lines.add(translate("scoreboardTeam", translate(name).colorByTeam(this), (targetedBlocks - damagedBlocks).toString().yellow()).gray()) 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) { 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 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 load: POSTWORLD
api-version: '1.21' api-version: '1.21'
dependencies: dependencies:
- name: SpigotCore server:
required: true SpigotCore:
- name: KotlinCore required: true
required: true load: BEFORE
KotlinCore:
required: true
load: BEFORE
@@ -29,7 +29,7 @@ public class Arenaserver extends Subserver {
private final boolean allowMerge; private final boolean allowMerge;
public Arenaserver(String serverName, String mode, String map, boolean allowMerge, int port, ProcessBuilder processBuilder, Runnable shutdownCallback) { 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.mode = mode;
this.map = map; this.map = map;
this.allowMerge = allowMerge; 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){ 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; this.owner = owner;
synchronized (servers) { 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){ 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; this.map = map;
synchronized (servers) { 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.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
@SuppressWarnings("unused")
public class Subserver { 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 private static final Component PREFIX = Component
.text("Steam").color(NamedTextColor.YELLOW) .text("Steam").color(NamedTextColor.YELLOW)
.append(Component.text("War» ").color(NamedTextColor.DARK_GRAY)); .append(Component.text("War» ").color(NamedTextColor.DARK_GRAY));
@@ -84,8 +95,6 @@ public class Subserver {
private final ServerInfo server; private final ServerInfo server;
@Getter @Getter
private RegisteredServer registeredServer; private RegisteredServer registeredServer;
@Getter
private final Servertype type;
private final Thread thread; private final Thread thread;
@Getter @Getter
private boolean started; private boolean started;
@@ -94,13 +103,13 @@ public class Subserver {
@Getter @Getter
private final Map<Player, String> tablistNames = new HashMap<>(); 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.started = false;
this.serverName = serverName; this.serverName = serverName;
this.type = type;
this.shutdownCallback = shutdownCallback; this.shutdownCallback = shutdownCallback;
this.failureCallback = failureCallback == null ? this::fatalError : failureCallback; this.failureCallback = failureCallback == null ? this::fatalError : failureCallback;
this.checkpoint = processBuilder.command().contains("criu"); this.checkpoint = processBuilder.command().contains("criu");
this.thread = new Thread(this::run, "Subserver " + serverName);
try { try {
this.process = processBuilder.start(); this.process = processBuilder.start();
@@ -112,7 +121,8 @@ public class Subserver {
this.server = new ServerInfo(serverName, address); this.server = new ServerInfo(serverName, address);
this.writer = new PrintWriter(process.getOutputStream(), true); this.writer = new PrintWriter(process.getOutputStream(), true);
this.thread = new Thread(this::run, "Subserver " + serverName); register();
this.thread.start(); this.thread.start();
} }
@@ -146,7 +156,8 @@ public class Subserver {
process.destroyForcibly(); process.destroyForcibly();
} }
thread.join(); if(thread.isAlive())
thread.join();
} catch (InterruptedException e) { } catch (InterruptedException e) {
logger.log(Level.SEVERE, "Subserver stop interrupted!", e); logger.log(Level.SEVERE, "Subserver stop interrupted!", e);
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
@@ -205,8 +216,6 @@ public class Subserver {
} }
private void run() { private void run() {
register();
Exception ex = null; Exception ex = null;
try { try {
if (checkpoint) { if (checkpoint) {
+1 -2
View File
@@ -62,8 +62,7 @@ dependencies {
implementation(libs.msgpack) implementation(libs.msgpack)
implementation(libs.apolloapi) implementation(libs.apolloprotos)
implementation(libs.apollocommon)
implementation(libs.nbt) 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_BUILDER_HOVER=§eSets the Role to Builder
HELP_BAU_SET_SUPERVISOR=§8/§ebuild supervisor §8- §7Starting build server. Saving schematics 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_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=§8/§ebuild delete §8- §7Reset your entire build server
HELP_BAU_DELETE_HOVER=§eReset build server HELP_BAU_DELETE_HOVER=§eReset build server
HELP_BAU_TESTARENA=§8/§ebuild testarena §8- §7Start a test arena 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_SELFDEL=§cYou cannot remove yourself!
BAU_DELMEMBER_DELETED=§cPlayer was removed. BAU_DELMEMBER_DELETED=§cPlayer was removed.
BAU_DELMEMBER_DELETED_TARGET=§cYou were removed from the world of §e{0}. 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_DELETED=§aYour world is being reset.
BAU_DELETE_GUI_NAME=§eDo you really want to delete the world? BAU_DELETE_GUI_NAME=§eDo you really want to delete the world?
BAU_DELETE_GUI_CANCEL=§cCancel BAU_DELETE_GUI_CANCEL=§cCancel
@@ -326,7 +330,7 @@ CHECK_DECLINED_TEAM=§7The schematic §e{0} §7from §e{1} §7is now declined be
#HistoricCommand #HistoricCommand
HISTORIC_BROADCAST=§7Historic §e{0} §7fight by §e{1}§8! 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 #JoinCommand
JOIN_PLAYER_BLOCK=§cYou currently cannot follow this player. 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_BUILDER_HOVER=§eSetzt die Rolle Builder
HELP_BAU_SET_SUPERVISOR=§8/§ebuild setsupervisor §8- §7Starten des Baus. Schematics erstellen HELP_BAU_SET_SUPERVISOR=§8/§ebuild setsupervisor §8- §7Starten des Baus. Schematics erstellen
HELP_BAU_SET_SUPERVISOR_HOVER=§eSetzt die Rolle Supervisor 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=§8/§ebau delete §8- §7Setzt deine Bauwelt zurück
HELP_BAU_DELETE_HOVER=§eBauwelt zurücksetzen HELP_BAU_DELETE_HOVER=§eBauwelt zurücksetzen
HELP_BAU_TESTARENA=§8/§ebau testarena §8- §7Starte eine Testarena 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_SELFDEL=§cDu kannst dich nicht selbst entfernen!
BAU_DELMEMBER_DELETED=§cDer Spieler wurde entfernt. BAU_DELMEMBER_DELETED=§cDer Spieler wurde entfernt.
BAU_DELMEMBER_DELETED_TARGET=§cDu wurdest von der Welt von §e{0} §centfernt. 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_DELETED=§aDeine Welt wird zurückgesetzt.
BAU_DELETE_GUI_NAME=§eWirklich Welt löschen? BAU_DELETE_GUI_NAME=§eWirklich Welt löschen?
BAU_DELETE_GUI_CANCEL=§cAbbrechen BAU_DELETE_GUI_CANCEL=§cAbbrechen
@@ -308,7 +312,7 @@ CHECK_DECLINED_TEAM=§7Die Schematic §e{0} §7von §e{1} §7wurde aufgrund von
#HistoricCommand #HistoricCommand
HISTORIC_BROADCAST=§7Historischer §e{0}§8-§7Kampf von §e{1}§8! 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 #JoinCommand
JOIN_PLAYER_BLOCK=§cDu kannst diesem Spieler derzeit nicht folgen. 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.event.connection.LoginEvent;
import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ServerConnection; import com.velocitypowered.api.proxy.ServerConnection;
import de.steamwar.persistent.Servertype;
import de.steamwar.persistent.Subserver; import de.steamwar.persistent.Subserver;
import de.steamwar.sql.SteamwarUser; import de.steamwar.sql.SteamwarUser;
import de.steamwar.sql.UserPerm; import de.steamwar.sql.UserPerm;
@@ -64,7 +63,7 @@ public interface Chatter {
static ChatterGroup globalChat() { static ChatterGroup globalChat() {
return new ChatterGroup(Stream.concat(Stream.of(Chatter.console()), allPlayers().filter(player -> { return new ChatterGroup(Stream.concat(Stream.of(Chatter.console()), allPlayers().filter(player -> {
Subserver subserver = Subserver.getSubserver(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))); }).map(Chatter::of)));
} }
@@ -53,7 +53,7 @@ public class ErrorLogger extends AbstractAppender {
@Override @Override
public void append(LogEvent event) { public void append(LogEvent event) {
if(event.getLevel().isLessSpecificThan(Level.WARN)) if(event.getLevel().intLevel() > Level.WARN.intLevel())
return; return;
String message = event.getMessage().getFormattedMessage(); String message = event.getMessage().getFormattedMessage();
@@ -70,6 +70,7 @@ public class ServerStarter {
private boolean checkpoint = false; private boolean checkpoint = false;
private ServerConstructor constructor = (serverName, port, builder, shutdownCallback, failureCallback) -> new Arenaserver(serverName, gameMode, fightMap, allowMerge, port, builder, shutdownCallback); private ServerConstructor constructor = (serverName, port, builder, shutdownCallback, failureCallback) -> new Arenaserver(serverName, gameMode, fightMap, allowMerge, port, builder, shutdownCallback);
private Consumer<Subserver> callback = subserver -> {}; private Consumer<Subserver> callback = subserver -> {};
private Object responsible = new Object();
private final Set<Player> playersToSend = new HashSet<>(); private final Set<Player> playersToSend = new HashSet<>();
private final Map<String, String> arguments = new HashMap<>(); private final Map<String, String> arguments = new HashMap<>();
@@ -84,6 +85,14 @@ public class ServerStarter {
directory = new File(SERVER_PATH, mode.getFolder()); directory = new File(SERVER_PATH, mode.getFolder());
arguments.put("config", mode.getConfig()); arguments.put("config", mode.getConfig());
tempWorld(SERVER_PATH + mode.getFolder() + "/arenas/" + map); 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; return this;
} }
@@ -245,6 +254,10 @@ public class ServerStarter {
public ServerStarter send(Player player) { public ServerStarter send(Player player) {
playersToSend.add(player); playersToSend.add(player);
if(!(responsible instanceof Player))
responsible = player;
return this; return this;
} }
@@ -253,47 +266,49 @@ public class ServerStarter {
return this; return this;
} }
public boolean start() { public void start() {
if(!startCondition.getAsBoolean()) VelocityCore.schedule(() -> {
return false; synchronized (responsible) {
if(!startCondition.getAsBoolean())
return;
int port = portrange.freePort(); int port = portrange.freePort();
String serverName = serverNameProvider.apply(port); String serverName = serverNameProvider.apply(port);
if(node == null) { if(node == null) {
node = Node.getNode(); node = Node.getNode();
if(node == null) { if(node == null) {
for (Player p : playersToSend) for (Player p : playersToSend)
Chatter.of(p).system("SERVER_START_OVERLOAD"); 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);
}
} }
} }).schedule();
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;
} }
private void regularStart(String serverName, int port) { private void regularStart(String serverName, int port) {
@@ -20,14 +20,13 @@
package de.steamwar.velocitycore.commands; package de.steamwar.velocitycore.commands;
import com.velocitypowered.api.proxy.server.RegisteredServer; 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.PreviousArguments;
import de.steamwar.command.SWCommand; import de.steamwar.command.SWCommand;
import de.steamwar.command.TypeMapper; import de.steamwar.command.TypeMapper;
import de.steamwar.messages.Chatter; import de.steamwar.messages.Chatter;
import de.steamwar.messages.PlayerChatter; import de.steamwar.messages.PlayerChatter;
import de.steamwar.persistent.Subserver;
import de.steamwar.velocitycore.VelocityCore;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
@@ -53,7 +52,7 @@ public class ArenaCommand extends SWCommand {
@Override @Override
public boolean validate(Chatter sender, Subserver value, MessageSender messageSender) { 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"); sender.system("ARENA_NOT_FOUND");
return false; return false;
} }
@@ -64,7 +63,7 @@ public class ArenaCommand extends SWCommand {
public Collection<String> tabCompletes(Chatter sender, PreviousArguments previousArguments, String s) { public Collection<String> tabCompletes(Chatter sender, PreviousArguments previousArguments, String s) {
List<Subserver> subserverList = Subserver.getServerList(); List<Subserver> subserverList = Subserver.getServerList();
synchronized (subserverList) { 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("resetall")
@Register("delete") @Register("delete")
public void delete(PlayerChatter sender, @OptionalValue(value = "", onlyUINIG = true) ServerVersion version) { public void delete(PlayerChatter sender, @OptionalValue(value = "", onlyUINIG = true) ServerVersion version) {
@@ -223,7 +235,7 @@ public class BauCommand extends SWCommand {
@Register("testarena") @Register("testarena")
public void testarena(PlayerChatter sender, @Mapper("nonHistoricArenaMode") @OptionalValue("") @AllowNull ArenaMode arenaMode, @Mapper("arenaMap") @OptionalValue("") @AllowNull String map) { 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) -> 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; package de.steamwar.velocitycore.commands;
import com.velocitypowered.api.proxy.Player; 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.SWCommand;
import de.steamwar.command.TypeValidator; import de.steamwar.command.TypeValidator;
import de.steamwar.messages.Chatter; import de.steamwar.messages.Chatter;
import de.steamwar.messages.Message; import de.steamwar.messages.Message;
import de.steamwar.messages.PlayerChatter; import de.steamwar.messages.PlayerChatter;
import de.steamwar.persistent.Subserver;
import de.steamwar.sql.IgnoreSystem; import de.steamwar.sql.IgnoreSystem;
import de.steamwar.velocitycore.ArenaMode;
import de.steamwar.velocitycore.ServerStarter;
import net.kyori.adventure.text.event.ClickEvent; import net.kyori.adventure.text.event.ClickEvent;
import java.util.LinkedList; import java.util.LinkedList;
@@ -84,8 +83,7 @@ public class ChallengeCommand extends SWCommand {
return false; return false;
} }
Subserver subserver = Subserver.getSubserver(value); if (Subserver.isArena(Subserver.getSubserver(value))) {
if (subserver != null && subserver.getType() == Servertype.ARENA) {
messageSender.send("CHALLENGE_INARENA"); messageSender.send("CHALLENGE_INARENA");
return false; return false;
} }
@@ -207,19 +207,15 @@ public class CheckCommand extends SWCommand {
this.startTime = Timestamp.from(Instant.now()); this.startTime = Timestamp.from(Instant.now());
this.checkList = checkQuestions.get(schematic.getSchemtype()).listIterator(); this.checkList = checkQuestions.get(schematic.getSchemtype()).listIterator();
VelocityCore.schedule(() -> { ArenaMode mode = ArenaMode.getBySchemType(fightTypes.get(schematic.getSchemtype()));
ArenaMode mode = ArenaMode.getBySchemType(fightTypes.get(schematic.getSchemtype())); new ServerStarter().test(mode, mode.getRandomMap(), checker.getPlayer()).check(schematic.getId()).callback(subserver -> {
if(!new ServerStarter().test(mode, mode.getRandomMap(), checker.getPlayer()).check(schematic.getId()).start()) {
remove();
return;
}
currentCheckers.put(checker.user().getUUID(), this); currentCheckers.put(checker.user().getUUID(), this);
currentSchems.put(schematic.getId(), this); currentSchems.put(schematic.getId(), this);
for(CheckedSchematic previous : CheckedSchematic.previousChecks(schematic)) for(CheckedSchematic previous : CheckedSchematic.previousChecks(schematic))
checker.prefixless("CHECK_SCHEMATIC_PREVIOUS", previous.getEndTime(), SteamwarUser.get(previous.getValidator()).getUserName(), previous.getDeclineReason()); checker.prefixless("CHECK_SCHEMATIC_PREVIOUS", previous.getEndTime(), SteamwarUser.get(previous.getValidator()).getUserName(), previous.getDeclineReason());
next(); next();
}).schedule(); }).start();
} }
private void next() { private void next() {
@@ -30,6 +30,7 @@ import de.steamwar.command.TypeValidator;
import de.steamwar.messages.PlayerChatter; import de.steamwar.messages.PlayerChatter;
import de.steamwar.sql.Punishment; import de.steamwar.sql.Punishment;
import de.steamwar.sql.SteamwarUser; import de.steamwar.sql.SteamwarUser;
import lombok.Getter;
import java.io.File; import java.io.File;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
@@ -39,7 +40,8 @@ import java.util.Map;
public class DevCommand extends SWCommand { public class DevCommand extends SWCommand {
private final File devServerDir = new File("/configs/DevServer"); 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() { public DevCommand() {
super("dev"); super("dev");
@@ -20,16 +20,16 @@
package de.steamwar.velocitycore.commands; package de.steamwar.velocitycore.commands;
import com.velocitypowered.api.proxy.Player; 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.command.SWCommand;
import de.steamwar.messages.Chatter; import de.steamwar.messages.Chatter;
import de.steamwar.messages.Message; import de.steamwar.messages.Message;
import de.steamwar.messages.PlayerChatter; import de.steamwar.messages.PlayerChatter;
import de.steamwar.persistent.Arenaserver; import de.steamwar.persistent.Arenaserver;
import de.steamwar.persistent.Servertype;
import de.steamwar.persistent.Subserver; 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.Component;
import net.kyori.adventure.text.event.ClickEvent; import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.event.HoverEvent; import net.kyori.adventure.text.event.HoverEvent;
@@ -60,20 +60,7 @@ public class FightCommand extends SWCommand {
sender.sendMessage(start); 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) { static void createArena(PlayerChatter sender, String precommand, boolean allowMerging, ArenaMode arenaMode, String map, boolean historic, FightCallback callback) {
if(alreadyInArena(sender))
return;
if (arenaMode == null) { if (arenaMode == null) {
getModes(sender, precommand, historic); getModes(sender, precommand, historic);
return; return;
@@ -92,6 +92,7 @@ public class HelpCommand extends SWCommand {
"HELP_BAU_SET_SPECTATOR", "/build setSpectator ", "HELP_BAU_SET_SPECTATOR", "/build setSpectator ",
"HELP_BAU_SET_BUILDER", "/build setBuilder ", "HELP_BAU_SET_BUILDER", "/build setBuilder ",
"HELP_BAU_SET_SUPERVISOR", "/build setSupervisor ", "HELP_BAU_SET_SUPERVISOR", "/build setSupervisor ",
"HELP_BAU_STOP", "/build stop",
"HELP_BAU_DELETE", "/build delete ", "HELP_BAU_DELETE", "/build delete ",
"HELP_BAU_TESTARENA", "/build testarena ", "HELP_BAU_TESTARENA", "/build testarena ",
"HELP_BAU_LOCK", "/build lock ", "HELP_BAU_LOCK", "/build lock ",
@@ -35,7 +35,7 @@ public class HistoricCommand extends SWCommand {
@Register @Register
public void historic(@Validator("arenaPlayer") PlayerChatter player, @Mapper("historicArenaMode") @OptionalValue("") @AllowNull ArenaMode arenaMode, @Mapper("arenaMap") @OptionalValue("") @AllowNull String map) { 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( 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()); ).start());
} }
} }
@@ -21,11 +21,10 @@ package de.steamwar.velocitycore.commands;
import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ServerConnection; 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.command.SWCommand;
import de.steamwar.messages.Chatter; import de.steamwar.messages.Chatter;
import de.steamwar.persistent.Subserver;
import de.steamwar.velocitycore.VelocityCore;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -46,8 +45,7 @@ public class ListCommand extends SWCommand {
if (pserver == null) if (pserver == null)
continue; continue;
Subserver subserver = Subserver.getSubserver(pserver.getServerInfo()); if (Subserver.isBuild(Subserver.getSubserver(pserver.getServerInfo()))) {
if (subserver != null && subserver.getType() == Servertype.BAUSERVER) {
playerMap.computeIfAbsent("Bau", s -> new ArrayList<>()).add(player); playerMap.computeIfAbsent("Bau", s -> new ArrayList<>()).add(player);
} else { } else {
playerMap.computeIfAbsent(pserver.getServerInfo().getName(), s -> new ArrayList<>()).add(player); playerMap.computeIfAbsent(pserver.getServerInfo().getName(), s -> new ArrayList<>()).add(player);
@@ -55,15 +55,7 @@ public class SendCommand extends SWCommand {
if (name.contains(" ")) return false; if (name.contains(" ")) return false;
Subserver subserver = Subserver.getSubserver(serverInfo); Subserver subserver = Subserver.getSubserver(serverInfo);
if (subserver == null) { return subserver == null || Subserver.isArena(subserver) || (Subserver.isBuilder(subserver) && user.hasPerm(UserPerm.BUILD));
return true;
}
return switch (subserver.getType()) {
case ARENA -> true;
case BUILDER -> user.hasPerm(UserPerm.BUILD);
default -> false;
};
} }
@Override @Override
@@ -110,37 +110,31 @@ public class TpCommand extends SWCommand {
return; return;
} }
switch (subserver.getType()) { if(Subserver.isArena(subserver)) {
case ARENA: if (PunishmentCommand.isPunishedWithMessage(sender, Punishment.PunishmentType.NoFightServer))
if (PunishmentCommand.isPunishedWithMessage(sender, Punishment.PunishmentType.NoFightServer)) return;
return; } else if(Subserver.isBuild(subserver)) {
break; Bauserver bauserver = (Bauserver) subserver;
Player checker = VelocityCore.getProxy().getPlayer(bauserver.getOwner()).orElse(null);
case BAUSERVER: if (checker != null && CheckCommand.isChecking(checker)) {
Bauserver bauserver = (Bauserver) subserver; if (!sender.user().hasPerm(UserPerm.CHECK) && CheckCommand.getCheckingSchem(checker).getOwner() != sender.user().getId()) {
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());
sender.system("JOIN_PLAYER_BLOCK"); sender.system("JOIN_PLAYER_BLOCK");
return; return;
} }
break; } else if (BauLock.isLocked(SteamwarUser.get(bauserver.getOwner()), sender.user())) {
sender.system("BAU_LOCKED_NOALLOWED");
case BUILDER: Chatter.of(bauserver.getOwner()).system("BAU_LOCK_BLOCKED", sender);
if(!sender.user().hasPerm(UserPerm.BUILD)) { return;
sender.system("JOIN_PLAYER_BLOCK"); } else if (!bauserver.getOwner().equals(sender.user().getUUID()) && BauweltMember.getBauMember(bauserver.getOwner(), sender.user().getUUID()) == null) {
return; SubserverSystem.sendDeniedMessage(sender, bauserver.getOwner());
} sender.system("JOIN_PLAYER_BLOCK");
break; return;
}
} else if(Subserver.isBuilder(subserver)) {
if(!sender.user().hasPerm(UserPerm.BUILD)) {
sender.system("JOIN_PLAYER_BLOCK");
return;
}
} }
SubserverSystem.sendPlayer(subserver, sender.getPlayer()); SubserverSystem.sendPlayer(subserver, sender.getPlayer());
@@ -19,21 +19,22 @@
package de.steamwar.velocitycore.commands; 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.SWCommand;
import de.steamwar.command.TypeValidator; import de.steamwar.command.TypeValidator;
import de.steamwar.messages.Chatter; import de.steamwar.messages.Chatter;
import de.steamwar.messages.Message; import de.steamwar.messages.Message;
import de.steamwar.messages.PlayerChatter; import de.steamwar.messages.PlayerChatter;
import de.steamwar.persistent.Servertype;
import de.steamwar.persistent.Subserver; import de.steamwar.persistent.Subserver;
import de.steamwar.sql.SteamwarUser; import de.steamwar.sql.SteamwarUser;
import de.steamwar.sql.Tutorial; import de.steamwar.sql.Tutorial;
import de.steamwar.sql.UserPerm; 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.io.File;
import java.util.Arrays; import java.util.Arrays;
@@ -140,7 +141,7 @@ public class TutorialCommand extends SWCommand {
SteamwarUser user = sender.user(); SteamwarUser user = sender.user();
File tempWorld = new File(ServerStarter.TEMP_WORLD_PATH, ServerStarter.serverToWorldName(ServerStarter.bauServerName(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"); sender.system("TUTORIAL_CREATE_MISSING");
return; return;
} }
@@ -20,7 +20,6 @@
package de.steamwar.velocitycore.discord.channels; package de.steamwar.velocitycore.discord.channels;
import net.dv8tion.jda.api.interactions.callbacks.IReplyCallback; 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.Component;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
@@ -44,23 +43,24 @@ public class InteractionReply extends DiscordChannel {
private InteractionReply(IReplyCallback interaction) { private InteractionReply(IReplyCallback interaction) {
super(interaction.getUser()); super(interaction.getUser());
this.interaction = interaction; this.interaction = interaction;
interaction.deferReply(true).queue();
} }
@Override @Override
public void sendMessage(Component msg) { public void sendMessage(Component msg) {
if(replied) { if(!replied) {
super.sendMessage(msg); messages.add(PlainTextComponentSerializer.plainText().serialize(msg));
return; 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() { public void submit() {
(messages.isEmpty() ? interaction.getHook().sendMessage(String.join("\n", messages)).queue();
interaction.deferReply() :
interaction.reply(String.join("\n", messages))
).setEphemeral(true).queue();
replied = true; replied = true;
} }
} }
@@ -43,7 +43,7 @@ public class DiscordAlert {
if(discordId == null) if(discordId == null)
return; return;
User user = DiscordBot.getInstance().getJda().getUserById(discordId); User user = DiscordBot.getInstance().getJda().retrieveUserById(discordId).complete();
if(user == null) if(user == null)
return; return;
@@ -32,7 +32,6 @@ import de.steamwar.messages.ChatterGroup;
import de.steamwar.messages.Message; import de.steamwar.messages.Message;
import de.steamwar.messages.PlayerChatter; import de.steamwar.messages.PlayerChatter;
import de.steamwar.network.packets.server.PingPacket; import de.steamwar.network.packets.server.PingPacket;
import de.steamwar.persistent.Servertype;
import de.steamwar.persistent.Subserver; import de.steamwar.persistent.Subserver;
import de.steamwar.sql.*; import de.steamwar.sql.*;
import de.steamwar.velocitycore.ArenaMode; import de.steamwar.velocitycore.ArenaMode;
@@ -110,7 +109,7 @@ public class ChatListener extends BasicListener {
return; return;
Subserver subserver = Subserver.getSubserver(player); 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); localChat(Chatter.of(player), message);
} else if (message.startsWith("+")) { } else if (message.startsWith("+")) {
localChat(Chatter.of(player), message.substring(1)); 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.connection.PostLoginEvent;
import com.velocitypowered.api.event.player.ServerConnectedEvent; import com.velocitypowered.api.event.player.ServerConnectedEvent;
import com.velocitypowered.api.proxy.Player; 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.messages.Chatter;
import de.steamwar.persistent.Bauserver;
import de.steamwar.persistent.Subserver;
import de.steamwar.sql.SchematicNode; import de.steamwar.sql.SchematicNode;
import de.steamwar.sql.SchematicType; import de.steamwar.sql.SchematicType;
import de.steamwar.velocitycore.commands.CheckCommand;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -56,11 +55,7 @@ public class CheckListener extends BasicListener {
Player player = e.getPlayer(); Player player = e.getPlayer();
if(CheckCommand.isChecking(player)){ if(CheckCommand.isChecking(player)){
Subserver server = Subserver.getSubserver(e.getServer().getServerInfo()); Subserver server = Subserver.getSubserver(e.getServer().getServerInfo());
if( if(!Subserver.isBuild(server) || ((Bauserver)server).getOwner() != player.getUniqueId())
server == null ||
server.getType() != Servertype.BAUSERVER ||
((Bauserver)server).getOwner() != player.getUniqueId()
)
CheckCommand.abort(player); CheckCommand.abort(player);
} }
} }
@@ -27,7 +27,6 @@ import com.velocitypowered.api.permission.Tristate;
import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.Player;
import de.steamwar.messages.Chatter; import de.steamwar.messages.Chatter;
import de.steamwar.messages.Message; import de.steamwar.messages.Message;
import de.steamwar.persistent.Servertype;
import de.steamwar.persistent.Subserver; import de.steamwar.persistent.Subserver;
import de.steamwar.sql.SteamwarUser; import de.steamwar.sql.SteamwarUser;
import de.steamwar.sql.UserPerm; import de.steamwar.sql.UserPerm;
@@ -77,7 +76,7 @@ public class ConnectionListener extends BasicListener {
CheckCommand.sendReminder(chatter); CheckCommand.sendReminder(chatter);
for(Subserver subserver : Subserver.getServerList()) { 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()); 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; package de.steamwar.velocitycore.listeners;
import com.lunarclient.apollo.ApolloManager;
import com.velocitypowered.api.event.Subscribe; import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.connection.PluginMessageEvent; import com.velocitypowered.api.event.connection.PluginMessageEvent;
import com.velocitypowered.api.event.player.PlayerChannelRegisterEvent; 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.LegacyChannelIdentifier;
import com.velocitypowered.api.proxy.messages.MinecraftChannelIdentifier; import com.velocitypowered.api.proxy.messages.MinecraftChannelIdentifier;
import com.velocitypowered.proxy.protocol.ProtocolUtils; 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.VelocityCore;
import de.steamwar.velocitycore.commands.TeamCommand; import de.steamwar.velocitycore.commands.TeamCommand;
import de.steamwar.velocitycore.mods.*; import de.steamwar.velocitycore.mods.*;
import de.steamwar.velocitycore.network.ServerMetaInfo; 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.ByteBuf;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
@@ -106,24 +105,24 @@ public class PluginMessage extends BasicListener {
for(String channel : Arrays.asList( for(String channel : Arrays.asList(
"fabric:container/open", "fabric:registry/sync/direct", "fabric:registry/sync", "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.CHANNEL, "FML|MP", "FML", "FORGE",
"fml:loginwrapper", "fml:handshake", "fml:play", "fml:loginwrapper", "fml:handshake", "fml:play",
"forge:tier_sorting", "forge:split", "forge:login", "forge:handshake", "forge:tier_sorting", "forge:split", "forge:login", "forge:handshake",
"labymod3:main", "labymod:neo", "labymod3:main", "labymod:neo", "labymod:voicechat", "labymod:germanminer",
"feather:client/frag", "feather:client/frag",
Alpine.HANDSHAKE, Alpine.PLAY, Alpine.HANDSHAKE, Alpine.PLAY,
"lunarclient:pm", "transfer:channel", "apollo:json", //https://lunarclient.dev/apollo/developers/modules/transfer (Lunarclient channels)
"sw:hotkeys", "sw:hotkeys",
"floodgate:form", "floodgate:transfer", "floodgate:packet", "floodgate:form", "floodgate:w", "floodgate:packet", "floodgate:transfer", "erosion:msg",
"Replay|Restrict", "replaymod:restrict", "Replay|Restrict", "replaymod:restrict",
"WDL|CONTROL", "wdl:control", "WDL|CONTROL", "wdl:control",
"tpshud:handshake", "tpshud:tps", //https://github.com/mooziii/tpshud-fabric/tree/main "tpshud:handshake", "tpshud:tps", //https://github.com/mooziii/tpshud-fabric/tree/main
"methane_server:statepacket", //https://modrinth.com/mod/methane "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 "architectury:spawn_entity_packet", //https://modrinth.com/mod/architectury-api
"jei:channel", "jei:cheat_permission", //https://modrinth.com/mod/jei "jei:channel", "jei:cheat_permission", //https://modrinth.com/mod/jei
"owo:local_packet", "owo:sync_screen_handler_properties", //https://modrinth.com/mod/owo-lib "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) "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) "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/ "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) "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) "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) "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) "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) "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) "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) "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) "easyanvils:1/0", "easyanvils:1/2", "easyanvils:play", //https://github.com/Fuzss/easyanvils (Anvil handling improvements)
"easymagic:1/0", "easymagic.main:0", //https://github.com/Fuzss/easymagic (Enchantment table 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) "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) "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) "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) "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) "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) "immersive_weathering:0", //https://github.com/AstralOrdana/Immersive-Weathering (Adds additional random block transitions)
"kiwi:sync_cosmetic", //github.com/Snownee/Kiwi (General purpose library) "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) "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) "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) "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) "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) "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) "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) //https://github.com/ZsoltMolnarrr/SpellEngine (Magic library)
"spell_engine:config_sync", "spell_engine:particle_effects", "spell_engine:spell_animation", "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) //https://github.com/CreativeMD/CreativeCore (General purpose library)
"creativecore:main0", "creativecore:main1", "creativecore:main2", "creativecore:main3", "creativecore:main0", "creativecore:main1", "creativecore:main2", "creativecore:main3",
"creativecore:main4", "creativecore:main5", "creativecore:main6", "creativecore:main7", "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) //https://github.com/Ladysnake/Cardinal-Components-API (General purpose library)
"cardinal-components:block_entity_sync", "cardinal-components:chunk_sync", "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", "minecells:elevator_destroyed", "minecells:spawn_rune_particles", "minecells:sync_minecells_data",
//https://modrinth.com/mod/appleskin (Additional food bar information) //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", "appleskin:saturation", "appleskin:exhaustion",
//https://modrinth.com/mod/puzzles-lib (General purpose library) //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", "puzzleslib.main:0", "puzzleslib.main:1", "puzzleslib:play/0",
//https://github.com/Fuzss/puzzlesapi (General purpose library extension) //https://github.com/Fuzss/puzzlesapi (General purpose library extension)
"puzzlesapi:1/1", "puzzlesapi:1/2", "puzzlesapi:1/5", "puzzlesapi:2/1", "puzzlesapi:2/2", "puzzlesapi:1/1", "puzzlesapi:1/2", "puzzlesapi:1/5", "puzzlesapi:2/1", "puzzlesapi:2/2",
//https://github.com/bernie-g/geckolib //https://github.com/bernie-g/geckolib
"geckolib:block_entity_anim_trigger_sync", "geckolib:entity_anim_trigger_sync", "geckolib:block_entity_anim_trigger_sync", "geckolib:entity_anim_trigger_sync",
"geckolib:block_entity_anim_data_sync", "geckolib:anim_data_sync", "geckolib:entity_data_sync", "geckolib:blockentity_anim_trigger", "geckolib:singleton_data_sync",
"geckolib:entity_anim_data_sync", "geckolib:anim_trigger_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) //https://github.com/Noxcrew/noxesium (MC Championship helper)
"noxesium:server_rules", "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-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: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: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(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(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("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("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("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_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("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("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); channelRegisterHandlers.put(Controlify.CHANNEL, new Controlify()::onRegister);
for(String channel : Arrays.asList( for(String channel : Arrays.asList(
"worldinfo:world_id", // JourneyMap and VoxelMap "worldinfo:world_id", // JourneyMap and VoxelMap
"journeymap:version", "journeymap:admin_req", "journeymap:mp_options_req", "journeymap:waypoint", "journeymap:version", "journeymap:admin_req", "journeymap:mp_options_req", "journeymap:waypoint",
"journeymap:player_loc", "journeymap:admin_save", "journeymap:teleport_req", "journeymap:common", "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")); 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:enable", "axiom:initialize_hotbars",
"axiom:response_chunk_data", "axiom:register_world_properties", "axiom:set_world_property", "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: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"); registerBiDirPassthrough("axiom:handle_big_payload", "axiom:set_editor_views");
for(String channel : Arrays.asList( for(String channel : Arrays.asList(
"axiom:hello", "axiom:set_gamemode", "axiom:set_fly_speed", "axiom:set_world_time", "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: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" "axiom:manipulate_entity", "axiom:delete_entity", "axiom:marker_nbt_request", "axiom:set_buffer"
)) { )) {
channelRegisterHandlers.put(channel, player -> {}); channelRegisterHandlers.put(channel, player -> {});
@@ -343,7 +385,8 @@ public class PluginMessage extends BasicListener {
"watut:nbt", //https://github.com/Corosauce/WATUT "watut:nbt", //https://github.com/Corosauce/WATUT
"bclib:hello_server", "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) "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 -> {}); channelRegisterHandlers.put(channel, player -> {});
register(channel, false, directional(UNKNOWN, DROP)); register(channel, false, directional(UNKNOWN, DROP));
@@ -372,7 +415,8 @@ public class PluginMessage extends BasicListener {
"fwaystones:request_player_waystone_update", "fwaystones:request_player_waystone_update",
"openboatutils:settings", //https://github.com/o7Moon/OpenBoatUtils "openboatutils:settings", //https://github.com/o7Moon/OpenBoatUtils
"block-event-separator:handshake", //https://github.com/SpaceWalkerRS/block-event-separator (Separating block events) "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)); 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("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(Alpine.HANDSHAKE, false, directional(UNKNOWN, new Alpine()::handleHandshakeMessage));
register("LMC", true, directional(UNKNOWN, async(labyMod::handlePluginMessage))); register("LMC", true, directional(UNKNOWN, async(labyMod::handlePluginMessage)));
register("labymod3:main", true, directional(UNKNOWN, async(labyMod::handlePluginMessage))); register("labymod3:main", true, directional(UNKNOWN, async(labyMod::handlePluginMessage)));
@@ -19,112 +19,79 @@
package de.steamwar.velocitycore.mods; package de.steamwar.velocitycore.mods;
import com.lunarclient.apollo.ApolloManager; import com.google.protobuf.Any;
import com.lunarclient.apollo.libs.protobuf.Any; import com.google.protobuf.InvalidProtocolBufferException;
import com.lunarclient.apollo.libs.protobuf.InvalidProtocolBufferException; import com.google.protobuf.Value;
import com.lunarclient.apollo.libs.protobuf.Message; import com.lunarclient.apollo.configurable.v1.ConfigurableSettings;
import com.lunarclient.apollo.mods.impl.*; import com.lunarclient.apollo.configurable.v1.OverrideConfigurableSettingsMessage;
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.lunarclient.apollo.player.v1.ModMessage; import com.lunarclient.apollo.player.v1.ModMessage;
import com.lunarclient.apollo.player.v1.PlayerHandshakeMessage; import com.lunarclient.apollo.player.v1.PlayerHandshakeMessage;
import com.velocitypowered.api.event.connection.PluginMessageEvent; import com.velocitypowered.api.event.connection.PluginMessageEvent;
import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.messages.MinecraftChannelIdentifier; import com.velocitypowered.api.proxy.messages.MinecraftChannelIdentifier;
import de.steamwar.velocitycore.VelocityCore;
import de.steamwar.sql.Mod; import de.steamwar.sql.Mod;
import lombok.AllArgsConstructor; import de.steamwar.velocitycore.VelocityCore;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID;
import java.util.function.Consumer;
import java.util.logging.Level; import java.util.logging.Level;
public class Lunar { public class Lunar {
// https://lunarclient.dev/apollo/introduction // https://lunarclient.dev/apollo/introduction
// https://github.com/LunarClient/Apollo // 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 private final byte[] packet;
Options modSettings = manager.getModule(ModSettingModule.class).getOptions();
modSettings.set(ModReplaymod.ENABLED, false); // TODO check if restrictions working public Lunar() {
modSettings.set(ModFreelook.ENABLED, false); ConfigurableSettings.Builder builder = ConfigurableSettings.newBuilder()
modSettings.set(ModHypixelMod.ENABLED, false); .setApolloModule("mod_setting")
modSettings.set(ModMinimap.ENABLED, false); .setEnable(true);
modSettings.set(ModNametag.ENABLED, false);
modSettings.set(ModTeamView.ENABLED, false); for(String property : List.of(
modSettings.set(ModTntCountdown.ENABLED, false); "freelook.enabled", "hypixel-mod.enabled", "minimap.enabled", "nametag.enabled", "replaymod.enabled",
modSettings.set(ModToggleSneak.TOGGLE_SNEAK_CONTAINER, false); "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) { public void sendRestrictions(Player player) {
NetworkOptions.sendOptions(manager.getModules(), true, new SWApolloPlayer(player)); player.sendPluginMessage(MinecraftChannelIdentifier.from(CHANNEL), packet);
} }
public void handlePluginMessage(PluginMessageEvent event) { public void handlePluginMessage(PluginMessageEvent event) {
Player player = (Player) event.getSource();
Any packet;
try { 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) { } catch (InvalidProtocolBufferException e) {
throw new SecurityException(e); throw new SecurityException(e);
} }
}
handle(PlayerHandshakeMessage.class, packet, handshake -> { private void handle(Player player, PlayerHandshakeMessage packet) {
List<Mod> mods = new ArrayList<>(); List<Mod> mods = new ArrayList<>();
for(ModMessage mod : handshake.getInstalledModsList()) { for(ModMessage mod : packet.getInstalledModsList()) {
switch(mod.getType()) { switch(mod.getType()) {
case TYPE_FABRIC_INTERNAL, TYPE_FORGE_INTERNAL: case TYPE_FABRIC_INTERNAL, TYPE_FORGE_INTERNAL:
// Controlled with ModSettings // Controlled with ModSettings
break; break;
case TYPE_FABRIC_EXTERNAL: case TYPE_FABRIC_EXTERNAL:
mods.add(Mod.getOrCreate(mod.getName(), Mod.Platform.FABRIC)); mods.add(Mod.getOrCreate(mod.getName(), Mod.Platform.FABRIC));
break; break;
case TYPE_FORGE_EXTERNAL: case TYPE_FORGE_EXTERNAL:
mods.add(Mod.getOrCreate(mod.getName(), Mod.Platform.FORGE)); mods.add(Mod.getOrCreate(mod.getName(), Mod.Platform.FORGE));
break; break;
default: default:
VelocityCore.getLogger().log(Level.INFO, () -> player.getUsername() + " uses Lunar mod with unknown type " + mod); VelocityCore.getLogger().log(Level.INFO, () -> player.getUsername() + " uses Lunar mod with unknown type " + mod);
break; 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 ModUtils.handleMods(player, mods);
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; }
} }
} }
@@ -26,6 +26,7 @@ import de.steamwar.persistent.Bauserver;
import de.steamwar.persistent.Builderserver; import de.steamwar.persistent.Builderserver;
import de.steamwar.velocitycore.VelocityCore; import de.steamwar.velocitycore.VelocityCore;
import de.steamwar.persistent.Subserver; import de.steamwar.persistent.Subserver;
import de.steamwar.velocitycore.commands.DevCommand;
import de.steamwar.velocitycore.listeners.BasicListener; import de.steamwar.velocitycore.listeners.BasicListener;
import de.steamwar.velocitycore.listeners.PluginMessage; import de.steamwar.velocitycore.listeners.PluginMessage;
@@ -56,7 +57,7 @@ public class ReplayMod extends BasicListener {
return; return;
Subserver subserver = Subserver.getSubserver(player.getCurrentServer().orElseThrow().getServerInfo()); 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; return;
PluginMessage.send(player, "Replay|Restrict", "replaymod:restrict", restrict); PluginMessage.send(player, "Replay|Restrict", "replaymod:restrict", restrict);
@@ -172,8 +172,10 @@ public class Tablist extends ChannelInboundHandlerAdapter {
sendTabPacket(current, null); sendTabPacket(current, null);
current.clear(); current.clear();
if(connection != null) if(connection != null) {
connection.getConnection().getChannel().pipeline().remove(this); connection.getConnection().getChannel().pipeline().remove(this);
connection = null;
}
} }
@Override @Override
@@ -22,10 +22,9 @@ package de.steamwar.velocitycore.tablist;
import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ServerConnection; import com.velocitypowered.api.proxy.ServerConnection;
import com.velocitypowered.api.proxy.server.RegisteredServer; 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.persistent.Subserver;
import de.steamwar.velocitycore.VelocityCore; import de.steamwar.velocitycore.VelocityCore;
import de.steamwar.messages.Chatter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@@ -38,9 +37,8 @@ public class TablistBuild implements TablistPart {
private final Map<RegisteredServer, List<Item>> players = new HashMap<>(); private final Map<RegisteredServer, List<Item>> players = new HashMap<>();
public TablistBuild() { public TablistBuild() {
for (RegisteredServer server : VelocityCore.getProxy().getAllServers()){ for (RegisteredServer server : VelocityCore.getProxy().getAllServers()) {
Subserver subserver = Subserver.getSubserver(server.getServerInfo()); if(server.getPlayersConnected().isEmpty() || !Subserver.isBuild(Subserver.getSubserver(server.getServerInfo())))
if(server.getPlayersConnected().isEmpty() || subserver == null || subserver.getType() != Servertype.BAUSERVER)
continue; continue;
servers.add(server); servers.add(server);
@@ -27,7 +27,6 @@ import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.server.RegisteredServer; import com.velocitypowered.api.proxy.server.RegisteredServer;
import de.steamwar.network.packets.common.FightInfoPacket; import de.steamwar.network.packets.common.FightInfoPacket;
import de.steamwar.persistent.Servertype;
import de.steamwar.persistent.Storage; import de.steamwar.persistent.Storage;
import de.steamwar.persistent.Subserver; import de.steamwar.persistent.Subserver;
import de.steamwar.velocitycore.VelocityCore; import de.steamwar.velocitycore.VelocityCore;
@@ -100,7 +99,7 @@ public class TablistManager extends BasicListener {
Subserver subserver = Subserver.getSubserver(server.getServerInfo()); Subserver subserver = Subserver.getSubserver(server.getServerInfo());
if (fightInfos.containsKey(server)) if (fightInfos.containsKey(server))
subservers.add(new TablistServer(server, fightInfos.get(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 TablistServer(server));
} }
subservers.add(new TablistBuild()); 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.ServerConnection;
import com.velocitypowered.api.proxy.server.RegisteredServer; import com.velocitypowered.api.proxy.server.RegisteredServer;
import com.velocitypowered.api.util.GameProfile; 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.messages.Chatter;
import de.steamwar.network.packets.common.FightInfoPacket; import de.steamwar.network.packets.common.FightInfoPacket;
import de.steamwar.persistent.Subserver;
import de.steamwar.sql.SteamwarUser; import de.steamwar.sql.SteamwarUser;
import de.steamwar.velocitycore.VelocityCore;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
@@ -94,8 +93,7 @@ public class TablistServer implements TablistPart {
return players.stream().map(item -> { return players.stream().map(item -> {
Player p = VelocityCore.getProxy().getPlayer(item.getUuid()).orElse(null); Player p = VelocityCore.getProxy().getPlayer(item.getUuid()).orElse(null);
if (p == null) return item; if (p == null) return item;
Subserver subserver = Subserver.getSubserver(p.getCurrentServer().map(ServerConnection::getServerInfo).orElse(null)); if (Subserver.isArena(Subserver.getSubserver(p.getCurrentServer().map(ServerConnection::getServerInfo).orElse(null)))) return item;
if (subserver != null && subserver.getType() == Servertype.ARENA) return item;
if (SteamwarUser.get(p.getUniqueId()).getTeam() != team) return item; if (SteamwarUser.get(p.getUniqueId()).getTeam() != team) return item;
return new Item(p, true); return new Item(p, true);
}); });
@@ -37,6 +37,9 @@ class Groups {
private var groups: GroupsData = if (kGroupsFile.exists()) { private var groups: GroupsData = if (kGroupsFile.exists()) {
Cbor.decodeFromByteArray(kGroupsFile.readBytes()) Cbor.decodeFromByteArray(kGroupsFile.readBytes())
} else { } else {
if (!kGroupsFile.parentFile.exists()) {
kGroupsFile.parentFile.mkdirs()
}
kGroupsFile.createNewFile() kGroupsFile.createNewFile()
kGroupsFile.writeBytes(Cbor.encodeToByteArray(GroupsData(mutableListOf()))) 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() val eventId = parameters[fieldName]?.toIntOrNull()
if (eventId == null) { if (eventId == null) {
respond(HttpStatusCode.BadRequest, ResponseError("Invalid event ID")) 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("netty", "io.netty:netty-all:4.1.68.Final")
library("junit", "junit:junit:4.13.2") library("junit", "junit:junit:4.13.2")
library("hamcrest", "org.hamcrest:hamcrest:2.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("classindex", "org.atteo.classindex:classindex:3.13")
library("spigotapi", "org.spigotmc:spigot-api:1.20-R0.1-SNAPSHOT") library("spigotapi", "org.spigotmc:spigot-api:1.20-R0.1-SNAPSHOT")
@@ -140,8 +138,9 @@ dependencyResolutionManagement {
library("velocity", "de.steamwar:velocity:RELEASE") library("velocity", "de.steamwar:velocity:RELEASE")
library("velocityapi", "com.velocitypowered:velocity-api:3.3.0-SNAPSHOT") library("velocityapi", "com.velocitypowered:velocity-api:3.3.0-SNAPSHOT")
library("apolloapi", "com.lunarclient:apollo-api:1.1.0") library("jda", "net.dv8tion:JDA:5.2.0")
library("apollocommon", "com.lunarclient:apollo-common:1.1.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") 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.jar": "FightSystem/build/libs/FightSystem-all.jar"
"/binarys/FightSystem_Standalone.jar": "FightSystem/FightSystem_Standalone/build/libs/FightSystem_Standalone-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" "/binarys/lobbysystem2.0.jar": "LobbySystem/build/libs/LobbySystem.jar"
@@ -29,4 +30,7 @@ artifacts:
"/binarys/VelocityCore.jar": "VelocityCore/build/libs/VelocityCore-all.jar" "/binarys/VelocityCore.jar": "VelocityCore/build/libs/VelocityCore-all.jar"
"/binarys/deployarena.py": "VelocityCore/deployarena.py" "/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"