patryk96 14 Opublikowano 24 listopada 2021 Udostępnij Opublikowano 24 listopada 2021 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 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!"); } } Cytuj Odnośnik do komentarza https://skript.pl/temat/50953-szkielet-pluginu-na-arenyminigry/ Udostępnij na innych stronach Więcej opcji udostępniania...
Rekomendowane odpowiedzi
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ą.