feat: test commands and role/team handling refactors

This commit is contained in:
Ninjdai 2024-09-28 20:52:47 +02:00
parent 116515a598
commit 897dd837ad
13 changed files with 335 additions and 23 deletions

View File

@ -17,6 +17,8 @@ dependencies {
compileOnly 'org.projectlombok:lombok:1.18.34' compileOnly 'org.projectlombok:lombok:1.18.34'
annotationProcessor 'org.projectlombok:lombok:1.18.34' annotationProcessor 'org.projectlombok:lombok:1.18.34'
implementation "org.slf4j:slf4j-simple:2.0.16"
} }
java { java {

View File

@ -1,5 +1,7 @@
package dev.ninjdai.werewolf; package dev.ninjdai.werewolf;
import dev.ninjdai.werewolf.commands.LGCommand;
import dev.ninjdai.werewolf.uhc.UHCPlayer;
import dev.ninjdai.werewolf.uhc.events.UHCPlayerDeathEvent; import dev.ninjdai.werewolf.uhc.events.UHCPlayerDeathEvent;
import io.github.togar2.pvp.MinestomPvP; import io.github.togar2.pvp.MinestomPvP;
import io.github.togar2.pvp.feature.CombatFeatureSet; import io.github.togar2.pvp.feature.CombatFeatureSet;
@ -9,12 +11,23 @@ import net.minestom.server.coordinate.Pos;
import net.minestom.server.entity.Player; import net.minestom.server.entity.Player;
import net.minestom.server.event.GlobalEventHandler; import net.minestom.server.event.GlobalEventHandler;
import net.minestom.server.event.player.AsyncPlayerConfigurationEvent; import net.minestom.server.event.player.AsyncPlayerConfigurationEvent;
import net.minestom.server.extras.lan.OpenToLAN;
import net.minestom.server.extras.velocity.VelocityProxy;
import net.minestom.server.instance.InstanceContainer; import net.minestom.server.instance.InstanceContainer;
import net.minestom.server.instance.InstanceManager; import net.minestom.server.instance.InstanceManager;
import net.minestom.server.instance.LightingChunk; import net.minestom.server.instance.LightingChunk;
import net.minestom.server.instance.block.Block; import net.minestom.server.instance.block.Block;
import net.minestom.server.network.PlayerProvider;
import net.minestom.server.network.player.PlayerConnection;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.UUID;
public class Main { public class Main {
public static final Logger LOGGER = LoggerFactory.getLogger("Playground");
public static void main(String[] args) { public static void main(String[] args) {
MinecraftServer minecraftServer = MinecraftServer.init(); MinecraftServer minecraftServer = MinecraftServer.init();
@ -30,13 +43,20 @@ public class Main {
player.setRespawnPoint(new Pos(0, 42, 0)); player.setRespawnPoint(new Pos(0, 42, 0));
}); });
MinestomPvP.init(); MinecraftServer.getCommandManager().register(new LGCommand());
MinestomPvP.init();
CombatFeatureSet legacyVanilla = CombatFeatures.legacyVanilla(); CombatFeatureSet legacyVanilla = CombatFeatures.legacyVanilla();
MinecraftServer.getGlobalEventHandler().addChild(legacyVanilla.createNode()); MinecraftServer.getGlobalEventHandler().addChild(legacyVanilla.createNode());
MinecraftServer.getConnectionManager().setPlayerProvider(UHCPlayer::new);
UHCPlayerDeathEvent.register(); UHCPlayerDeathEvent.register();
OpenToLAN.open();
MinecraftServer.setBrandName("Playground");
VelocityProxy.enable("cMkrrJ8tdUS6");
minecraftServer.start("0.0.0.0", 30065); minecraftServer.start("0.0.0.0", 30065);
} }
} }

View File

@ -0,0 +1,19 @@
package dev.ninjdai.werewolf.commands;
import net.minestom.server.command.builder.Command;
import net.minestom.server.command.builder.arguments.ArgumentType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class LGCommand extends Command {
public LGCommand() {
super("lg", "loupgarou", "werewolf");
// Executed if no other executor can be used
setDefaultExecutor((sender, context) -> {
sender.sendMessage("LG UHC");
});
addSubcommand(new LGTeamCommand());
}
}

View File

@ -0,0 +1,76 @@
package dev.ninjdai.werewolf.commands;
import dev.ninjdai.werewolf.Main;
import dev.ninjdai.werewolf.uhc.UHCPlayer;
import dev.ninjdai.werewolf.uhc.roles.Role;
import dev.ninjdai.werewolf.uhc.roles.Roles;
import dev.ninjdai.werewolf.uhc.teams.Team;
import dev.ninjdai.werewolf.uhc.teams.Teams;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.Style;
import net.kyori.adventure.text.format.TextColor;
import net.kyori.adventure.text.format.TextDecoration;
import net.minestom.server.command.builder.Command;
import net.minestom.server.command.builder.arguments.ArgumentEnum;
import net.minestom.server.command.builder.arguments.ArgumentType;
import net.minestom.server.command.builder.arguments.minecraft.ArgumentEntity;
import net.minestom.server.entity.Player;
import net.minestom.server.utils.entity.EntityFinder;
public class LGRoleCommand extends Command {
static final ArgumentEnum<Roles> roleArgument = ArgumentType.Enum("target_role", Roles.class);
static final ArgumentEntity singlePlayerArgument = ArgumentType.Entity("player").onlyPlayers(true).singleEntity(true);
public LGRoleCommand() {
super("role");
addSubcommand(new LGRoleAddCommand());
addSubcommand(new LGRoleGetCommand());
setDefaultExecutor(((sender, context) -> sender.sendMessage("Please select an action")));
}
static class LGRoleAddCommand extends Command {
public LGRoleAddCommand() {
super("add");
addSyntax(((sender, context) -> {
EntityFinder finder = context.get(singlePlayerArgument);
UHCPlayer player = (UHCPlayer) finder.findFirstPlayer(sender);
Role role = context.get(roleArgument).role;
if (player == null) {
sender.sendMessage("Couldn't find player");
return;
}
player.setUHCRole(role);
sender.sendMessage(Component.empty().style(Style.style(TextDecoration.ITALIC))
.append(Component.text(player.getUsername()))
.append(Component.text(" now has role ", TextColor.color(94,94,94)))
.append(Component.text(role.getName()))
);
}), roleArgument, singlePlayerArgument);
}
}
static class LGRoleGetCommand extends Command {
public LGRoleGetCommand() {
super("get");
addSyntax(((sender, context) -> {
EntityFinder finder = context.get(singlePlayerArgument);
UHCPlayer player = (UHCPlayer) finder.findFirstPlayer(sender);
if (player == null) {
sender.sendMessage("Couldn't find player");
return;
}
Role role = player.getUHCRole();
sender.sendMessage(Component.empty().style(Style.style(TextDecoration.ITALIC))
.append(Component.text(player.getUsername()))
.append(Component.text(" has role ", TextColor.color(94,94,94)))
.append(Component.text(role.getName()))
);
}), singlePlayerArgument);
}
}
}

View File

@ -0,0 +1,74 @@
package dev.ninjdai.werewolf.commands;
import dev.ninjdai.werewolf.Main;
import dev.ninjdai.werewolf.uhc.UHCPlayer;
import dev.ninjdai.werewolf.uhc.teams.Team;
import dev.ninjdai.werewolf.uhc.teams.Teams;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.Style;
import net.kyori.adventure.text.format.TextColor;
import net.kyori.adventure.text.format.TextDecoration;
import net.minestom.server.command.builder.Command;
import net.minestom.server.command.builder.arguments.ArgumentEnum;
import net.minestom.server.command.builder.arguments.ArgumentType;
import net.minestom.server.command.builder.arguments.minecraft.ArgumentEntity;
import net.minestom.server.entity.Player;
import net.minestom.server.utils.entity.EntityFinder;
public class LGTeamCommand extends Command {
static final ArgumentEnum<Teams> teamArgument = ArgumentType.Enum("target_team", Teams.class);
static final ArgumentEntity singlePlayerArgument = ArgumentType.Entity("player").onlyPlayers(true).singleEntity(true);
public LGTeamCommand() {
super("team");
addSubcommand(new LGTeamAddCommand());
addSubcommand(new LGTeamGetCommand());
setDefaultExecutor(((sender, context) -> sender.sendMessage("Please select an action")));
}
static class LGTeamAddCommand extends Command {
public LGTeamAddCommand() {
super("add");
addSyntax(((sender, context) -> {
EntityFinder finder = context.get(singlePlayerArgument);
UHCPlayer player = (UHCPlayer) finder.findFirstPlayer(sender);
Team team = context.get(teamArgument).team;
if (player == null) {
sender.sendMessage("Couldn't find player");
return;
}
player.setUHCTeam(team);
sender.sendMessage(Component.empty().style(Style.style(TextDecoration.ITALIC))
.append(Component.text(player.getUsername(), TextColor.color(team.getColor())))
.append(Component.text(" added to team ", TextColor.color(94,94,94)))
.append(Component.text(team.getName(), TextColor.color(team.getColor())))
);
}), teamArgument, singlePlayerArgument);
}
}
static class LGTeamGetCommand extends Command {
public LGTeamGetCommand() {
super("get");
addSyntax(((sender, context) -> {
EntityFinder finder = context.get(singlePlayerArgument);
UHCPlayer player = (UHCPlayer) finder.findFirstPlayer(sender);
if (player == null) {
sender.sendMessage("Couldn't find player");
return;
}
Team team = player.getUHCTeam();
sender.sendMessage(Component.empty().style(Style.style(TextDecoration.ITALIC))
.append(Component.text(player.getUsername(), TextColor.color(team.getColor())))
.append(Component.text(" belongs to team ", TextColor.color(94,94,94)))
.append(Component.text(team.getName(), TextColor.color(team.getColor())))
);
}), singlePlayerArgument);
}
}
}

View File

@ -0,0 +1,58 @@
package dev.ninjdai.werewolf.uhc;
import dev.ninjdai.werewolf.uhc.roles.Role;
import dev.ninjdai.werewolf.uhc.roles.Roles;
import dev.ninjdai.werewolf.uhc.teams.Team;
import dev.ninjdai.werewolf.uhc.teams.Teams;
import io.github.togar2.pvp.MinestomPvP;
import io.github.togar2.pvp.player.CombatPlayerImpl;
import lombok.Getter;
import net.minestom.server.entity.GameMode;
import net.minestom.server.network.packet.server.play.WorldBorderSizePacket;
import net.minestom.server.network.player.PlayerConnection;
import net.minestom.server.potion.Potion;
import net.minestom.server.potion.PotionEffect;
import net.minestom.server.timer.TaskSchedule;
import org.jetbrains.annotations.NotNull;
import java.util.Optional;
import java.util.UUID;
public class UHCPlayer extends CombatPlayerImpl {
@Getter private boolean spectating;
public UHCPlayer(@NotNull UUID uuid, @NotNull String username, @NotNull PlayerConnection playerConnection) {
super(uuid, username, playerConnection);
}
public void setUHCTeam(Team team) {
this.updateTag(Team.teamTag, (t) -> team.getId());
}
public Team getUHCTeam() {
return Team.teamMap.getOrDefault(getTag(Team.teamTag), Teams.VILLAGERS.get());
}
public void setUHCRole(Role role) {
this.updateTag(Role.roleTag, (r) -> role.getId());
}
public Role getUHCRole() {
String teamId = getTag(Role.roleTag);
return Role.roleMap.getOrDefault(teamId, Roles.VILLAGER.role);
}
public void toggleSpectating() {
if (isSpectating()) {
spectating = false;
setGameMode(GameMode.SURVIVAL);
setInvisible(false);
} else {
spectating = true;
addEffect(new Potion(PotionEffect.BLINDNESS, (byte) 3, 100, (byte) 0));
setGameMode(GameMode.SPECTATOR);
setInvisible(true);
}
}
}

View File

@ -11,7 +11,7 @@ import net.minestom.server.potion.PotionEffect;
public class WerewolfStrength extends Effect { public class WerewolfStrength extends Effect {
int duration = 5000; int duration = 5000;
EffectProperty property = new EffectProperty.Builder() EffectProperty effectProperty = new EffectProperty.Builder()
.setPotion(new Potion(PotionEffect.STRENGTH, (byte)1, duration)) .setPotion(new Potion(PotionEffect.STRENGTH, (byte)1, duration))
.setTimeData(new EffectProperty.TimeData(0, duration)) .setTimeData(new EffectProperty.TimeData(0, duration))
.build(); .build();

View File

@ -1,9 +1,12 @@
package dev.ninjdai.werewolf.uhc.events; package dev.ninjdai.werewolf.uhc.events;
import dev.ninjdai.werewolf.uhc.UHCPlayer;
import dev.ninjdai.werewolf.uhc.roles.Role; import dev.ninjdai.werewolf.uhc.roles.Role;
import dev.ninjdai.werewolf.uhc.roles.RoleProperties; import dev.ninjdai.werewolf.uhc.roles.RoleProperties;
import dev.ninjdai.werewolf.uhc.roles.Roles;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.minestom.server.MinecraftServer; import net.minestom.server.MinecraftServer;
import net.minestom.server.coordinate.Pos;
import net.minestom.server.entity.Entity; import net.minestom.server.entity.Entity;
import net.minestom.server.entity.ItemEntity; import net.minestom.server.entity.ItemEntity;
import net.minestom.server.entity.Player; import net.minestom.server.entity.Player;
@ -14,16 +17,20 @@ import net.minestom.server.timer.Task;
import net.minestom.server.timer.TaskSchedule; import net.minestom.server.timer.TaskSchedule;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.time.Duration;
public class TimedPlayerDeath { public class TimedPlayerDeath {
private final ItemStack[] inventory; private final ItemStack[] inventory;
private final Instance instance; private final Instance instance;
private final Player targetPlayer; private final Pos deathPos;
private final UHCPlayer targetPlayer;
private final Task triggerTask; private final Task triggerTask;
public TimedPlayerDeath(@NotNull Player player, @NotNull Damage damage, int seconds) { public TimedPlayerDeath(@NotNull Player player, @NotNull Damage damage, int seconds) {
this.inventory = player.getInventory().getItemStacks(); this.inventory = player.getInventory().getItemStacks();
this.instance = player.getInstance(); this.instance = player.getInstance();
this.targetPlayer = player; this.deathPos = player.getPosition();
this.targetPlayer = (UHCPlayer) player;
this.triggerTask = MinecraftServer.getSchedulerManager().scheduleTask(this::trigger, TaskSchedule.seconds(seconds)); this.triggerTask = MinecraftServer.getSchedulerManager().scheduleTask(this::trigger, TaskSchedule.seconds(seconds));
} }
@ -34,11 +41,12 @@ public class TimedPlayerDeath {
private TaskSchedule trigger(){ private TaskSchedule trigger(){
for (ItemStack itemStack: inventory) { for (ItemStack itemStack: inventory) {
instance.getEntities().add(new ItemEntity(itemStack)); ItemEntity e = new ItemEntity(itemStack);
e.setPickupDelay(Duration.ofSeconds(1));
e.setInstance(this.instance, deathPos);
} }
if ((!this.targetPlayer.getTag(Role.roleTag).isBlank()) if(!targetPlayer.getUHCRole().getRoleProperties().contains(RoleProperties.NO_DEATH_MESSAGE)) {
&& (!Role.roleMap.get(targetPlayer.getTag(Role.roleTag)).getRoleProperties().contains(RoleProperties.NO_DEATH_MESSAGE))) {
this.instance.sendMessage(Component.text(targetPlayer.getUsername()).append(Component.text(" died"))); this.instance.sendMessage(Component.text(targetPlayer.getUsername()).append(Component.text(" died")));
} }

View File

@ -1,6 +1,10 @@
package dev.ninjdai.werewolf.uhc.events; package dev.ninjdai.werewolf.uhc.events;
import dev.ninjdai.werewolf.uhc.UHCPlayer;
import dev.ninjdai.werewolf.uhc.roles.Role;
import dev.ninjdai.werewolf.uhc.roles.Roles;
import dev.ninjdai.werewolf.uhc.teams.Team; import dev.ninjdai.werewolf.uhc.teams.Team;
import dev.ninjdai.werewolf.uhc.teams.Teams;
import dev.ninjdai.werewolf.uhc.teams.WinCondition; import dev.ninjdai.werewolf.uhc.teams.WinCondition;
import io.github.togar2.pvp.events.EntityPreDeathEvent; import io.github.togar2.pvp.events.EntityPreDeathEvent;
import net.minestom.server.MinecraftServer; import net.minestom.server.MinecraftServer;
@ -12,16 +16,19 @@ import net.minestom.server.event.trait.EntityEvent;
public class UHCPlayerDeathEvent { public class UHCPlayerDeathEvent {
public static void onPlayerDeath(EntityPreDeathEvent event) { public static void onPlayerDeath(EntityPreDeathEvent event) {
Player player = (Player) event.getEntity(); UHCPlayer player = (UHCPlayer) event.getEntity();
if(event.getDamage().getAttacker() instanceof Player killer && !killer.getTag(Team.teamTag).isBlank()) { if(event.getDamage().getAttacker() instanceof UHCPlayer killer) {
Team team = Team.teamMap.get(killer.getTag(Team.teamTag)); Team team = Team.teamMap.get(killer.getUHCTeam().getId());
WinCondition.checkTeamWin(team, event.getInstance().getPlayers()); WinCondition.checkTeamWin(team, event.getInstance().getPlayers());
} }
event.setCancelDeath(true); event.setCancelDeath(true);
player.setGameMode(GameMode.SPECTATOR); player.toggleSpectating();
var timedPlayerDeath = new TimedPlayerDeath(player, event.getDamage(), 15); var timedPlayerDeath = new TimedPlayerDeath(player, event.getDamage(), 15);
player.getUHCRole().onPlayerDeath(player, timedPlayerDeath);
} }
public static void register() { public static void register() {
@ -29,7 +36,7 @@ public class UHCPlayerDeathEvent {
MinecraftServer.getGlobalEventHandler().addChild(playerNode); MinecraftServer.getGlobalEventHandler().addChild(playerNode);
playerNode.addListener(EntityPreDeathEvent.class, event -> { playerNode.addListener(EntityPreDeathEvent.class, event -> {
if (event.getEntity() instanceof Player) onPlayerDeath(event); if (event.getEntity() instanceof UHCPlayer) onPlayerDeath(event);
}); });
} }
} }

View File

@ -1,9 +1,16 @@
package dev.ninjdai.werewolf.uhc.roles; package dev.ninjdai.werewolf.uhc.roles;
import dev.ninjdai.werewolf.uhc.UHCPlayer;
import dev.ninjdai.werewolf.uhc.effects.Effect; import dev.ninjdai.werewolf.uhc.effects.Effect;
import dev.ninjdai.werewolf.uhc.events.TimedPlayerDeath;
import lombok.Getter; import lombok.Getter;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.TextColor;
import net.minestom.server.color.Color;
import net.minestom.server.entity.Player;
import net.minestom.server.item.ItemStack; import net.minestom.server.item.ItemStack;
import net.minestom.server.tag.Tag; import net.minestom.server.tag.Tag;
import net.minestom.server.timer.Task;
import java.util.*; import java.util.*;
@ -34,16 +41,22 @@ public class Role {
@Getter private List<Effect> roleEffects; @Getter private List<Effect> roleEffects;
@Getter private Set<RoleProperties> roleProperties; @Getter private Set<RoleProperties> roleProperties;
public void onPlayerDeath(UHCPlayer player, TimedPlayerDeath timedPlayerDeath) {
player.sendMessage(Component.text("", TextColor.color(184,14,14))
.append(Component.text("You died, but don't leave too soon ! You may be resurrected in the next 15 seconds.\nYou can still watch the game after dying definitely."))
);
}
public static Tag<String> roleTag = Tag.String("role"); public static Tag<String> roleTag = Tag.String("role");
// ID: Role // ID: Role
public static Map<String, Role> roleMap = new HashMap<>(); public static final Map<String, Role> roleMap = new HashMap<>();
public static class Builder { public static class Builder {
String id = "dummy"; String id = "DUMMY";
String name = "Dummy"; String name = "Dummy";
private List<ItemStack> roleItems = List.of(); private List<ItemStack> roleItems = new ArrayList<>();
private List<Effect> roleEffects = List.of(); private List<Effect> roleEffects = new ArrayList<>();
Set<RoleProperties> roleProperties = new HashSet<>(); Set<RoleProperties> roleProperties = new HashSet<>();
public Builder setId(String id) { public Builder setId(String id) {
@ -76,6 +89,11 @@ public class Role {
return this; return this;
} }
public Builder addRoleEffect(Effect roleEffect) {
this.roleEffects.add(roleEffect);
return this;
}
public Builder setRoleProperties(Set<RoleProperties> roleProperties) { public Builder setRoleProperties(Set<RoleProperties> roleProperties) {
this.roleProperties = roleProperties; this.roleProperties = roleProperties;
return this; return this;

View File

@ -2,6 +2,19 @@ package dev.ninjdai.werewolf.uhc.roles;
import dev.ninjdai.werewolf.uhc.effects.werewolves.WerewolfStrength; import dev.ninjdai.werewolf.uhc.effects.werewolves.WerewolfStrength;
public class Roles { import java.util.HashMap;
public static Role werewolf = new Role.Builder().addRoleEffects(new WerewolfStrength()).build(); import java.util.Map;
public enum Roles {
WEREWOLF(new Role.Builder().setId("werewolf").setName("Werewolf").addRoleEffect(new WerewolfStrength()).build()),
VILLAGER(new Role.Builder().setId("villager").setName("Villager").build());
public final Role role;
Roles(Role role) {
this.role = role;
}
public Role get() {
return this.role;
}
} }

View File

@ -34,10 +34,13 @@ public class Team {
public static Tag<String> teamTag = Tag.String("team"); public static Tag<String> teamTag = Tag.String("team");
// ID: Team // ID: Team
public static Map<String, Team> teamMap = new HashMap<>(); public static final Map<String, Team> teamMap;
static {
teamMap = new HashMap<>();
};
public static class Builder { public static class Builder {
private String id = "dummy"; private String id = "DUMMY";
private String name = "Dummy"; private String name = "Dummy";
private Color color = new Color(0, 0, 0); private Color color = new Color(0, 0, 0);
private WinCondition.WinConditionType winConditionType = WinCondition.WinConditionType.ONLY_TEAM_REMAINING; private WinCondition.WinConditionType winConditionType = WinCondition.WinConditionType.ONLY_TEAM_REMAINING;

View File

@ -1,8 +1,22 @@
package dev.ninjdai.werewolf.uhc.teams; package dev.ninjdai.werewolf.uhc.teams;
import dev.ninjdai.werewolf.uhc.roles.Role;
import net.minestom.server.color.Color; import net.minestom.server.color.Color;
public class Teams { import java.util.HashMap;
public static Team werewolves = new Team.Builder().setId("werewolves").setName("Werewolves").setColor(new Color(150,10,10)).build(); import java.util.Map;
public static Team villagers = new Team.Builder().setId("villagers").setName("Villagers").setColor(new Color(48,216,90)).build();
public enum Teams {
WEREWOLVES(new Team.Builder().setId("werewolves").setName("Werewolves").setColor(new Color(150,10,10)).build()),
VILLAGERS(new Team.Builder().setId("villagers").setName("Villagers").setColor(new Color(48,216,90)).build()),
COUPLE(new Team.Builder().setId("couple").setName("Couple").setColor(new Color(195,61,148)).build());
public final Team team;
Teams(Team team) {
this.team = team;
}
public Team get() {
return this.team;
}
} }