[Utility] Xern-Utilities

Discussion in 'Resources' started by Jogy34, Feb 9, 2014.

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

    Jogy34

    This is a collection of mostly utility classes that I've developed over the years. Anyone who wants to use any of these feel free to copy any of the classes into your own plugin. I only ask that you leave the '@author' tag at the top of each file.

    I have marked these off into different categories and have given them a 'usefulness' value, a 'complexity' value, and a 'reliance' value all based off of my opinion. For usefulness, 1 means that it probably isn't that useful while 5 means that it can be really useful. Complexity, 1 means that the code isn't very complex and can fairly easily be duplicated while 5 means that it is extremely complex and that it took me a really long time and/or I had to go to other sources for help. Reliance is how much NMS/OBC or other Xern-Utilities classes that the resource needs, 1 means that it just needs bukkit while 5 means it needs a lot of other Xern-Utilities classes or a lot of NMS/OBC.

    Before I actually start explaining everything, the entire repository source can be found here: https://bitbucket.org/Jogy34/xern-utilities/src, I will link each individual class/package as I go as well.



    Handlers
    Handlers are the resources that either handle aspects automatically or wrap objects in simpler ways​

    Config Handler: [LINK]
    The config handler handles the creation of a relatively infinite number of custom config files. All methods in the class are static.

    Usefulness: 4
    Complexity: 2
    Reliance: 1

    To begin using the ConfigHandler you have to call the initialize method in your onEnable() sending in your main class so that it has an instance of your plugin to use your data folder. After that any time you want to use a custom config you simply call the static methods sending in the name/id of your config file. The methods work very similarly to how the normal JavaPlugin config methods work.

    Example Code:
    Code:java
    1.  
    2. //in onEnable()
    3. ConfigHandler.initalize(this);
    4.  
    5. //Later
    6. ConfigHandler.getConfig("MyNewConfig").set("Some.Value", 18);
    7. ConfigHandler.saveConfig("MyNewConfig");
    8.  

    That will create a new config file called 'MyNewConfig.yml' in the plugin folder under my plugin's name that has 'Some.Value' set to 18 in it.


    Door: [LINK]
    The Door class is a wrapper for the current door block state, which for anyone who has ever tried to use it, doesn't work all that well. This works with both wooden and iron doors

    Usefulness: 3
    Complexity: 2
    Reliance: 1

    If you attempt to do some task on this door when it is no longer a door, it will throw an exception.

    You can create these doors any time by sending in the location of a door whether top or bottom it will still work. This handles the door states by keeping track of what all of the bytes that correspond to every open and closed version of the door. The DoorState enum contains all of this. Once you have one of these Door objects you can do a variety of things with it. You can check if it is closed, you can toggle it with and without sounds, you can get the bottom and top halves, you can get the DoorState, you can check to make sure that it is still a door, and you can recycle the objects by setting a new location for the door.

    Example Code:
    Code:java
    1.  
    2. Location loc;
    3. //Set loc to some location that is a door
    4. try
    5. {
    6. Door door = new Door(loc);
    7. if(!door.isClosed())
    8. {
    9. door.toggle(); //Defaults to playing the toggle door sound
    10. }
    11. }
    12. catch(NonExistantDoorException e) //Custom exception just as a safety precaution
    13. {
    14. //The location isn't actually a door
    15. }
    16.  



    Modifiers
    Modifiers are things that modify (typically through reflection) aspects that are typically hard to modify​
    Custom Entity Modifier: [LINK]
    The CustomEntityModifier contains a single static method that will register your custom entity to the server for you.

    Usefulness: 3
    Complexity: 2.5
    Reliance: 2 (NMS and Reflection)

    To use this you first must have made a custom entity and you simply call the static addCustomEntity() method sending in the entity's class, name, and network id. It add the entity to the server without override any spawn eggs.

    Example Code:
    Code:java
    1.  
    2. //In onLoad() (typically)
    3. CustomEntityModifier.addCustomEntity(MyCustomDragon.class, "Bob", 63);
    4.  


    For more information on custom entities check out my thread on creating custom entities.

    Tile Entity Modifier: [LINK]
    The Tile Entity Modifier allows you to modify the aspects of a few tile entities easily.

    Usefulness: 3
    Complexity: 3
    Reliance: 3 (NMS and Reflection)

    The first thing that you can currently do with this is change the name of a chest. To do this you send in the location of a chest and the name you want the chest to have. This name will appear in the chest inventory until it is changed or the chest is destroyed. The second thing is setting the effects a beacon gives off. For this you send in the location of a beacon and then the effect ids for the primary and seconds effects.

    If you send in a location that isn't the proper TileEntity it will force that location to be one.

    Example Code:
    Code:java
    1.  
    2. Location chestLoc = //some location
    3. Location beaconLoc = //some location
    4.  
    5. TileEntityModifier.setChestName(chestLoc, ChatColor.GOLD + "Shiney");
    6. TileEntityModifier.setBeaconEffects(beaconLoc, 21, 22); //Health Boost and Absorption
    7.  



    Enum Modifier: [LINK]
    This is my personal favorite. It allows you to dynamically add enum constants to enums.

    Usefulness: 2
    Complexity: 5.1
    Reliance: 3 (A LOT of reflection with some optional NMS)

    Be very careful if you use this as there is a possibility that you will screw things up if you aren't careful.

    This class allows you to dynamically add enum constants to enums. I personally use this for custom sounds and adding EntityTypes for my custom entities to get around other plugins being able to find them by comparing types. I've added methods to add in custom sounds and entity types in addition to the general enum addition method.

    One thing before I start, the 'enum name' is the identifier of the enum constant. So if you added into an enum with the enum name of 'NEW_ENUM', there would be a new constant called 'NEW_ENUM' if you were to look through the list of constants.

    One other thing, I've found an issue with copying the addToEnum() method into eclipse where it can't find the 'sun.reflect.ReflectionFactory' package. I found that to fix this you just have to get rid of your JRE in your build path, rebuild your project, and then add it in again and rebuild once more. It should be fine after that.

    Adding in sounds is the least complicated to use so I'll start with that. Adding sounds is also the least necessary as you can easily handle it through packets. For the sounds to work the player must be using a resource pack that has a custom sound in the same format as the 'sound' String that you send in. To add in a sound you call the static addSound() method sending in the enum name and the name of the actual sound.

    Example Code:
    Code:java
    1.  
    2. //In one of my plugin's resource packs I have a sound called Doomsday.Doomsday1
    3. //So to make a new sound for that I would do the following
    4. Sound doomsdaySound_1 = EnumModifier.addSound("DOOMSDAY1", "Doomsday.Doomsday1");
    5. //If you were to print out everything in the sound enum you would see my new sound
    6.  
    7. //To use it I would then do something like this
    8. p.playSound(p.getLocation(), doomsdaySound_1 , Integer.MAX_VALUE, 1);
    9.  

    Here's an example of this in use in a radio that I made for one of my plugins.


    Next up is adding custom entity types. For this you call the static addEntityType() method sending in the enum name, the entity name, the entity class, and integer typeId, and a boolean for independence. You'll have to look at the EntityType enum for a better understanding of this but I believe the 'independent' variable dictates if it can be spawned in just by using the enum but I'm not sure about the typeId but it may correspond to the network id however I typically send in -1 for the typeId and false for independent.

    Example Code:
    Code:java
    1.  
    2. //Towards the top of my custom craft entity implementation
    3. public static final EntityType MY_ENTITY_TYPE = EnumMdifier.addEntityType("MY_ENTITY_TYPE", "My Entity Type", MyCustomEntity.class, -1, false);
    4. //If you looked through the EntityType enum you would find my new constant in there
    5.  
    6. //I would then return that in the craft entity implementation in the getType()
    7. //And use that if I wanted to check for my own entity
    8.  

    You can find example usage of that here


    Finally is the general method. This is a more complicated to use as it actually requires knowing the enum class and any additional constructor parameters and types. To use this, you call the static addToEnum() method sending in the enum class, the enum name, then an array of classes corresponding to any additional argument types, and then an array of objects for the extra arguments in the constructor. If you want some example code of this you should look at what addEntityType() does as it does this exact same thing. addSound() also does it but it doesn't take in any extra arguments and also goes through quite a bit to make the enum to the sound.

    My Other Things:
    Meta Mobs
    Custom Entity Tutorial

    Still To Come:
    * Inventory Menus
    * Human NPCs (probably in a different thread)

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

    rcth

    So, with Enum modifier, you can add custom soundeffects without need of a specific resource pack?
     
  3. Offline

    Jogy34

    Sorry I didn't explain that well enough. For the sounds they have to be in a resource pack in the same format as the 'sound' String for it to work.
     
  4. Offline

    xTrollxDudex

    Jogy34
    Is it possible to refer back to the enum entry you added dynamically as if it were explicitly declared?
     
  5. Offline

    Jogy34

    If you're talking about doing something like EnumName.VALUE, I'm not quite sure. Possibly if you were to somehow ensure that you were only calling it like that after you added it (possibly adding it in onLoad() or such) but it would give you an error in your IDE and possibly a compile time error. I'm curious about that so I'll try it and get back to you on it.

    You can, however, access it by either getting all of the values and iterating through them or calling valueOf() on the enum though. I typically just store it as a static constant that I would be able to access from anywhere though.
     
  6. Offline

    xTrollxDudex

    Jogy34
    Excellent, thank you.
     
  7. Offline

    Jogy34

    Well doing EnumName.VALUE does (not-surprisingly) throw a compile time error. Using the valueOf() method works perfectly fine though.
     
  8. Offline

    BungeeTheCookie

    Jogy34
    Cool. Where are those Human NPCS?
     
  9. Offline

    HeroWorkbrine

    I tried to import this into my plugin, but the ReflectionFactory class doesnt exist?
     
  10. Offline

    xTrollxDudex

    It's from the sun.* package. Are you using JDK or JRE?
     
  11. Offline

    RawCode

    This is my personal favorite. It allows you to dynamically add enum constants to enums.
    Complexity: 5.1
    modifiersField.setInt(soundArray, soundArray.getModifiers() & ~Modifier.FINAL);

    1) Are you kidding?
    2) Dont mindlessly copypaste code you dont understand, there is absolutely no reason to mess with modifiers, code NEVER check them.

    Forging instance of enum done by SINGLE invocation, no more no less:

    Code:
    ENUMTEST exex = (ENUMTEST) unsafe.allocateInstance(ENUMTEST.class);
    
    ordinal and "value" map is optional and never used by JVM currently, C# have special "FLAGS" modifier that use ordinal, java is not.
    after that you can pass your "new" enum and use it for anything you want.

    after that you can store new object inside static final field of any class and use it like original one.
     
Thread Status:
Not open for further replies.

Share This Page