I feel that when you add an attribute it should be persistent after a server restart.
After testing this is not currently the case.
I feel that when you add an attribute it should be persistent after a server restart.
After testing this is not currently the case.
Yes. is persistent only during session. If want to make permanent i think must save them into db and restore on player connect. This if is a attribute of a player ...
This is NPC attributes. I don't really want to have to save them manually lol
Edit: I mean, I have to save them manually, why bother with attributes in the first place?
Attributes are indeed only valid during the session. Right now it's more meant to be a convenient way to store temporary per-instance data (and possibly share it between plugins)... in fact it wouldn't be easy to make them persistent - right now it's possible to store any object as attribute (this could be a reference to another class, e.g a UI element, or just a primitive data type), but we could only store primitive data types persistently (no way to store and recover that properly).
We could think about adding a way to store separate, persistent attributes, but that would be limited to serializable data only (e.g. primitive data types, strings, vectors etc). Custom objects could only be stored if they implement the serializable interface (but no way to store API objects, like players, UI elements etc). It would be a separate API then, like setPersistentAttribute(), getPersistentAttribute() etc.
Yes it was only primitive data types I was adding to NPCs as Attributes. If it's easy from your side to implement then please do so.
However, if it's not going to be a quick fix, please don't waste time on it - I'm sure I could write my own NPC handler for this.
I'm going to share a couple of functions I use to save/get data, which also takes in account attributes.
With these you can simply call get/set data, if it exists returns the value and if not it returns 0.
//Call InitDB() when plugin starts, to create a player database
void InitDB() throws SQLException {
db = getSQLiteConnection(getPath() + "/players.db");
String query = "CREATE TABLE IF NOT EXISTS `userdata` " +
"(`id` INTEGER PRIMARY KEY, " +
"`userid` TEXT, " +
"`key` TEXT, " +
"`value` TEXT)";
db.execute(query);}
//Usage: int stepsTaken = Integer.parseInt(getData(player,"stepsTaken"));
String getData(Player player, String key) {
if(player.hasAttribute(key)) return player.getAttribute(key).toString();
String ret = "0";
String userid = player.getUID();
String query = "SELECT `value` FROM `userdata` WHERE `key`='%s' AND `userid`='%s' LIMIT 1".formatted(key,userid);
try(ResultSet res = db.executeQuery(query))
{
while(res.next())
{
ret = res.getString("value");
if(ret == null) ret = "0";
//if(key.equals("level") && ret.equals("0")) ret = "1";
return ret;
}
}
catch (SQLException e)
{
System.out.println(e.getMessage());
}
//if(key.equals("level") && ret.equals("0")) ret = "1";
return ret;
}
//usage: int steps = 200;
//setData(player, "stepsTaken", steps);
void setData(Player player, String key, Object obVal)
{
if(!player.isConnected()) return;
String val = obVal.toString();
if(player.hasAttribute(key))
{
String at = (String)player.getAttribute(key);
if(at.equals(val)) return;
}
player.setAttribute(key,val);
String userid = player.getUID();
String delquery = "DELETE FROM `userdata` WHERE `userid`='%s' AND `key`='%s;'".formatted(userid,key);
if(val.equals("false"))
{
db.execute(delquery);
//player.setAttribute(key,null);
player.deleteAttribute(key);
return;
}
db.execute(delquery);
String query =
"INSERT OR IGNORE INTO `userdata` (`userid`, `key`, `value`) VALUES ('%s','%s','%s');"
.formatted(userid,key,
val);
db.execute(query);
query = "UPDATE `userdata` SET `value`='%s' WHERE `key`='%s' AND `userid`='%s'".formatted(val,key,userid);
db.execute(query);
}
With those set up, you can persist attribute data on the go. You can also modify them for npcs, plants, etc.
Don’t have an account yet? Create a new account now and be part of our community!