Big news! The Core now uses Spigot's mappings to map methods of versions 1.18 and higher. This means that unless a method/constructor changes parameters or its logic an update to the Core shouldn't be necessary to keep it functioning with the new version. This requires an internet connection as they are pulled from a website, a way to feed the mappings as a file will be added in the future.
The ProGuard Mappings parser will be made open-source Soon™.
The
Wiki is also coming Soon™.
If you notice any bugs, hiccups or anything out of place feel free to PM me or to report it in the Discussion page.
Now the boring changelog:
Added a way to force game mode (on-join and on-reload, possibly not allowing gamemode change without permission in the future).
Now registers inventories as listeners when opened using InventoryManager#openInventory() and unregisters them as needed if they implement the Core Inventory class.
+ CPacketPlayInUseEntity
+ PlayerInfoAction enum
+ CPacketPlayOutEntity
+ CPacketPlayOutEntityHeadRotation
+ CPacket#addPacket() - this method lets you add your own CPacket that will overwrite any existing CPacket with this name. Your class' name MUST follow this format: one character and the packet name (e.g.: APacketPlayOutKeepAlive, BPacketPlayOutKeepAlive)
* Made #sendPacketToAll(CPacket packet, Object[]) public
+ CoreItemStack #addHideFlag(ItemFlag... itemFlags) - adds `ItemFlag`s to a CoreItemStack
+ CoreItemStack #fillArray(ItemStack[] array, boolean unique) - fills an ItemStack array with this item. If `unique` is on a `random` NBT will be set to a random string, making each item unique. This can be used to prevent picking all the items at once by double-clicking.
+ CoreItemStack #setLoreColoured(List<String> lore) - sets the item's lore with color formatting
+ ItemMeta #getItemMeta()
+ CoreItemStack #setItemMeta(ItemMeta meta)
+ `ArmorStandSerialization` class which allows for ArmorStands serialization and de-serialization
+ `DeserializedArmorStand` class, which is returned by `ArmorStandSerialization#deserialize(String, World, Location, FacingType)`
+ Entity Entities#getEntityByUuid(World, UUID)
* Now rain and thunderstorm is only going to be prevented if turned on within the EventManager (off by default)
Bug fixes (high priority):
Fixed a bug that has been introduced in a previous version (1.3.5) making it so some versions would be incorrectly detected as higher than some others (e.g. version "1.12.2" being detected as higher than "1.17") - this could prevent the plugin from working on such versions (complaining about the MinecraftKey class not existing of something of the likes)
—————————————— Developer API additions
PluginHandler:
+ Added database into PluginHandler
CoreItemStack
+ Added Javadoc for #setMirror(boolean)
+ Added #isMirror()
Inventory
+ Added #fillInventory(Material)
ParticleData:
+ Added "data"/extra to ParticleData
+ Made it so data isn't final anymore and can be changed
BodyPart:
+ Added #setPose(ArmorStand, double, double) to use raw yaw and pitch instead of EulerAngle
ArmorStandUtils:
+ Added #disableEquipmentInteraction(ArmorStand, boolean), this method sets an NBT into an ArmorStand's helmet
+ Added #isEquipmentInteractionDisabled(ArmorStand) that checks an armorstand's helmet for the NBT tag.
PlayerListener:
+ Added a listener to prevent players from interacting with an armorstand's equipment if ArmorStandUtils#isEquipmentInteractionDisabled(ArmorStand) returns true.
LocationUtils:
+ Added a way to get the default world for a specific environment (NORMAL, NETHER and END) with LocationUtils#getDefaultWorldByEnvironment(Environment), LocationUtils#getDefaultWorld(), LocationUtils#getDefaultNetherWorld() and LocationUtils#getDefaultEndWorld().
Fixed a bug with hex colours
Changed the CPacketEvents once again, they can now be fired both sync and async depending on the circumstances.
Added some more CMaterials
Added a toggle for CoreItemStacks to mirror the item rather than copying it to a new one
More bugfixes
Fixed version check (used to know if a Minecraft version is higher or lower than another one, say checking if the current version is higher than or equal to 1.13), this also fixes the update checker not properly detecting updates on SpigotMC
CPacketEvents are now async events, they are now fired from the actual Netty thread of the packet's context, this fixes some possible bugs (like items being invisible when dropped on certain versions).
This may break some plugins using this Core, if that's the case contact their author linking to this update notes, you will know this is the cause as the console error may talk about "asynchronous events" or "CPacket"s. If I'm the author of said plugin just message me and I will fix it.
Added a couple of CMaterials
Made it so if a CMaterial cannot be found from its name it will check normal Materials (fixes possible exception with materials from config)
Added some SkullMeta wrappers to get and set the owner
Fixed a bug introduced in 1.3.1 that would cause the player's language to be null (causing null pointer exceptions when trying to send a message to any player)
Added 1.19 support!
Added MongoDB database type (in beta). For more information about this database type and its configuration visit the
documentation page Added support for RGB colors in configuration files (e.g.: ""eb6eLime text") and gradients (e.g. "<#34aeeb>Text with gradient<#9f34eb>")
Fixed some rare networking issues (players would be kicked out on join for no apparent reason and no stacktrace in the console)
Added CMaterial class for cross compatibility with old material/damage materials (e.g. green wool)
Added some sounds to SoundData
Now shading MongoDB's driver again (updated version)
CoreItemStack, added a way to serialize and deserialize itemstacks
Added an update check on start-up
Added some CPackets
Renamed "Players2" -> "Players"
Renamed "Titles2" -> "Titles"
Updated the shaded Java-BetterReflection
Fixed some bugs
Added some SoundMappings
Removed/modified some legacy code
Does not shade javax.mail, any Apache Commons library and mongo-java-driver anymore
Some more breaking changes
Fixed some mappings, calling CPacketEvents synchronously and created "SoundMappings", which can link 1.8, 1.9 and 1.13+ sounds together, making it easy to load a sound from configuration files or use a specific sound without having to worry about what the sound name actually is for the version you're working on.
* Modified the constructor to: #WebServer(int port, File webRoot, String fileNotFound, String methodNotSupported, boolean verbose, boolean debugging).
+ When the url does NOT end with a slash, it now checks if it's a file or a folder, if it's a folder then it treates it a s a folder and searches for the index file.
+ Fixed the Verbose messages on-website not working if there is no #onError(WebServerInfo webServerInfo) method in the WebServer class.
+ Added the comments. If the line (trimmed) starts with "//" the line is going to be ignored
* Fixed ArrayIndexOutOfBounds if there are too many arguments.
+ Added #include(String fileName) and #required(String fileName) - they work with HTML files, UC files etc. The #include(String fileName) method will try to include the file (so copy all the text of the file, and if it is an UC file parse it), and in case of file not found or any other error it's going to verbose (if enabled) and continue. The #required(String fileName) instead, if the file is not found, is going to verbose and die.
+ Added trim to the UC tags (this means you can now put spaces before the opening and closing tags).
+ Added variables!
+ Added PlaceHolders!
+ Added #redirect(String location, int time), which is going to redirect to a specific URL or file, after #time seconds.
The variable can be used almost everywhere in the UC code, and to call it you must write: G_name (where "name" is the name of the variable) in case the variable is global (which means can be called in the whole project after being declared), or V_name (where "name" is the name of the variable) in case the variable is not global (keep in mind that if it is not global you can NOT call it from other UC files).
}
Placeholders {
PlaceHolders are default "variables" you can use in your code. Since you can not use methods inside of other methods (yet), they have been added and will be replaced with their value.
To call a placeholder this is the syntax: "{placeholder}". A list of the placeholders follows.
coreVersion - returns the version of the Core in use.
fileName - returns the name of the file.
requestedFileName - returns the name of the requested file.
clientAddress - returns the address of the client.
clientPort - returns the port of the client.
localAddress - returns the local address.
localPort - returns the local port.
onlinePlayers - returns the number of the online players.
maxPlayers - returns the number of the max players that can join the server.
serverName - returns the name of the server (the one set in the server.properties).
motd - returns the motd of the server (the one in the server.properties).
serverVersion - returns the Minecraft version of the server.
bukkitVersion - returns the version of Bukkit the server is running.
serverAddress - returns the address of the server (the one in the server.properties).
serverPort - returns the port the server is running on.
}
}
The ConfigsManager class has been renamed to ConfigManager.
The UltraCode has been totally rewritten, and a Tokenizer has been added.
The syntax has also been changed. Now, all the parameters in a method MUST be inside of double quotes.
A known issue is that you can't write more than one method PER LINE. And that the uc open and close tag ("<uc>" and "</uc>") can NOT be in the same line of the method, so no way to make the code
Code (HTML5):
<uc> echo("test");
</uc>
compact, or fit in just one line. For now
Some of the existing methods' structure has been modified. And some new has been implemented. Here following, the list of all the methods!
* plugin.execute(String action, boolean echo); - This actually triggers the method #execute(WebServerAction
webServerAction) inside of the class extending the WebServer. It passes the WebServerAction Object, which contains the #action, and the Socket connection, which is the connection between the client and the HTTP WebServer. Both of them can be get from a getter (#getAction() and #getConnection()).
* api.call(String url, String method, String parameters, boolean echo); - Makes a HTTP Request of the method #method (which can be either "GET" or "POST" to the #url with #parameters as parameters. The type of the #parameters is NOT JSON, instead, a GET-Like syntax is used, so for example: "id=1&user=test". Note there is no question mark? That's not a mistake. Don't add one. The echo is a boolean, which MUST be inside of the quotes anyway, and is whether it should echo the result of the request or not.
+ website.request(String url, boolean echo); - Loads the website #url. The boolean #echo is whether it should print the CONTENT of the webpage.
| getFileName(); - Echoes the name of the file that has been actually loaded.
| getRequestedFileName(); - Echoes the name of the requested file, the one in the navigation bar
+ newLine(); - Echoes a <br>
* getClientAddress(); - Echoes the address of the client
* getClientPort(); - Echoes the connection port of the client
+ getLocalAddress(); - Echoes the local address
+ getLocalPort(); - Echoes the local port, the one the webserver is running on.
+ echo(String string); - Echoes the String #string.
+ = added
- = removed
* = modified
| = same as the older version.
The package name has been changed from it.ultracore.* to shop.ultracore.*
- Removed the String index from the WebServer Class Builder.
A new "programming language" has been added to the WebServer, since PHP is not an option
This "programming language" as now comprehends this "methods":
getVersion(); - returns the version of the plugin
getFileName(); - returns the name of the file that the user is actually on
getRequestedFileName(); - returns the name of the requested file (the one on the navbar), this can be useful in the 404 page for example.
getAddress(); - gets replaced with the address of the user
getPort(); - gets replaced with the port of the user
die(); - stops the loading of the page to this line and gets replaced with null
die(String string); - stops the loading of the page to this line and gets replaced with the String string
api.call(String url, String method, boolean echo, String arguments); - Sends an HTTP Request (the method is the String method, and could be either "GET", or "POST" (ignoreCase)), the boolean echo is whether this should be replaced with the response, or with null (true = response, false = null). The arguments are the parameters and the values, and should be like this: "ID=1&name=test". NOTE: No questionmark (?) at the beginning.
plugin.execute(String action, boolean echo) - calls the method #execute(String action) in the WebServer class (to work, the class must Override "public String execute(String action)". echo: true = this is going to be replaced with the String returned by the method #execute(String action) in the WebServer class; false = this is going to be replaced with null.
The code must be inside of the tags "<uc>" and "</uc>". And the begin and end tags must be on different lines.
Also, the file name must end with ".uc" instead of ".html". The Strings also mustn't be inside of the quotes (""), example:
Code (HTML5):
api.call(http://example.com, POST, false, ID=1
&name=test);
+ Added the #sendRequest(String url, String method, String urlParameters) method, which can throw a IOException. The method is the HTTP method type, and can be "GET" or "POST". The urlParameters is the arguments, and should be like this: "ID=1&name=test". NOTE: No questionmark (?) at the beginning.
The PlayersManager and the EventsManager have been updated. Now you can set custom infos on the player join. (And more things you couldn't do before, because the CorePlayer object didn't get updated).
// Click on the update title for more.
* CorePlayer
#getFallDistance();
#isOnGround(); // Deprecated, references on the Spigot code.
#getGameMode();
#setGameMode(GameMode gameMode);
#getEntityId();
#getVehicle();
#getAllowFlight();
#setAllowFlight(boolean allowFlight);
#getEntity();
#isDead();
#isOnline();
#getHealth();
#isBlocking();
#getBlockUnderPlayer(int i); // Where i is the amount of blocks under the player.
#getBlockUnderPlayer();
#getCustomInfo();
#setHealth(double health); // This was an int before.
* Config Object
* The method #addDefault(String path, Object value, Type type) is now deprecated. It is going to be removed in the next version.
+ Added the method #addDefault(String path, String value)
+ Added the method #addDefault(String path, int value)
+ Added the method #addDefault(String path, boolean value)
+ Added the method #addDefault(String path, float value)
+ Added the method #addDefault(String path, double value)
+ Added the method #addDefault(String path, World value)
+ Added the method #addDefault(String path, Location value)
Attention:Please update your code, since in the next versions the #addDefault() how you know it is not going to be there anymore!
+ Blocks class
+ #isStairs(Block block) - returns whether the Block block is stairs or not
+ #isSlab(Block block) - returns whether the Block block is slab or not
+ #isFence(Block block) - returns whether the Block block is a fence or not
+ #isPlate(Block block) - returns whether the Block block is a plate or not
* CorePlayer
+ #getYaw() - returns the yaw of the player (from it's location)
+ #getPitch() - returns the pitch of the player (from it's location)
+ #getDirection() - returns the Vector direction of the player (from it's location)
+ #getPlayerFacing() - returns the facing direction as enum FacingType.* (where * could be NORTH, SOUTH, EAST, WEST, north, south, east, west).
+ #getBlockBehindPlayer() - returns the block behind of the player
+ #getBlockBehindPlayerGround() - returns the block behind the player under his feet
+ #getBlockInFrontOfPlayer() - returns the block in front of the player
+ #getBlockInFrontOfPlayerGround() - returns the block in front of the player under his feet
* renamed #getBlockUnder() to #getBlockUnderPlayer()
* renamed #getBlockAbove() to #getBlockAbovePlayer()
* CorePlayer Object
+ Added the method #getBlockAbove(), it's gonna return the block above the player
+ Added the method #getBlockUnder(), it's gonna return the block under the player
+ Added the method #playSound(Location location, Sound sound, float volume, float pitch).
I noticed, thanks to the user
yorik100, that I uploaded an old version of the Core, which gave problems with the plugin ChatPing.
This is the actual latest version, and doesn't bring any actual update of the Core.
+ Added the event AsyncPlayerChatEvent (onChatPlayer(AsyncPlayerChatEvent event, CorePlayer player)) to the PlayerEvents class.
* All of the events, besides the onChatPlayer one, have been deprecated. Since the Event and the Player are going to be switched (actual syntax: event(CorePlayer player, Event event), new syntax: event(Event event, CorePlayer player)).
* CorePlayer
+ Added the #setHealth(int health) method. (Sets the player's health to the param health)
+ Added the #heal() method. (Sets the player's health to 20)
* The Core PlayersManager is not static anymore. To access it you should use it.ultracore.core.Main.getPlugin(it.ultracore.core.Main.getClass).whatYouNeed. For example, for the PlayersManager the code would be:
it.ultracore.core.Main.getPlugin(it.ultracore.core.Main.getClass).playersManager;
* MySQL
+ Added get method with String as query parameter, instead of Query. This way you can do more things, but you won't be able to use the statement.set(#) method (for replace the question mark (?) with a value). This is gonna be implemented in the API soon.
IMPORTANT:When you use the get() method, it's gonna open a connection to the MySQL database. Remember to close it as soon as you finish using the Result of the get(). (Not before, else you won't be able to use the ResultSet coming from Result, since the connection is closed.)
+ Added MySQL support
+ Created the MySQL Object
+ Created openConnection method
+ Created closeConnection method
+ Created get method (For now no Javadocs, coming soon. Also, for now you can only use one "WHERE", there is no "AND".)
+ Created Query object.
+ Created ConnectionInfo object (Required to create the MySQL object)
+ Created Result object (is the result that the get method is gonna return)
+ Created Value object (it's the input for the get method, since it doesn't use a query string too yet).
P.S. the get methods doesn't use a direct query string. It requires a Query object (introduced by the API)
MySQL mysql = new MySQL(new ConnectionInfo("host", 3306 /* port */, "database", "username", "password"));
// Also. For now, even if the Value is an Array type, it only supports one. If you put more than one there might be an error. Will be fixed soon.
Result result = mysql.get(new Query("table", new Values[] {"where", "like", Type.TYPE /* of the "like" */}, 1 /* MAX LIMIT */)); // You can use 1, 2 instead of just 1 for the min and max.
Soon the get with a plain String will be implemented
+ Added Website class (must be accessed in a static way).
+ Added getContet(String url) method. This will return the content of a website
+ Added Shortener class (must be accessed in a static way).
+ Added TinyURL shortener. Example: Shortener.tinyURL("
https://google.com") <-- This will return the shortened URL for Google
* PlayerEvents
* The methods are now non-abstract anymore. This means you don't have to Override all the methods, but can Override only the ones you need or want to.
* CorePlayer
+ Almost all the class now has Javadocs.
+ #getPingDifference(Player corePlayer) (BETA, not tested yet.), this gets the ping difference between the player and corePlayer.
+ Per player config
If the setting
per_player_config is set to
true in the config, when a player joins a config file gets generated for him, inside the folder
player in the plugin's directory.
What's inside of it is defined in the config.yml with the following syntax:
Code (Text):
'value_name: value_type, value'
(value_type is the type, for example int. There are placeholders too for the value!)
Code (Text):
'player_name: String, %player_name%'
(More examples are in the config.yml) The player's config gets updated every time the player joins.
+ Place holders for the "value" in the per-player configs
%player_name% -> returns the player name
%player_uuid% -> returns the player uuid
%player_address% -> returns the player address
%player_port% -> returns the player port