[WIP] Minigame Tutorial | Using Arenas as Objects. Custom Arena Names/Ids IN FULL DETAIL!

Discussion in 'Resources' started by Phasesaber, Jun 29, 2014.

Thread Status:
Not open for further replies.
  1. Offline

    Phasesaber

    This is a WIP! I have been typing this up for a while, but haven't finished it. So I thought I'd post it so people can still see parts of it. Anywho, this should be completed in the near future. (Probs this weekend, if I'm not lazy.)

    Hey there p.getName()!
    I have been looking at minigame tutorials for a while, but none have really appealed to me.
    So, I decided to make my own!
    This tutorial goes through creating an Arena to adding Listeners!
    So let's get started!

    First you are going to want to create an Arena class:

    Code:java
    1.  
    2. public class Arena{
    3. }
    4.  


    Then we are going to want to put some objects that out arena will hold.
    These are the most important part of the Arena, as they decide all the attributes of the game!
    For example, I will add a join location and a leave location.
    We want to make these private, because we don't want to access them from another class.
    We also don't want to initialize it, because we will do that later.
    Code:java
    1.  
    2. private Location joinLocation;
    3. private Location leaveLocation;
    4.  


    Another thing we might want to add is in game spawns, such as Red Team & Blue Team spawns
    So, to add that, all we have to do is add the same things above, but with different names!
    Code:java
    1.  
    2. private Location redSpawn;
    3. private Location blueSpawn;
    4.  


    And for any other Locations you want, you can add those.

    Now, for the most important part, the id!
    The id can be anything you want! A char, int, String, boolean(you would only be able to have 2), long, double, or anything else!
    Usually, ids are Strings, but int are also used.
    For this tutorial, I am going to use Strings.
    Code:java
    1.  
    2. private String id;
    3.  


    Next, we are going to make a list of players.
    In the 1.7.9 update, player names were replaced with UUIDs (not really replaced, most methods just got depricated).
    So, we make a list of UUIDs instead of Strings.
    Be sure to initialize this!
    Code:java
    1.  
    2. private List<UUID> players = new ArrayList<UUID>();
    3.  


    If you want a custom scoreboard on the side, you are going to want to do this:
    Code:java
    1.  
    2. private Scoreboard scoreboard;
    3.  


    We also want to add a boolean to see if the Arena is in-game or not.
    Code:java
    1.  
    2. private boolean inGame;
    3.  


    We want to make an List of all the Arenas made, so we can access them quickly.
    You can make this one static too.
    Code:java
    1.  
    2. public static List<Arena> arenaObjects = new ArrayList<Arena>();
    3.  


    Now for the constructor! This is the base part of the Arena!
    Here I have the 4 locations I used, if you have other locations, you will want to change them to those.
    Code:java
    1.  
    2. public Arena(String id, Location joinLocation, Location leaveLocation, Location redSpawn, Location blueSpawn){
    3.  
    4. }
    5.  


    Now, in the constructor, we are going to initialize all our variables.
    (I put the previous constructor code to clear confusion.)
    Code:java
    1.  
    2. public Arena(String id, Location joinLocation, Location leaveLocation, Location redSpawn, Location blueSpawn){
    3. this.id = id;
    4. this.joinLocation = joinLocation;
    5. this.leaveLocation = leaveLocation;
    6. this.redSpawn = redSpawn;
    7. this.blueSpawn = blueSpawn;
    8. this.inGame = false;
    9. this.scoreboard = Bukkit.getScoreboardManager.getNewScoreboard();
    10. //Put this at the bottom. V V V
    11. this.arenaObjects.add(this);
    12. }
    13.  


    Now, we must do the WORST part of this.... Getters & Setters.
    These take 5 seconds with Eclipse though!
    (So all you with IntelegentLetterJ & MavisBeacon better watch out!)
    Things you want to do:
    1. Click the "Source" tab at the top.
    2. Click "Generate Getters and Setters", it's near the bottom.
    3. Select all of the objects you made earlier.
    4. Use the "Insertion point:" tab to make all the methods come after the constructer.
    5. Click "Ok"!

    This is some of the code that SHOULD generate (There will be a lot more):
    Code:java
    1.  
    2. public ArrayList<UUID> getPlayers() {
    3. return players;
    4. }
    5.  
    6. public Scoreboard getScoreboard(){
    7. return scoreboard;
    8. }
    9.  
    10. public Location getJoinLocation() {
    11. return join;
    12. }
    13.  
    14. public void setJoinLocation(Location l) {
    15. join = l;
    16. }
    17.  
    18. public Location getLeaveLocation() {
    19. return leave;
    20. }
    21.  
    22. public void setLeaveLocation(Location l) {
    23. leave = l;
    24. }
    25.  
    26. public boolean isInGame(){
    27. return inGame;
    28. }
    29.  
    30. public void setInGame(boolean b){
    31. inGame = b;
    32. }
    33.  


    Another method you might want to add is a sendMessage method.
    To do this, we must go through all the players in the List.
    Code:java
    1.  
    2. public void sendMessage(String message){
    3. for(UUID u : getPlayers()){
    4. Player p = Bukkit.getPlayer(u);
    5. p.sendMessage(message);
    6. }
    7. }
    8.  


    For the scoreboard, we want to add all the objectives & scores in the constructor.
    So, we will add an Objective called "main_scores", and add two scores called Red Team & Blue Team.
    chasechocolate has a great tutorial on Scoreboards if you need help.
    (Put this after the initialization of the Scoreboard)
    Code:java
    1.  
    2. scoreboard.registerNewObjective("main_scores",dummy);
    3. Objective o = scoreboard.getObjective("main_scores");
    4. //We want to set the scores to 1, then back to 0, because scoreboards are weird. Go blame Mojang.
    5. o.getScore("Red Team").setScore(1);
    6. o.getScore("Blue Team").setScore(1);
    7. o.getScore("Red Team").setScore(0);
    8. o.getScore("Blue Team").setScore(0);
    9.  
    10. o.setDisplaySlot(DisplaySlot.SIDEBAR);
    11.  
    12. o.setDisplayName(ChatColor.RED+""+ChatColor.BOLD+"The Game!");
    13.  


    Now to setup teams!
    We are going to register the two teams, red & blue. If you have more, be sure to add those.
    We will also register a Spectator team, for all the players that aren't in-game.
    Code:java
    1.  
    2. Team red = scoreboard.registerNewTeam("redTeam");
    3. Team blue = scoreboard.registerNewTeam("blueTeam");
    4. Team spectator = scoreboard.registerNewTeam("spectator");
    5.  


    We can add custom prefixes too!
    You can make them words, or just colors. (Only up to 16 characters!)
    Code:java
    1.  
    2. red.setPrefix(ChatColor.RED+"Red"+ChatColor.RESET);
    3. blue.setPrefix(ChatColor.BLUE+"Blue"+ChatColor.RESET);
    4. spectator.setSuffix("is Spectating");
    5.  


    We also want to add some options to the teams.
    Code:java
    1.  
    2. red.setAllowFriendlyFire(false);
    3. blue.setAllowFriendlyFire(false);
    4. spectator.setAllowFriendlyFire(false);
    5. spectator/setCanSeeFriendlyInvisibles(true);
    6.  


    That's it for the scoreboard!

    Now, we are going to make an enum called TeamType.
    Code:java
    1.  
    2. public enum TeamType{
    3. }
    4.  


    And in here we are going to put our 3 teams, red, blue, and spectator.



    ---------------------------------------------------------------------------------------
    Helpful Links:
    xTrollxDudex made an awesome tutorial that shows the basics of the Arena & ArenaManager class
    JPG2000 made a somewhat working tutorial here, some of the stuff is broken though, so you will have to fix it yourself!
    unenergizer has a neat Minigame Framework, so you don't have to code it yourself!
    ShadyPotato made a whole API, just so you don't have to do anything!

    [pig]---Saved for future purposes.---[pig]

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 9, 2016
  2. Offline

    xTrollxDudex

    Phasesaber
    Meh, step by step tutorials are very, very difficult I must say. Difficult to get right without too much text, difficult to write itself.

    Also, very Eclipse directed.

    Otherwise, it seems to be a good start.
     
    Phasesaber and MordorKing78 like this.
  3. Offline

    Not2EXceL

    POJOs and Beans, why are there so many tutorials on them. srsly this is ridiculous
     
  4. Offline

    RawCode

    minigames and "kits" are most popular features...
    and most cases they implemented very very wrong:

    Set of teams shoud be MAP or ENUM to provide scalability in case of different number of teams or different names.
    Magic numbers just like magic literals is bad practice, tutorials shoud atleast follow oracle specs...
    Oracle tells - use collection, return collection and recieve collection.

    In current case, two classes shoud be implemented - class Team that process settings for groups of players - host collection of (Player)
    And class Arena that host collection (Team).

    WOOT???
    care to read javadocs\news\something about how UUIDs works before writting tutorial?
    Minigame shoud store UUIDs in only single case - players permanently bound to some arena and can't leave it or arena persistent.
    In such cases you must provide serialization sample - loading and reading from persistent configuration or database for arenas in case of server reloading.

    For what magical reason getters and setters are here, you implemented no public API interface for them, they absolutely useless.
    If you feature no interface - other developers unlikely to use your class, soo there is absolutely no reason to implement setters or getters - IO fields directly is acceptable here.

    I already explained why UUIDs not applicable for your tutorial.
    In sample code, just Player p : Collection(Player) p.sentmessage() without converting player to uuid just to convert uuid to player on next iteration
    As for players who rejoined - reference regeneration is trivial task that cost no resources.

    Hardcoded literals again, use enum or map and fetch data from it.


    Tutorial maybe usefull for someone who want to learn "bad" style of coding or want to learn how he should not code.
     
    AoH_Ruthless likes this.
  5. Offline

    Phasesaber

    I've seen all the other ones, and this one appeals to me most. The other ones kinda spoonfeed the code, and I want people to learn.
    And I was just showing and easier way than typing out every method for Eclipse.

    I wrote this quite a while ago, and have learned a lot newer methods of doing things. This is just a basic tutorial of course. Again, these are kinda like the other tutorials, but more explained. I might change/make a new one explaining teams a lot better. I should have made the objects.
     
  6. Offline

    Panjab

    "Usually, ids are Strings"

    Sorry, but since when are IDs used as Strings?
     
    AoH_Ruthless likes this.
  7. Offline

    Phasesaber

    Ids for Arenas, in JPG2000's tutorial, he used the as Strings, and in xTrollxDudex's tutorial, he used them as ints. They are the "Arena Name" so to speak. They are used to separate them from other Arenas, helpful when you are going through the whole list.
     
  8. Offline

    RawCode

    Phasesaber
    you wrote your tutorial from other tutorial without any research?

    As for your explanation:
    Code:
    int a = 10 // we define integer field a with default value of 10
    
    it's called "captain obvious was here", this violate generic coding guide - comments should not explain something obvious - this does not help, actually it have reverse effect, you likely to miss something important in wall of text.

    I can code "arena ID" as byte array and state:
    Usually, ids are byte array because i seen this in random youtube video, i don't understand why but i will write it in tutorial.
     
    xTigerRebornx and AoH_Ruthless like this.
  9. Offline

    Phasesaber

    Research isn't needed where there is common sense. If I throw code at someone and say "make a minigame out of it", then I'm not helping them. This tutorial is designed for people that might not know anything about minigames! I'm trying to let people learn instead of saying "here's some code I made last night, use it for a minigame."

    And I'm not sure how arrays would work as ids, primitive data types work best. (Such as Strings (not really, but whatevs) and ints)

    This tutorial probably isn't for you anyway, as you seem to know what you are doing. They call it the "Resources" section for a reason, it is where plugin developers can get help, no matter what the subject. This is just for advanced stuff, it's for everything. Say some guy just started learning Bukkit yesterday, and he comes in here seeing all of you with your 'NMS' and 'Packets', he's going to get scared! I know I would if I did that. So why not have some simple tutorials? Or some that explain what the hell you are typing into your computer!

    Another great example is NMS, there are tons of methods like this:
    Code:java
    1. private int a(int i){
    2. int j = i+Math.sqrt(i•8)
    3. return j;
    4. }


    There is no explanation! Nothing to tell you whatever this method does!

    I could do
    Code:java
    1. int a = 10;

    but no one would no what this does!

    So I can add comments to help someone in the future who might want to use this see what it does!
    Code:java
    1.  
    2. //This is the health of the final boss
    3. int a = 10;
    4.  

    There is no mindless commenting obvious things here, I am telling people what the stuff does! Just because an int might be called 'arenaId', doesn't mean someone is going to know what that is. The whole reason I made this tutorial is because I didn't think the others out there were that helpful, they gave me code, but without going through the steps of making it, I had no idea what any of it did!
    This is why people make Youtube videos on it, I know TheBCBroz has like 80 videos on it. They show you the steps of making it, and how you can implement your own stuff. So sorry if this "isn't advanced enough" for this section.
     
  10. Offline

    AoH_Ruthless

    Phasesaber
    RawCode is right. That is mindless commenting. Instead of calling the integer a, you should call the integer finalBossHealth so then someone reading the code knows what it is without comments. Your code should be blatantly obvious in what it does (unless obfuscation is your strategy), not comments.

    You try to make your own tutorial, but what makes this any better than the other 3+ Arena tutorials I've seen? This is basically reiterating the same exact things. Maybe it is a work in progress, but that is not by any means a really sufficient excuse.

    Had I not known how to make arena minigames, this tutorial offers little help because you don't explain what needs to be explained. You don't tell players why so many parameters has to be passed through the constructor, and frankly I disagree with that practice. You should define locations not in the constructor but after in their own separate tasks. When a player creates an arena via commands (which is the easiest way imo), they won't have 4 locations spooled up to pass through .... a lot harder. The locations should be null in the constructor, and initialized later when they are actually defined. For this you can have a ready flag which is false if any location is null, and true otherwise... Just my two cents.

    Also, what is "this.arenaObjects.add(this)" ??? ?????? ?????
    Storing a list of arenas, in the Arena Class makes zero sense. You should have an ArenaHandler/Manager class to avoid singletons as for minigame arenas, singletons are not a very good idea.

    Lastly, your UUID list is flawed. You should initialize in the constructor (just good practice) and you would probably need two, (one for each team, preferably a third one for all players in general). Also, I would recommend Sets because Lists allow you to get individual indexes, which is kind of useless for arenas (You won't really need which player joined when ...). With Sets, you can ensure there are no duplicate UUIDs.
     
    RawCode and Phasesaber like this.
  11. Offline

    Phasesaber

    AoH_Ruthless I wrote this on a txt file a long time ago, and have learned better methods of doing things. Mostly everything you just posted.

    I also need to study up on Singletons, as I have no idea what those are. I hear those getting passed around a lot, but I never bothered to look them up.

    And for the arenaList, I feel it is nice to store it in a list so you can go through them and easily check for ids/player/whatever. Putting it in the Arena class might not have been the smartest idea. :p

    And for the UUID list, I have been making my Teams objects instead of just Enums, as it allows for more "stuff". In the Team objects, I can have a list of players in each, and have a global list in the Arena class to store them all. That would be good for combat/death, as you could check if both players were in the Arena, then check if they were both on different teams.
    And initializing it in the constructor would be the same, wouldn't it?


    And for the locations, you could easily have the user input a command to start the creation of an arena, then add them to a list (or whatever) and wait for them to run another command to get there current location, then save that and do it all over again. Not the best method, but it works.
     
  12. Offline

    AoH_Ruthless

    Phasesaber
    That is no excuse. You should have taken the time to decently put forth the effort into creating a resource that succinctly completes what you are trying to teach. Frankly I have a hard time believing this due to the way you explain this resource in your OP.

    What you are attempting to teach is a Singleton, and has it's purposes but not really wise for this scenario. Google it as soon as you read this post...

    I am not disagreeing with the use of them, I am disagreeing with the placement.

    I make my teams objects as well. I am suggesting you use a Set instead of a List, but this is not really a defining point and doesn't make much of a difference, but I believe Sets have an advantage in this instance. It's just a better practice to initialize it in the constructor.

    That isn't really a valid argument. "Not the best method" -> If it isn't as good as you can do, you a) shouldn't be making a resource if you can't input the effort, or b) Take the time to make something worthwhile, even if it works.
    Having a user do all that is clunky and rather annoying.
     
    RawCode likes this.
  13. Offline

    The Fancy Whale

    Just a quick suggestion. I would use an enum like GameStage for checking if the game is ingame rather than using a boolean. That's just me however. This also allows for you to have a lobby stage, waiting stage, in game stage, or even a stage where the players are in the arena but can not yet move.
    Tutorial looks pretty good, however you have to keep in mind that there are I think 3 or 4 others out there already.
     
  14. Offline

    AoH_Ruthless

    The Fancy Whale
    I have worked with both options: boolean flags and ArenaStates (enum values). I would prefer boolean values (personally), as boolean flags are easy to turn on and off without much of a hassle, but sometimes enum values it can be hard to make sure the arena is under one state. And what constitutes a state? Is enabled/disabled a state? Is it just disabled a state, and every other state falls under enabled? What about if players are in the lobby, or if the arena is running? Is that two states? or 3 .. if you have a countdown? Too much information to keep track of in my opinion: two flags (enabled-true/false and running-true/false when the arena is running) is much easier for me ... but to each his own.
     
  15. Offline

    Phasesaber

Thread Status:
Not open for further replies.

Share This Page