diff --git a/build.gradle b/build.gradle index e422086..11afeb9 100644 --- a/build.gradle +++ b/build.gradle @@ -17,6 +17,8 @@ dependencies { compileOnly 'org.projectlombok:lombok:1.18.34' annotationProcessor 'org.projectlombok:lombok:1.18.34' + + implementation "org.slf4j:slf4j-simple:2.0.16" } java { diff --git a/src/main/java/dev/ninjdai/werewolf/Main.java b/src/main/java/dev/ninjdai/werewolf/Main.java index a2d527c..fe37731 100644 --- a/src/main/java/dev/ninjdai/werewolf/Main.java +++ b/src/main/java/dev/ninjdai/werewolf/Main.java @@ -1,5 +1,7 @@ package dev.ninjdai.werewolf; +import dev.ninjdai.werewolf.commands.LGCommand; +import dev.ninjdai.werewolf.uhc.UHCPlayer; import dev.ninjdai.werewolf.uhc.events.UHCPlayerDeathEvent; import io.github.togar2.pvp.MinestomPvP; 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.event.GlobalEventHandler; 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.InstanceManager; import net.minestom.server.instance.LightingChunk; 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 static final Logger LOGGER = LoggerFactory.getLogger("Playground"); + public static void main(String[] args) { MinecraftServer minecraftServer = MinecraftServer.init(); @@ -30,13 +43,20 @@ public class Main { player.setRespawnPoint(new Pos(0, 42, 0)); }); - MinestomPvP.init(); + MinecraftServer.getCommandManager().register(new LGCommand()); + MinestomPvP.init(); CombatFeatureSet legacyVanilla = CombatFeatures.legacyVanilla(); MinecraftServer.getGlobalEventHandler().addChild(legacyVanilla.createNode()); + MinecraftServer.getConnectionManager().setPlayerProvider(UHCPlayer::new); + UHCPlayerDeathEvent.register(); + OpenToLAN.open(); + MinecraftServer.setBrandName("Playground"); + VelocityProxy.enable("cMkrrJ8tdUS6"); + minecraftServer.start("0.0.0.0", 30065); } } diff --git a/src/main/java/dev/ninjdai/werewolf/commands/LGCommand.java b/src/main/java/dev/ninjdai/werewolf/commands/LGCommand.java new file mode 100644 index 0000000..5a44ae9 --- /dev/null +++ b/src/main/java/dev/ninjdai/werewolf/commands/LGCommand.java @@ -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()); + } +} diff --git a/src/main/java/dev/ninjdai/werewolf/commands/LGRoleCommand.java b/src/main/java/dev/ninjdai/werewolf/commands/LGRoleCommand.java new file mode 100644 index 0000000..b4e219b --- /dev/null +++ b/src/main/java/dev/ninjdai/werewolf/commands/LGRoleCommand.java @@ -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 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); + } + } +} diff --git a/src/main/java/dev/ninjdai/werewolf/commands/LGTeamCommand.java b/src/main/java/dev/ninjdai/werewolf/commands/LGTeamCommand.java new file mode 100644 index 0000000..0041d36 --- /dev/null +++ b/src/main/java/dev/ninjdai/werewolf/commands/LGTeamCommand.java @@ -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 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); + } + } +} diff --git a/src/main/java/dev/ninjdai/werewolf/uhc/UHCPlayer.java b/src/main/java/dev/ninjdai/werewolf/uhc/UHCPlayer.java new file mode 100644 index 0000000..f4bd500 --- /dev/null +++ b/src/main/java/dev/ninjdai/werewolf/uhc/UHCPlayer.java @@ -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); + } + } +} diff --git a/src/main/java/dev/ninjdai/werewolf/uhc/effects/werewolves/WerewolfStrength.java b/src/main/java/dev/ninjdai/werewolf/uhc/effects/werewolves/WerewolfStrength.java index a985197..ce55352 100644 --- a/src/main/java/dev/ninjdai/werewolf/uhc/effects/werewolves/WerewolfStrength.java +++ b/src/main/java/dev/ninjdai/werewolf/uhc/effects/werewolves/WerewolfStrength.java @@ -11,7 +11,7 @@ import net.minestom.server.potion.PotionEffect; public class WerewolfStrength extends Effect { int duration = 5000; - EffectProperty property = new EffectProperty.Builder() + EffectProperty effectProperty = new EffectProperty.Builder() .setPotion(new Potion(PotionEffect.STRENGTH, (byte)1, duration)) .setTimeData(new EffectProperty.TimeData(0, duration)) .build(); diff --git a/src/main/java/dev/ninjdai/werewolf/uhc/events/TimedPlayerDeath.java b/src/main/java/dev/ninjdai/werewolf/uhc/events/TimedPlayerDeath.java index 519fde8..2b1e1a6 100644 --- a/src/main/java/dev/ninjdai/werewolf/uhc/events/TimedPlayerDeath.java +++ b/src/main/java/dev/ninjdai/werewolf/uhc/events/TimedPlayerDeath.java @@ -1,9 +1,12 @@ 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.RoleProperties; +import dev.ninjdai.werewolf.uhc.roles.Roles; import net.kyori.adventure.text.Component; import net.minestom.server.MinecraftServer; +import net.minestom.server.coordinate.Pos; import net.minestom.server.entity.Entity; import net.minestom.server.entity.ItemEntity; import net.minestom.server.entity.Player; @@ -14,16 +17,20 @@ import net.minestom.server.timer.Task; import net.minestom.server.timer.TaskSchedule; import org.jetbrains.annotations.NotNull; +import java.time.Duration; + public class TimedPlayerDeath { private final ItemStack[] inventory; private final Instance instance; - private final Player targetPlayer; + private final Pos deathPos; + private final UHCPlayer targetPlayer; private final Task triggerTask; public TimedPlayerDeath(@NotNull Player player, @NotNull Damage damage, int seconds) { this.inventory = player.getInventory().getItemStacks(); 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)); } @@ -34,11 +41,12 @@ public class TimedPlayerDeath { private TaskSchedule trigger(){ 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()) - && (!Role.roleMap.get(targetPlayer.getTag(Role.roleTag)).getRoleProperties().contains(RoleProperties.NO_DEATH_MESSAGE))) { + if(!targetPlayer.getUHCRole().getRoleProperties().contains(RoleProperties.NO_DEATH_MESSAGE)) { this.instance.sendMessage(Component.text(targetPlayer.getUsername()).append(Component.text(" died"))); } diff --git a/src/main/java/dev/ninjdai/werewolf/uhc/events/UHCPlayerDeathEvent.java b/src/main/java/dev/ninjdai/werewolf/uhc/events/UHCPlayerDeathEvent.java index 7378aa7..5c2c72b 100644 --- a/src/main/java/dev/ninjdai/werewolf/uhc/events/UHCPlayerDeathEvent.java +++ b/src/main/java/dev/ninjdai/werewolf/uhc/events/UHCPlayerDeathEvent.java @@ -1,6 +1,10 @@ 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.Teams; import dev.ninjdai.werewolf.uhc.teams.WinCondition; import io.github.togar2.pvp.events.EntityPreDeathEvent; import net.minestom.server.MinecraftServer; @@ -12,16 +16,19 @@ import net.minestom.server.event.trait.EntityEvent; public class UHCPlayerDeathEvent { public static void onPlayerDeath(EntityPreDeathEvent event) { - Player player = (Player) event.getEntity(); - if(event.getDamage().getAttacker() instanceof Player killer && !killer.getTag(Team.teamTag).isBlank()) { - Team team = Team.teamMap.get(killer.getTag(Team.teamTag)); + UHCPlayer player = (UHCPlayer) event.getEntity(); + if(event.getDamage().getAttacker() instanceof UHCPlayer killer) { + Team team = Team.teamMap.get(killer.getUHCTeam().getId()); WinCondition.checkTeamWin(team, event.getInstance().getPlayers()); } event.setCancelDeath(true); - player.setGameMode(GameMode.SPECTATOR); + player.toggleSpectating(); + var timedPlayerDeath = new TimedPlayerDeath(player, event.getDamage(), 15); + + player.getUHCRole().onPlayerDeath(player, timedPlayerDeath); } public static void register() { @@ -29,7 +36,7 @@ public class UHCPlayerDeathEvent { MinecraftServer.getGlobalEventHandler().addChild(playerNode); playerNode.addListener(EntityPreDeathEvent.class, event -> { - if (event.getEntity() instanceof Player) onPlayerDeath(event); + if (event.getEntity() instanceof UHCPlayer) onPlayerDeath(event); }); } } diff --git a/src/main/java/dev/ninjdai/werewolf/uhc/roles/Role.java b/src/main/java/dev/ninjdai/werewolf/uhc/roles/Role.java index df0bf32..aa516e7 100644 --- a/src/main/java/dev/ninjdai/werewolf/uhc/roles/Role.java +++ b/src/main/java/dev/ninjdai/werewolf/uhc/roles/Role.java @@ -1,9 +1,16 @@ package dev.ninjdai.werewolf.uhc.roles; +import dev.ninjdai.werewolf.uhc.UHCPlayer; import dev.ninjdai.werewolf.uhc.effects.Effect; +import dev.ninjdai.werewolf.uhc.events.TimedPlayerDeath; 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.tag.Tag; +import net.minestom.server.timer.Task; import java.util.*; @@ -34,16 +41,22 @@ public class Role { @Getter private List roleEffects; @Getter private Set 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 roleTag = Tag.String("role"); // ID: Role - public static Map roleMap = new HashMap<>(); + public static final Map roleMap = new HashMap<>(); public static class Builder { - String id = "dummy"; + String id = "DUMMY"; String name = "Dummy"; - private List roleItems = List.of(); - private List roleEffects = List.of(); + private List roleItems = new ArrayList<>(); + private List roleEffects = new ArrayList<>(); Set roleProperties = new HashSet<>(); public Builder setId(String id) { @@ -76,6 +89,11 @@ public class Role { return this; } + public Builder addRoleEffect(Effect roleEffect) { + this.roleEffects.add(roleEffect); + return this; + } + public Builder setRoleProperties(Set roleProperties) { this.roleProperties = roleProperties; return this; diff --git a/src/main/java/dev/ninjdai/werewolf/uhc/roles/Roles.java b/src/main/java/dev/ninjdai/werewolf/uhc/roles/Roles.java index ce0eda2..b72516c 100644 --- a/src/main/java/dev/ninjdai/werewolf/uhc/roles/Roles.java +++ b/src/main/java/dev/ninjdai/werewolf/uhc/roles/Roles.java @@ -2,6 +2,19 @@ package dev.ninjdai.werewolf.uhc.roles; import dev.ninjdai.werewolf.uhc.effects.werewolves.WerewolfStrength; -public class Roles { - public static Role werewolf = new Role.Builder().addRoleEffects(new WerewolfStrength()).build(); +import java.util.HashMap; +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; + } } diff --git a/src/main/java/dev/ninjdai/werewolf/uhc/teams/Team.java b/src/main/java/dev/ninjdai/werewolf/uhc/teams/Team.java index 13c00ed..c925787 100644 --- a/src/main/java/dev/ninjdai/werewolf/uhc/teams/Team.java +++ b/src/main/java/dev/ninjdai/werewolf/uhc/teams/Team.java @@ -34,10 +34,13 @@ public class Team { public static Tag teamTag = Tag.String("team"); // ID: Team - public static Map teamMap = new HashMap<>(); + public static final Map teamMap; + static { + teamMap = new HashMap<>(); + }; public static class Builder { - private String id = "dummy"; + private String id = "DUMMY"; private String name = "Dummy"; private Color color = new Color(0, 0, 0); private WinCondition.WinConditionType winConditionType = WinCondition.WinConditionType.ONLY_TEAM_REMAINING; diff --git a/src/main/java/dev/ninjdai/werewolf/uhc/teams/Teams.java b/src/main/java/dev/ninjdai/werewolf/uhc/teams/Teams.java index 59d2a47..5210727 100644 --- a/src/main/java/dev/ninjdai/werewolf/uhc/teams/Teams.java +++ b/src/main/java/dev/ninjdai/werewolf/uhc/teams/Teams.java @@ -1,8 +1,22 @@ package dev.ninjdai.werewolf.uhc.teams; +import dev.ninjdai.werewolf.uhc.roles.Role; import net.minestom.server.color.Color; -public class Teams { - public static Team werewolves = new Team.Builder().setId("werewolves").setName("Werewolves").setColor(new Color(150,10,10)).build(); - public static Team villagers = new Team.Builder().setId("villagers").setName("Villagers").setColor(new Color(48,216,90)).build(); +import java.util.HashMap; +import java.util.Map; + +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; + } }