Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft : Capture the flag #44

Open
wants to merge 25 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
d1d3c67
Début du jeu CTF
orwenn22 Sep 12, 2023
d55bc11
CTF : amélioration code
orwenn22 Sep 13, 2023
847be56
CTF : ramener drapeau adverse à sa base
orwenn22 Sep 13, 2023
d778031
CTF : scoreboard avec les scores
orwenn22 Sep 13, 2023
dfaae9a
CTF : retirer commentaire TODO
orwenn22 Sep 13, 2023
b42becd
CTF : rendre le jeu gagnable
orwenn22 Sep 14, 2023
0b642b7
CTF : effet de glow
orwenn22 Sep 14, 2023
2aeb53d
CTF : drop le drapeau au sol
orwenn22 Sep 14, 2023
1338ead
CTF : cercles autour des spawns de drapeaux
orwenn22 Sep 15, 2023
9d16ab1
CTF : renommer teams en français
orwenn22 Sep 15, 2023
a60fda6
CTF:Ne pas drop le drapeau si joueur meurt dans le vide
orwenn22 Sep 16, 2023
ab41249
CTF : 8 joueurs max dans la game
orwenn22 Sep 17, 2023
5905c6e
CTF : amélioration check si le joueur casse son propre drapeau
orwenn22 Sep 17, 2023
a6a7ab4
CTF : ajouter killzone
orwenn22 Oct 1, 2023
a3f9f41
CTF : suivre la position des drapeaux
orwenn22 Oct 1, 2023
f1d5223
CTF: toujours drop le drapeau sur un block solide
orwenn22 Nov 9, 2023
ac3a4cf
CTF: amélioration drop drapeau
orwenn22 Nov 9, 2023
0c50291
CTF : utiliser TeamWin pour définir les vainqueurs
orwenn22 Dec 14, 2023
2401c97
Merge remote-tracking branch 'origin/dev' into CTF
orwenn22 Dec 14, 2023
39bde86
CTF : typo belowBock -> belowBlock
orwenn22 Dec 15, 2023
8183c2c
CTF : game_points -> gamePoint
orwenn22 Dec 15, 2023
211a8ef
CTF : belowBlock
orwenn22 Dec 15, 2023
4459613
CTF : ne pas utiliser le snake case dans initFlags
orwenn22 Dec 15, 2023
585eb48
CTF : Ne pas hardcoder les positions dans l'inventaire
orwenn22 Jan 5, 2024
e550b48
CTF : Gérer les particules dans une classe séparé
orwenn22 Jan 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions games/ctf/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import net.minecrell.pluginyml.bukkit.BukkitPluginDescription

plugins {
`java-library`
id("net.minecrell.plugin-yml.bukkit") version "0.5.2" // Generates plugin.yml
}

dependencies {
implementation(project(":core"))

compileOnly("io.papermc.paper:paper-api:1.19.2-R0.1-SNAPSHOT")

compileOnly("fr.efreicraft:ECATUP:latest.integration")
}

bukkit {
load = BukkitPluginDescription.PluginLoadOrder.POSTWORLD
name = "LudosCTF"
main = "fr.efreicraft.ludos.games.ctf.Main"
apiVersion = "1.19"
authors = listOf("Ewenn BAUDET")
prefix = "CTF"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package fr.efreicraft.ludos.games.ctf;

import fr.efreicraft.ludos.core.Core;
import fr.efreicraft.ludos.core.games.interfaces.GameWinner;
import fr.efreicraft.ludos.core.players.LudosPlayer;
import org.bukkit.Color;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

public record CtfWinners(String teamKey, Color teamColor) implements GameWinner {
@Override
public Color getFireworkColor() {
return Core.get().getTeamManager().getTeam(teamKey).getColor().bukkitColor();
}

@Override
public List<LudosPlayer> getPlayers() {
Set<LudosPlayer> teamPlayers = Core.get().getTeamManager().getTeam(teamKey).getPlayers();
return new ArrayList<>(teamPlayers);
}

@Override
public String getWinnerColoredName() {
String colorCode;
switch(teamKey) {
case "RED" -> colorCode = "&c";
case "BLUE" -> colorCode = "&9";
default -> colorCode = "";
}
return "L'équipe " + colorCode + Core.get().getTeamManager().getTeam(teamKey).getName().toLowerCase();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package fr.efreicraft.ludos.games.ctf;

import fr.efreicraft.ludos.core.Core;
import fr.efreicraft.ludos.core.players.LudosPlayer;
import org.bukkit.Location;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.player.PlayerDropItemEvent;
import org.bukkit.event.player.PlayerMoveEvent;

public record EventListener(GameLogic ctfLogic) implements Listener {
JiveOff marked this conversation as resolved.
Show resolved Hide resolved
@EventHandler
public void onPlayerDrop(PlayerDropItemEvent event) {
event.setCancelled(true);
}

@EventHandler
public void onInventoryClick(InventoryClickEvent event) {
event.setCancelled(true);
}

@EventHandler
public void onPlayerBreakBlock(BlockBreakEvent event) {
LudosPlayer ludosPlayer = Core.get().getPlayerManager().getPlayer(event.getPlayer());

String teamOfFlag; //on doit vérifier si le joueur n'appartient pas à cette team avant de casser le drapeau

//Obtenir la team du drapeau (déplacer ça autre part dans le future ?)
switch (event.getBlock().getBlockData().getMaterial()) {
case RED_BANNER -> teamOfFlag = "Red";
case BLUE_BANNER -> teamOfFlag = "Blue";
default -> {
event.setCancelled(true);
return;
}
}

//gérer le cassage du drapeau
event.setCancelled(ctfLogic.handleBreakFlag(ludosPlayer, teamOfFlag));
}

@EventHandler
public void onDeath(PlayerDeathEvent event) {
LudosPlayer ludosPlayer = Core.get().getPlayerManager().getPlayer(event.getPlayer());
ctfLogic.dropFlagIfCarried(ludosPlayer, true);
}


@EventHandler
public void onBlockPlace(BlockPlaceEvent event) {
/*
LudosPlayer ludosPlayer = Core.get().getPlayerManager().getPlayer(event.getPlayer());
Location blockLocation = event.getBlock().getLocation();
ctfLogic.tryToScore(ludosPlayer, blockLocation);
*/
event.setCancelled(true);
}


@EventHandler
public void onPlayerMove(PlayerMoveEvent event) {
if(!event.hasChangedBlock()) return;

LudosPlayer ludosPlayer = Core.get().getPlayerManager().getPlayer(event.getPlayer());
Location playerLocation = ludosPlayer.entity().getLocation();
ctfLogic.tryToScore(ludosPlayer, playerLocation);
}
}
243 changes: 243 additions & 0 deletions games/ctf/src/main/java/fr/efreicraft/ludos/games/ctf/GameLogic.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,243 @@
package fr.efreicraft.ludos.games.ctf;

import fr.efreicraft.ludos.core.players.LudosPlayer;
import fr.efreicraft.ludos.core.utils.MessageUtils;
import org.bukkit.Color;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.LeatherArmorMeta;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.util.Vector;

import java.util.Objects;

public class GameLogic {
private LudosGame ludosGame;

private Location redLocation = null;
private Location blueLocation = null;

private int scoreTeamRed = 0;
private int scoreTeamBlue = 0;
private static final int SCORE_TO_WIN = 3;


public GameLogic(LudosGame ludosGame1) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tu peux utiliser une classe record pour ne pas avoir de constructeur comme ça

ludosGame = ludosGame1;
}

//Faire apparaître les drapeaux sur la map, et stocker leurs positions
public void initFlags(Location red_location, Location blue_location) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Généralement, on essaye de privilégier un seul casing pour les arguments de méthodes, il faut donc éviter le snake case occasionnel.

redLocation = red_location;
blueLocation = blue_location;

redLocation.getWorld().setBlockData(redLocation, Material.RED_BANNER.createBlockData());
blueLocation.getWorld().setBlockData(blueLocation, Material.BLUE_BANNER.createBlockData());
}

public void preparePlayerToSpawn(LudosPlayer player) {
player.entity().setGameMode(GameMode.SURVIVAL);
player.entity().getInventory().addItem(new ItemStack(Material.DIAMOND_SWORD));

ItemStack chestplate = new ItemStack(Material.LEATHER_CHESTPLATE);
LeatherArmorMeta lam = (LeatherArmorMeta)chestplate.getItemMeta();
lam.setColor(player.getTeam().getColor().bukkitColor());
chestplate.setItemMeta(lam);
player.entity().getInventory().setChestplate(chestplate);
//TODO : ajouter + d'équipement ici ?
}


/**
* Vérifier si le joueur peut casser le drapeau, et si oui le casser.
* @param player joueur qui a cassé le drapeau
* @param teamOfFlag la team du drapeau qui a été cassé
* @return true pour annuler l'event du cassage, sinon retourne false
*/
public boolean handleBreakFlag(LudosPlayer player, String teamOfFlag) {
//Vérifier si le joueur essaie de casser le drapeau de sa propre équipe (si oui le replacer à sa position initiale)
if(Objects.equals(player.getTeam().getName(), teamOfFlag)) {
//Obtenir la position de la base du drapeau et vérifier s'il y est actuellement
Location baseLocation = getBaseLocation(teamOfFlag);
if(baseLocation.getBlock().getBlockData().getMaterial() == getFlagMaterial(teamOfFlag)) return true; //si oui annuler le cassage

//Sinon le replacer à sa position initiale
baseLocation.getWorld().setBlockData(baseLocation, getFlagMaterial(teamOfFlag).createBlockData());
MessageUtils.broadcastMessage(
MessageUtils.ChatPrefix.GAME,
getTeamColorCode(teamOfFlag) + "Le drapeau " + teamOfFlag.toLowerCase()
+ " a été renvoyé à sa base."
);

return false; //Détruire le bloc
}

MessageUtils.broadcastMessage(
MessageUtils.ChatPrefix.GAME,
getTeamColorCode(player.getTeam().getName()) + player.getName()
+ " &ra capturé le drapeau de l'équipe "
+ getTeamColorCode(teamOfFlag) + teamOfFlag.toLowerCase()
);

Material flagMaterial = getFlagMaterial(teamOfFlag);
if(flagMaterial == null) return true;

//Le drapeau est placé sur la tête du joueur qui le récupère afin d'être visible par tout le monde,
//et dans le deuxième slot de la hotbar afin d'être visible par le joueur lui-même
player.entity().getInventory().setHelmet(new ItemStack(flagMaterial));
player.entity().getInventory().setItem(1, new ItemStack(flagMaterial)); //1 = deuxième slot hotbar

//ajouter effet de glow
player.entity().addPotionEffect(new PotionEffect(PotionEffectType.GLOWING, 423310, 1));

return false;
}


/**
* Si le joueur possède un drapeau, il sera retiré de l'inventaire et replacé sur la map
* @param player le joueur dont on souhaite retirer le drapeau
* @param dropOnPlayerPosition true : drop le drapeau à la position du joueur | false : tp le drapeau à sa base
*/
public void dropFlagIfCarried(LudosPlayer player, boolean dropOnPlayerPosition) {
ItemStack helmetItem = player.entity().getInventory().getHelmet();
if(helmetItem == null) return; //Le joueur ne possède aucun drapeau dans ce cas

//Retirer l'effet de glow
player.entity().removePotionEffect(PotionEffectType.GLOWING);

Material helmetSlotMaterial = helmetItem.getType();
player.entity().getInventory().clear(39); //39 = slot helmet
player.entity().getInventory().clear(1); // 1 = deuxième slot hotbar
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Attention aux clear dans les slots quand les joueurs peuvent manipuler leur inventaire.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nbt sur items

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Au final j'ai pas fait avec les nbt, j'utilise juste inventory.remove pour retirer les drapeaux

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Je sais pas si c'est une bonne idée de faire ce que tu as fait avec le slot du helmet mais bon, ça devrait être bon.


//Déterminer où replacer le drapeau sur la map
Location dropLocation;
if(dropOnPlayerPosition) {
dropLocation = player.entity().getLocation();
}
else {
dropLocation = getBaseLocation(helmetSlotMaterial);
if(dropLocation == null) return;
}

//Replacer le drapeau sur la map
dropLocation.getWorld().setBlockData(dropLocation, helmetSlotMaterial.createBlockData());
}


/**
* Appelé lorque l'on souhaite savoir si un joueur peut marquer un point
* @param player joueur qui essaie de marquer un point
* @param locationToCompare position à laquelle on souhaite calculer la distance avec la base du joueur
*/
public void tryToScore(LudosPlayer player, Location locationToCompare) {
ItemStack helmetItem = player.entity().getInventory().getHelmet();
if(helmetItem == null) return; //Le joueur ne possède aucun drapeau dans ce cas

Location baseLocation = getBaseLocation(player.getTeam().getName()); //position de la base du joueur player
if(baseLocation == null) return;

//Vecteur de la distance entre le drapeau qui vient d'être posé et la base du joueur player
Vector vec = new Vector(
locationToCompare.getX() - baseLocation.getX(),
locationToCompare.getY() - baseLocation.getY(),
locationToCompare.getZ() - baseLocation.getZ()
);

//Norme du vecteur
double distance = vec.length();
//player.sendMessage(MessageUtils.ChatPrefix.GAME, distance+"");

//Si la distance est inférieure à 4, alors le joueur marque 1 point pour son équipe
if(distance < 4) {
String playerTeam = player.getTeam().getName();
MessageUtils.broadcastMessage(
MessageUtils.ChatPrefix.GAME,
getTeamColorCode(playerTeam) + player.getName() + " a marqué un point pour l'équipe "
+ playerTeam.toLowerCase()
);
dropFlagIfCarried(player, false); //Refaire spawn le drapeau à la base adverse
incrementScore(player.getTeam().getName());
}
}


//TODO : trouver un moyen de mieux gérer les trucs qu'il y a ci-dessous

/**
* Obtenir la position d'une base (drapeau) à partir d'un nom de team
* @param teamName nom de la team
* @return position de la base de la team (ou null si la team n'existe pas)
*/
public Location getBaseLocation(String teamName) {
switch (teamName) {
case "Red" -> { return redLocation; }
case "Blue" -> { return blueLocation; }
default -> { return null; }
}
}

/**
* Obtenir la position d'une base (drapeau) à partir d'un matériel
* @param material matériel correspondant au drapeau de la team
* @return position de la base de la team (ou null si la team n'existe pas)
*/
public Location getBaseLocation(Material material) {
switch (material) {
case RED_BANNER -> { return redLocation; }
case BLUE_BANNER -> { return blueLocation; }
default -> { return null; }
}
}

public Material getFlagMaterial(String teamName) {
switch(teamName) {
case "Red" -> { return Material.RED_BANNER; }
case "Blue" -> { return Material.BLUE_BANNER; }
default -> { return null; }
}
}

public String getTeamColorCode(String teamName) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Normalement, tu peux récupérer la couleur d'une team avec le getTeam du Team manager.

Aussi, tu peux renommer les teams en "Rouge" et "Bleu" si tu le souhaites.

switch (teamName) {
case "Red" -> { return "&c"; }
case "Blue" -> { return "&9"; }
default -> {return ""; }
}
}

/**
* Incrémenter le score d'une team
* @param teamName nom de la team
*/
public void incrementScore(String teamName) {
switch (teamName) {
case "Red" -> {
scoreTeamRed += 1;
if(scoreTeamRed >= SCORE_TO_WIN)
ludosGame.setWinnerAndEndGame(new CtfWinners("RED", Color.RED));
}
case "Blue" -> {
scoreTeamBlue += 1;
if(scoreTeamBlue >= SCORE_TO_WIN)
ludosGame.setWinnerAndEndGame(new CtfWinners("BLUE", Color.BLUE));
}
}
}

/**
* Obtenir le score d'une team
* @param teamName nom de la team
* @return le score de la team en question (ou -1 si la team n'existe pas)
*/
public int getScore(String teamName) {
switch (teamName) {
case "Red" -> { return scoreTeamRed; }
case "Blue" -> { return scoreTeamBlue; }
default -> { return -1; }
}
}
}
Loading