Setup
Features
- 🖥️ Commands
- ✅ Sync Features
- ⚙️ Sync Modes
- ↪️ Data Rotation
- ❓ FAQs
Guides
- ↗️ Legacy Migration
- ✨ MPDB Migration
- ☂️ Dumping UserData
- 🟩 Plan Hook
- 📋 Event Priorities
- ⚔️ Keep Inventory
- 🎏 Translations
HuskSync allows you to save and synchronize custom data through the existing versatile DataSnapshot format. This page assumes you've read the API introduction and are familiar with the aforementioned Data Snapshot API. This page discusses API implementations that target the Bukkit platform.
To do this, you create and register an implementation of a platform Data
class (e.g., BukkitData
) and a corresponding Serializer
class (e.g., BukkitSerializer
). You can then apply your custom data type to a user using the OnlineUser#setData(Identifier, Data)
method.
Note:Before you begin, consider if this is what you'd like to do. For simpler/smaller data sync tasks you may wish to consider using the PersistentDataContainer API format instead, which is a bit more portable if you decide to exit the HuskSync ecosystem.
If you'd like to have a look at an example of a data extension for HuskSync that provides serializers for Pixelmon data when running the plugin on Arclight, check out PokeSync by GsTio86!
Data
interface that you must implement that will represent your custom data.extends
BukkitData
. This class has method to implement: #apply(BukkitUser, BukkitHuskSync)
, which will be called when the data needs to be applied to the player.BukkitUser
class to get the Player
object of the user. Avoid using the BukkitHuskSync
class as this is for accessing plugin internals.// An example of a BukkitData class that you could use in a cosmetic plugin to store player particle data.
public class LoginParticleData extends BukkitData {
private String particleId;
private int numberOfParticles;
public LoginParticleData(String particleId, int numberOfParticles) {
this.particleId = particleId;
this.numberOfParticles = numberOfParticles;
}
// This method is called whenever a user has their data applied.
// If you just want to use HuskSync to sync data used elsewhere, you don't have to do anything here, of course
@Override
public void apply(BukkitUser user, BukkitHuskSync plugin) {
final Player player = user.getPlayer();
// Let's use the Bukkit API to spawn some particles when a user's data is applied (e.g. when they login).
player.spawnParticle(Particle.valueOf(particleId), player.getLocation(), numberOfParticles);
}
}
Adaptable
marker interface to make it easier to Serialize and Deserialize your data using Gson (needed in the next step).Adaptable
. This requires a zero-arg constructor. Note that you cannot serialize proprietary data types or final
fields using Adaptable
.// We've implemented Adaptable here to make it easier to serialize and deserialize our data using Gson.
public class LoginParticleData extends BukkitData implements Adaptable {
private String particleId;
private int numberOfParticles;
public LoginParticleData(String particleId, int numberOfParticles) {
this.particleId = particleId;
this.numberOfParticles = numberOfParticles;
}
@SuppressWarnings("unused") // Suppress compiler warnings
private LoginParticleData() {
// This is required for the Adaptable interface so that Gson can intantiate the class when deserializing.
}
@Override
public void apply(BukkitUser user, BukkitHuskSync plugin) {
user.getPlayer().spawnParticle(Particle.valueOf(particleId), player.getLocation(), numberOfParticles);
}
}
Data
, you'll need to provide a Serializer
class that will be used to serialize and deserialize your Data
to and from a java String
that can later be converted to a byte array and compressed/stored by HuskSync.
public class LoginParticleSerializer extends BukkitSerializer implements Serializer<LoginParticleData>
to serialize the previous example.Serializer
interface, which has two methods: #serialize(T)
and #deserialize(String)
.Adaptable
as per above HuskSync also provides a BukkitSerializer.Json<T extends Adaptable>
class which you can extend to create a simple serializer using Gson.
// An example of a BukkitSerializer class that you could use in a cosmetic plugin to store player particle data.
public class LoginParticleSerializer extends BukkitSerializer.Json<LoginParticleData> implements Serializer<LoginParticleData> {
// We need to create a constructor that takes our instance of the API
public LoginParticleSerializer(@NotNull HuskSyncAPI api) {
super(api, LoginParticleData.class); // We pass the class type here so that Gson knows what class we're serializing
}
}
Data
and Serializer
classes, we need to register them with HuskSync.Identifier
with HuskSync. This is a unique identifier key for your data type.
Identifer#from(String, String)
or Identifier#from(Key)
to create an identifier from a namespace-value pair or an adventure Key
object.// Create an identifier for our data (you may wish to store this somewhere where it can be accessed statically)
public static Identifier LOGIN_PARTICLES_ID = Identifier.from("myplugin", "login_particles");
// (...)
// Register our serializer
huskSyncAPI.registerSerializer(LOGIN_PARTICLES_ID, new LoginParticleSerializer(HuskSyncAPI.getInstance()));
Dependency
objects when creating an Identifier
. These are used to deterministically apply data in a specific order.Identifer#from(String, String, Set<Dependency>)
or Identifier#from(Key, Set<Dependency>)
to create an identifier with dependenciesDependency.optional(Identifier)
or Dependency.required(Identifier)
for optional or required dependencies respectively.Data
and Serializer
classes, we can set our data to a user, applying it to them.OnlineUser#setData(Identifier, Data)
method.
// Create an identifier for our data requiring the user's location to have been set first
public static Identifier LOGIN_PARTICLES_ID = Identifier.from("myplugin", "login_particles", Set.of(Dependency.optional(Key.key("husksync", "location"))));
// We can then register this as we did previously (...)
// Create an instance of our data
LoginParticleData loginParticleData = new LoginParticleData("FIREWORKS_SPARK", 10);
// Set the data to a player
huskSyncAPI.getUser(player).setData(LOGIN_PARTICLES_ID, loginParticleData);
// Get our data from a player
LoginParticleData loginParticleData = (LoginParticleData) huskSyncAPI.getUser(player).getData(LOGIN_PARTICLES_ID);
Add an EventListener to the DataSaveEvent
and use the #editData
consumer method to apply custom data during standard DataSaves. This will persist data to users any time the data save routine executes (on user logout, server shutdown, world save, etc.)
@EventHandler
public void onDataSave(BukkitDataSaveEvent event) {
event.editData((unpacked) -> unpacked.setData(LOGIN_PARTICLES_ID, new LoginParticleData("FIREWORKS_SPARK", 10)));
}