Skocz do zawartości

Szkielet pluginu na areny/minigry!


Rekomendowane odpowiedzi

Witam wszystkich. W tym poradniku dowiesz się jak stworzyć minigrę typu SquidGame z etapmi gry.

Nie będe tego ukrywał że cały pomysł wpadł mi do głowy oglądając ten serial. Chciałem napisać ten poradnik już dużo wcześniej ale jakoś mnie odrzucało od bukkita :D 

Poradnik jest samym szkieletem, jak zacząć tworzyć pluginy tego typu, brakuje tam dużo elementów np takich jak opuszczenie areny itd.

Cały kod daję tutaj http://hostuje.net/file.php?id=163efc882f7b058689b96ee24e12b5fa a niżej postaram się wyjaśnić co robić i czego nie robić.

Plik nie zawiera żadnych wirusów daje go na hostuje ponieważ mój github jest bardziej prywatny.

Skan: https://www.virustotal.com/gui/file/991c0bd292fc3ce9ce5d832be605da139bc869c425550f07bcd90b39835b613f?nocache=1

Gra będzie polegała na dwóch etapach gry, w pierwszym musimy scraftować 5 przedmiotów.

W drugim etapie musimy zabić pozostałych graczy.

Gracze którzy wytrwają do końca wygrywają.

Przyznam że kod nie jest najlepszy, ale w razie czego służę pomocą!

 

Krok 1.

- najpierw wypadałoby stworzyć klasę główną z jej statyczną instancją.

public class ArenaPlugin extends JavaPlugin {

    @Getter private static ArenaPlugin arenaPlugin;

    @Override
    public void onEnable() {
        arenaPlugin = this;
    }

    @Override
    public void onDisable() {
        super.onDisable();
    }
}

Krok 1.5.

- utile nie ma co się rozwodzić nad ich tematem.

public final class Utils {

    private Utils(){

    }

    public static String color(String text){
        return ChatColor.translateAlternateColorCodes('&', text);
    }

    public static boolean sendMessage(Player player, String text){
        player.sendMessage(color(text));
        return true;
    }
}

 

Krok 2.

- obiekt areny w której będziemy przetrzymywać dane dotyczące areny.

id - id areny.

name - nazwa areny.

time - czas który będzie aktywował poszczególne etapy areny.

maxPlayers - maxymalna liczba graczy która może dołączyć do jednej areny.

playersToStart - wymagana liczba graczy do rozpoczęcia areny. 

status - aktualny etap areny, Etapy gry utworzymy w kroku 3.

locations - lokacje dla wybranych etapów gry.

players - gracze uczestniczący w arenie.

points - punkty, beda potrzebne w jednej z etapow gry.

Dodatkowo funkcja getPs() która pobiera graczy uczestniczących w arenie, chyba nie muszę mówić że przechowywanie obiektu Player w obiekcie jest niebezpieczne.

Oraz funkcja sendMessage() która będzie wysyłała wiadomość do graczy z areny.

@Data
public class Arena {

    private String id;
    private String name;
    private int time;
    private int maxPlayers;
    private int playersToStart;
    private Status status;
    private Map<Status, Location> locations;
    private List<UUID> players;
    private ConcurrentHashMap<UUID, Integer> points;

    public Arena(){
        this.time = 10;
        this.status = Status.WAIT;
        this.locations = new HashMap<>();
        this.players = new ArrayList<>();
        this.points = new ConcurrentHashMap<>();
    }

    public Arena(String id, String name, int maxPlayers, int playersToStart){
        this.id = id;
        this.name = name;
        this.time = 10;
        this.maxPlayers = maxPlayers;
        this.playersToStart = playersToStart;
        this.status = Status.WAIT;
        this.locations = new HashMap<>();
        this.players = new ArrayList<>();
        this.points = new ConcurrentHashMap<>();
    }

    public List<Player> getPs(){
        List<Player> ps = new ArrayList<>();
        for(UUID uuid : getPlayers()){
            Player player = Bukkit.getPlayer(uuid);
            if(player == null) continue;
            ps.add(player);
        }
        return ps;
    }

    public void sendMessage(String msg){
        for(Player player : getPs()){
            Utils.sendMessage(player, msg);
        }
    }

    public Player getPlayer(UUID uuid){
        return Bukkit.getPlayer(uuid);
    }
}

Krok 3.

- etapy areny

 

public enum Status {

    WAIT,
    COUNT,
    PRE_GAME1,
    GAME1,
    END_GAME1,
    PRE_GAME2,
    GAME2,
    END_GAME2,
    END;
}

 

Krok 4.

- ArenaStorage - inaczej manager, będziemy tam przechowywać wszystkie areny.

- zmienna ARENAS przechowuje arene w mapie.

- funkcja load() tworzy arene - ja stworzyłem tylko jedną, tutaj uzupełniasz dane obiektu Arena

- dodatkowo funkcja arenaFromPlayer() która pobiera arene na której jest gracz.

- oraz funkcja arenaFromId() która pobiera arena z id, przyda się to później przy komendzie /arenajoin

- dodaj ArenaStorage.load(); w onEnable.

public class ArenaStorage {

    @Getter private static Map<String, Arena> ARENAS = new HashMap<>();

    public static void load(){
        Arena arena = new Arena();
        arena.setId("1");
        arena.setName("&6Arena 1");
        arena.setMaxPlayers(10);
        arena.setPlayersToStart(2);
        Location l1 = new Location(Bukkit.getWorld("world"), 0, 5, 0);
        Location l2 = new Location(Bukkit.getWorld("world"), 50, 5, 0);
        Location l3 = new Location(Bukkit.getWorld("world"), 50, 5, 50);
        arena.getLocations().put(Status.WAIT, l1);
        arena.getLocations().put(Status.COUNT, l1);
        arena.getLocations().put(Status.PRE_GAME1, l2);
        arena.getLocations().put(Status.PRE_GAME2, l3);
        arena.getLocations().put(Status.END, Bukkit.getWorld("world").getSpawnLocation());

        getARENAS().put(arena.getId(), arena);
    }

    public static Arena arenaFromPlayer(Player player){
        for(Arena arena : getARENAS().values()){
            if(arena.getPlayers().contains(player.getUniqueId())){
                return arena;
            }
        }
        return null;
    }

    public static Arena arenaFromId(String id){
        if(getARENAS().containsKey(id)){
            return getARENAS().get(id);
        }
        return null;
    }
}

 

Krok 5.

- stwórz interfejs ArenaWork

public interface ArenaWork {

    void arena(Arena arena);
}

- stwórz klasę ArenaWorkManager w której będziemy przechowywać klasy wykonujące kod do danego etapu gry.

- dodaj ArenaWorkManager.load(); w onEnable.

    @Getter private static Map<Status, ArenaWork> WORKS = new HashMap<>();

    public static void load(){
        //register(status, klasa());
    }

    private static void register(Status status, ArenaWork arenaWork){
        getWORKS().put(status, arenaWork);
    }

Krok 6.

- stworzenie taska który będzie wykonywał kod poszczególnych workerów w zależności od statusu areny.

jak widać task sprawdza czy ArenaWork istnieje dla areny, jeśli istnieje wykonuje metode .arena(arena) z naszego workera.

public class ArenaTask extends BukkitRunnable {
    @Override
    public void run() {
        for(Arena arena : ArenaStorage.getARENAS().values()){
            Status status = arena.getStatus();
            ArenaWork work = ArenaWorkManager.getWORKS().get(status);
            if(work == null) continue;
            work.arena(arena);
        }
    }
}

Krok 7.

- tutaj dam tylko kilka workerów, reszte znajdziecie na hostuje.

- pierwszy worker który będzie sprawdzał czy na arenie jest wymagana liczba graczy do startu, jesli tak to zmieni status areny na COUNT - odliczanie do startu.

public class ArenaWaitWork implements ArenaWork {
    @Override
    public void arena(Arena arena) {
        if(arena.getPs().size() >= arena.getPlayersToStart()){
            arena.setStatus(Status.COUNT);
            arena.setTime(10);
            arena.sendMessage("&6Arena wystartuje za: &6"+arena.getTime()+" sekund");
            return;
        }
    }
}

- następnym workerem będzie odliczanie do startu.
 

public class ArenaCountWork implements ArenaWork {
    @Override
    public void arena(Arena arena) {
        if(arena.getPs().size() < arena.getPlayersToStart()){
            arena.sendMessage("&cOdliczanie do startu zostaje zatrzymane (Zbyt mała liczba graczy)!");
            arena.setStatus(Status.WAIT);
            return;
        }
        arena.setTime(arena.getTime() - 1);
        if(arena.getTime() == 0){
            arena.sendMessage("&aArena wystartowała!");
            arena.setStatus(Status.PRE_GAME1);
            arena.setTime(10);
            for(Player player : arena.getPs()){
                player.teleport(arena.getLocations().get(Status.PRE_GAME1));
            }
            return;
        }
        int time = arena.getTime();
        if(time == 10 || time <=3){
            arena.sendMessage("&cArena wystartuje za: &6" + time + "sekund");
        }
    }
}

- ostatni worker będzie resetował arene.

public class ArenaEndWork implements ArenaWork {
    @Override
    public void arena(Arena arena) {
        if(arena.getTime() == 5){
            arena.getPlayers().clear();
            arena.getPoints().clear();
        }
        arena.setTime(arena.getTime() - 1);
        if(arena.getTime() == 0){
            arena.setStatus(Status.WAIT);
            arena.setTime(10);
        }

    }
}

Krok 8.

- rejestracja workerów w ArenaWorkManager, tutaj przygotowałem już metode register() która zarejestruje nam te workery.

 

    public static void load(){
        register(Status.WAIT, new ArenaWaitWork());
        register(Status.COUNT, new ArenaCountWork());
        register(Status.END, new ArenaEndWork());
        register(Status.PRE_GAME1, new ArenaPreGameFirstWork());
        register(Status.GAME1, new ArenaGameFirstWork());
        register(Status.END_GAME1, new ArenaEndGameFirstWork());
        register(Status.PRE_GAME2, new ArenaPreGameSecondWork());
        register(Status.GAME2, new ArenaGameSecondWork());
        register(Status.END_GAME2, new ArenaEndGameSecondWork());
    }

Krok 9. 

- listenery.

- do pierwszego etapu gry:

public class PlayerCraftListener implements Listener {

    @EventHandler
    public void onCraft(CraftItemEvent event){
        Player player = (Player) event.getWhoClicked();
        Arena arena = ArenaStorage.arenaFromPlayer(player);
        if(arena == null){
            event.setCancelled(true);
            return;
        }
        if(arena.getStatus() != Status.GAME1){
            event.setCancelled(true);
            return;
        }
        if(arena.getPoints().get(player.getUniqueId()) >= 5){
            event.setCancelled(true);
            return;
        }
        if(event.getRecipe().getResult() != null) {
            arena.getPoints().put(player.getUniqueId(), (arena.getPoints().get(player.getUniqueId()) + 1));
            Utils.sendMessage(player, "&cCraftowanie: &7"+arena.getPoints().get(player.getUniqueId())+"/5");
            if(arena.getPoints().get(player.getUniqueId()) >= 5){
                Utils.sendMessage(player, "&cZadanie ukonczone!");
                return;
            }
        }
    }
}

- do drugiego etapu gry:

public class PlayerDeathListener implements Listener {

    @EventHandler
    public void onDeath(EntityDamageByEntityEvent event){
        if(event.getEntity() instanceof Player && event.getDamager() instanceof Player){
            Player damager = (Player) event.getDamager();
            Arena arena = ArenaStorage.arenaFromPlayer(damager);
            if(arena == null){
                event.setCancelled(true);
                return;
            }
            if(arena.getStatus() != Status.GAME2){
                event.setCancelled(true);
                return;
            }
            Player entity = (Player) event.getEntity();
            double finalDamage = event.getFinalDamage();
            if(finalDamage >= entity.getHealth()){
                entity.getInventory().clear();
                entity.getInventory().setArmorContents(null);
                event.setCancelled(true);
                entity.setHealth(20);
                Utils.sendMessage(entity, "&6Zostales wyeliminowany!");
                arena.getPlayers().remove(entity.getUniqueId());
                arena.sendMessage("&6Gracz: &7"+entity.getName()+" &6został wyeliminowany!");
                entity.teleport(Bukkit.getWorld("world").getSpawnLocation());
            }
        }
    }
}

Krok 10.

- komenda którą bedziemy dołączać do areny.

public class ArenaJoinCmd implements CommandExecutor {
    @Override
    public boolean onCommand(CommandSender sender, Command command, String s, String[] args) {
        Player player = (Player) sender;
        if(args.length == 0){
            return Utils.sendMessage(player, "&cPodaj id areny!");
        }
        if(ArenaStorage.arenaFromPlayer(player) != null){
            return Utils.sendMessage(player, "&cJestes juz czlonkiem areny!");
        }
        Arena arena = ArenaStorage.arenaFromId(args[0]);
        if(arena == null){
            return Utils.sendMessage(player, "&cNie ma areny o takim id!");
        }
        if(arena.getStatus() == Status.WAIT){
            arena.getPlayers().add(player.getUniqueId());
            player.teleport(arena.getLocations().get(arena.getStatus()));
            return false;
        }
        if(arena.getStatus() == Status.COUNT && arena.getPs().size() < arena.getMaxPlayers()){
            arena.getPlayers().add(player.getUniqueId());
            player.teleport(arena.getLocations().get(arena.getStatus()));
            return false;
        }
        return Utils.sendMessage(player, "&cArena juz wystartowala!");
    }
}

 

Odnośnik do komentarza
https://skript.pl/temat/50953-szkielet-pluginu-na-arenyminigry/
Udostępnij na innych stronach

Dołącz do dyskusji

Możesz dodać zawartość już teraz a zarejestrować się później. Jeśli posiadasz już konto, zaloguj się aby dodać zawartość za jego pomocą.

Nieaktywny
Dodaj odpowiedź do tematu...

×   Wklejono zawartość z formatowaniem.   Usuń formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Odnośnik został automatycznie osadzony.   Przywróć wyświetlanie jako odnośnik

×   Przywrócono poprzednią zawartość.   Wyczyść edytor

×   Nie możesz bezpośrednio wkleić grafiki. Dodaj lub załącz grafiki z adresu URL.

  • Ostatnio przeglądający   0 użytkowników

    • Brak zarejestrowanych użytkowników przeglądających tę stronę.
×
×
  • Dodaj nową pozycję...