[INACTIVE][DEV] Persistence v0.76 - Data-Driven Bukkit [677]

Discussion in 'Inactive/Unsupported Plugins' started by NathanWolf, Jan 29, 2011.

  1. Offline


    Persistence - Data-Driven Bukkit

    Persistence is a developer API and framework- NOT a game or admin plugin.

    If you've come here looking for plugin/admin support for Spells, Wand, NetherGate or any other plugin that uses Persistence- please turn around and go back to that thread. Thank you for your cooperation!

    If you're a dev, then check the Persistence wiki for information on using the Persistence framework.

    View changelog on github
    Duccis likes this.
  2. Offline


    Nice first version! Hope to see this grow some more, especially deferencing... that would be sweet. This might also be something that could be integrated into Bukkit, since there -still- is no standard way to save data :'(. Will be keeping my one this one ;).
  3. Offline


    I've definitely offered up this project on the feature request page that talks about this- it basically fits the bill, in terms of the diagram they have for how they'd like to do it. :) We'll see what they think, when it's mature enough to catch someone's eye.

    I am working on object references now- my first test classes are actually very complex, as it turns out- including a tree structure (references to other instances of the same type, so circular dependencies), objects that reference objects in another schema, objects that contain lists of other objects, etc. I think once I get my own plugin operational, the Persistence API will be pretty robust!

    So far, I've got deferred binding of single references working (Check out the new example code, with a persisted object reference!). I'm going to work on lists next, which should be interesting. I've had a lot of issues with Java generics and reflection that have made me have to make some.... sacrifices in the cleanliness of the API (e.g. having to pass in a class type along with a typed list, because I can't get the type information from the list at runtime if it happens to be empty).

    Anyway, glad you're interested- I definitely would appreciate feedback along the way.
    --- merged: Jan 30, 2011 7:44 PM ---
    Check out the console UI- it's really handy!
  4. Offline


    Nice, adds a bit of usability polish. Makes it easier to use even moreAgain.
    This would also tie in greatly with a webserver who can publish json/xml/whatever-information. That'll make it possible to 'query' this database :D.
  5. Offline


    Exactly! I definitely want to offer a web UI, at least as a separate plugin (probably as a separate plugin...)

    The biggest issue there is web permissions- people have a hard enough time setting up dynmap, imagine if it had to be secure!

    I would love to create a pluggable web UI for this system, though. I can imagine clients having their own custom forms- like a user/group/permissions management section, a spells management section, etc.

    I'm also very much considering integrating configuration settings into this system. I'll probably have to support text file import eventually, so people could still edit the "old fashioned" way. For me, a hierarchical data-driven settings management system would be awesome.

    Imagine, ops having in-game control of any plugins' global configuration settings, and plugins being able to offer per-player settings that players could control on their own (control the amount of console output a plugin produces, etc). It could be really great.
    --- merged: Jan 30, 2011 8:51 PM ---
    Currently thinking about the best way to handle objects with more than one id field. I've already got some use cases that would do really well with this- such as a general "MaterialData" class that encapsulates (and persists) a Material and data combination. Other persisted classes could use MaterialData to reference a material, allowing for fun things material name overriding on a global level, etc. (And, also, referential consistency- a material is more than just a number, people! :))

    I'd have MaterialData pre-populate from the Material constants, with "friendly-ized" names like I do in Spells. Then I'd pre-populate all the known variants with reasonable names (e.g. "birch" or "red wool"). Assuming that there isn't a Bukkit system for this available yet.

    Anyway the point is that MaterialData needs a two-key id: (materialId, data). This opens up a whole can of worms, since everything is based on id lookups right now- the object cache is all hashed by id, etc. How do you even ask for an item with two ids? Pass in a string list of id names and another of values?

    It's all very ... messy. I may have to go refresh my memory as to how Hibernate handles this in its API.
  6. Offline


    Oh flames and I have been talking about making a general webserver from the one of Dynmap, so that others can add handlers for that. We settled on some more work for Dynmap before generalizing it (so that we knew what problems we might be facing) and maybe also add WebSocket support.
    About double key problem: Why not just a materialId? The material-object can be retrieved from that. (Maybe I'm not understanding the problem :p)
  7. Offline


    Cool! I'd love to write a plugin for that plugin that exposes Persistence data! :)

    Well, in general I'd like to support multi-key ids, but I guess you could argue that's not good db design.

    As for the specific material problem - the issue is that the same material id can be two different materials, depending on data- such as birch wood versus normal wood, or the different colored wools. It would be nice to encapsulate that in a data type.
  8. Offline


    Aah, right. Yes forgot about wool and such (like I did for Dynmap :p). How about a BlockType(=blockid) and a MaterialType(=blockid with material, which results in a new key/id), to make it resemble Minecraft a bit. (You might have guessed I don't really like multi-key stuff :p)
  9. Offline


    The more I think about it, the more I think that multi-key ids are a bad idea. Backburned at best.

    I can accomplish the Material thing with each material having a list of data-based variants, that's actually much more elegant. I imagine that similar solutions will arise on inspection of other cases where it seems like a multi-key id would be nice. I know, for instance, I want to have each player have a list of wands in Wandmin. A table with a key of (playerId, wandId) would make sense- but instead I'll probably have to encapsulate it in some kind of PlayerWands class or something. Which is probably better design anyway.

    Now, what I really wish is that I could markup the Bukkit Material class to persist it directly. Player class also- I wouldn't need a special User class to persist data if I could just use the core classes. Ah, well, maybe the Bukkit team will take this tech one day :)
    --- merged: Jan 30, 2011 11:14 PM ---
    Great minds... :) I don't like them, either- and I especially don't like how incredibly complex the code would have to get to support them!

    I seem to recall something in my db architecture class about multi-key ids always being a bad thing. It's certainly not normalized.

    So, yeah, one and only one id field per entity for now!

    I plan on adding an "index" markup to the field annotation to automatically create a table index for a field- you can then query for objects using that field as well, making it somewhat less important what the id is.

    Anyway- I've almost got simple (primitive-based) List persistence working. It auto-creates a nicely named sub-table and populates it with values, I'm just working on the load right now. It shouldn't be too difficult to extend that to Lists of other DAOs, I think the code is abstracted well enough to make that pretty clean. (I hope!)

    Once that's working, that's basically it for the super-core functionality. I'll be moving on to implementing basic id-based String storage and Material entities. And, from there, supporting my own plugins as they transition over to using the system.

    I'm excited to transition all of my plugins to have their text entirely data-driven. I feel very strongly about not hard-coding text, and about the importance of supporting internationalization. I hope I can take a big step in that direction.
    --- merged: Jan 31, 2011 1:06 AM ---
    Oh, and object merging- I forgot, that's another big item on my list. Right now, if you reload the cache, it will orphan any references you're maintaining. This is not the behavior I want- I need to reload the table, and then merge the results into the cache.

    The same goes for putting an individual object- right now, it just swaps out the cache reference.

    This all works great for simple examples like I gave above, but if you were to do something like try to keep a reference through a reload, or put an object that you created yourself, but its id collides with an existing object (that you have referenced elsewhere)- then, references get orphaned and things generally stop working.

    So, yeah, that's a big near-term TODO :)
    --- merged: Jan 31, 2011 1:46 AM ---
    Ok, one more deep thought for today...

    Looking at the schema generated under some circumstances, it occurs to me I may want some kind of "contains" or "owns" tag on the Persist annotation for object references.

    I think Hibernate had this.

    Basically, in some cases a class may contain references to another class, but that class is not an independent class. I'm sure there's a better word for it- in C++, we'd just say it's owned instead of referenced, I guess.

    Anyway- in these cases, a cleaner schema could be made. Maybe an example would be good:

    class MaterialData
       int materialId;
       List<MaterialVariant> variants;
    class MaterialVariant
        Material material;
        byte data;
    This is simplified, but you get the idea here. This would be persisted with three tables: Material, MaterialVariant, and MaterialVariants.

    However, knowing that MaterialData owns/contains MaterialVariant in a one-to-many way (I think, in fact, Hibernate uses the OneToMany tag for this behavior...) then we can drop the MaterialVariants table, since it is redundant.

    Anyway, I'd like to be smart about this. Things are getting complicated :)
  10. Offline


    Am I correct that this is similar to something like quickdb?
  11. Offline


    I'm not familiar with it, but I took a quick look at the link, and yes, I think that's the same idea. I've used Hibernate before, and that is sort of what I'm basing this on, though I'm trying to keep it simple.

    It's an object persistence engine, basically- I think that's what you'd call something like quickdb.

    Database use without having to deal directly with the database, or with SQL.
    --- merged: Jan 31, 2011 2:44 AM ---
    Yes, looking closer- quickdb is annotation-based as well, so I think the usage would be very similar.

    Technically, you could just install and use something like quickdb or Hibernate- but I'm trying to make something more tightly integrated with Bukkit, and far more lightweight.
  12. Offline


    Definitely need this - will be watching this project.
  13. Offline


    I'm glad you're interested!

    It's fairly useable right now, but within a week or so I hope to start converting my plugins over to use it- at which point, there will be a lot of real-world use cases and it will probably get really flushed out.

    As it stands, I'm only using it in a "Classes" plugin for testing- however, it's kind of cool that in about 8 lines of code (and a few DAOs...), I was able to make a simple player tracking system. Right now, all "Classes" does it maintain a list of players with some info about them- last login, last disconnect, etc. You can use the persistence console UI to query the data, such as "/persist list classes.player.NathanWolf" - and it will tell you the last time I was around.

    Pretty neat for testing code! :)

    Anyway, I just added support for lists of objects- it's getting pretty robust now.
  14. Offline


    Very interesting, looks easy to save and load objects, definitely something I could use :)
  15. Offline


    That's the idea!

    I got sick of writing the same boilerplate code over and over to save/load objects- it's really the kind of thing a persistence engine should handle in a nice, transparent way.

    If it helps anyone feel better using this, I actually wrote a save system for a published console title (Midway's Psi-Ops, for the hardcore gamer crowd out there....), I've also worked professionally with Java and databases for over five years (over ten for db's, 5-ish for Java), and have spent a lot of time mucking about using Hibernate and digging around in its source code. So, hopefully I'm somewhat qualified to create something like this. :)
    --- merged: Feb 1, 2011 10:21 PM ---
    Getting very close to having contained objects working. I've also implemented autogenerated ids, which can be useful for some things.

    I'll need to circle back afterward and do some refactoring- make sure that edge cases like object-based ids or contained classes with contained classes in them work properly.

    After that- well, I'm at a bit of an impass.

    I've been working on a system to allow console commands (and in-game messages) to be data-driven, but this is in direct conflict with the direction Bukkit seems to be going in, now wanting us to use the YML file for plugin commands.

    Ok, I really hate YAML but I'm also not willing to be so much a rebel that I abandon the Bukkit way of doing things.

    So, instead, I'm considering abandoning the Command interface.

    I'm also considering keeping it, and having persistence automatically register plugins' commands in the data store by parsing the yml, if present. And then, hoping for the ability down the road for Persistence to modify the runtime command structure, keeping it in sync with db edits. (Since, otherwise, this whole exercise is pointless...)

    I'm not sure if it's worth exploring given the resistance, but I've already got a little code written, and Persistence refactored to use it- so I may just keep it and see what I can do.
    --- merged: Feb 2, 2011 12:54 AM ---
    Ok, so 0.17 now has Persistence using the proper way to register and handle commands.

    I'm still going to create a data store to hold commands, it's going to be a tree structure to support commands with sub-commands, such as all the variants of /persist.

    I'm going to use this to generate my own in-game help for any plugins that are using persistence (as well as for persistence itself).

    I'll stay away from /help, since it sounds like that will be reserved for ChatBukkit. I may go with /phelp, leave /persist for the actual commands.

    Anyway, there's not a whole lot else going on in 0.17 - I support autogenerated ints now, but I haven't tested it out yet. I will- I recall there being a use case for one of the basic classes that required it, but it escapes me what at the moment.

    Mostly, what's going on right now is lots of refactoring, I'm about 50% of the way there on supporting contained objects. The SqlStore now supports the concept that each class field may map to one or more database fields, this is the key for contained objects. So, that part's done.

    Now I just need to modify the handlers for lists and references to behave a little differently when they're containing their objects, and I'll be all set.

    After that, it's back to the roadmap. I'm looking forward to getting a little more high-level soon... my brain hurts.
    --- merged: Feb 2, 2011 3:05 AM ---
    Not to keep spam-bumping this thread, but I've not got javadocs, which are nice.
    --- merged: Feb 2, 2011 6:16 PM ---
    Ok, as much as I whined about it, the new Bukkit Command interface is really cool. You can now access Persistence commands from the server console! Meaning you can examine entities, reload data, force a save, etc- without ever even having to log into the game. Pretty sweet.
    --- merged: Feb 4, 2011 3:29 AM ---

    0.20 is a big step forward towards non-SQL data stores. I moved all of the logic having to do with creating and populating instances into PersistenceField and PersistenceClass where it belongs. SqlStore is now very light, only containing the code to piece together SQL commands.

    This is also a big step towards owned objects, something I'm really hoping to finally put a nail in soon so I can move on to actually using Persistence!

    Of note, I may not have mentioned it, but I decided to integrate the Classes functionality directly into Persistence. I wanted to keep that functionality separate, but I thought that integrating the global Commands system directly with the permissions functionality of Classes was too tempting.

    So, what does this mean? Not a whole lot, other than that there will be some functionality built-in to Persistence that you can optionally use. It will manage players, groups and permissions- and eventually offer Permissions import.

    Right now, all it does is track players- which is still sort of neat. You can use:

    /persist list global.player
    to list the ids of all players that have ever been on this server (since installing Persistence, anyway)- whether or not they're online right now.

    You can then use:

    /persist list global.player.NathanWolf
    To find out information about a player (in this case, me). So far, I track last login/logout, first login and whether or not the player is online. Kinda handy.
    --- merged: Feb 4, 2011 5:32 AM ---
    I know I'm just talking to myself here, but... :)

    v0.21 brings plugin meta data to the data store. So, for instance, you can check:

    /persist list global.plugin
    To see all registered plugins. You can interrogate a plugin by id, same as any other entity- I put all of the YML file info in there. There is even a sub-table of pluginAuthors, because Persistence is awesome like that.

    This interface is really in place so I can have a universal data-driven, in-depth (as in, supports sub-commands and command variants) help system for any plugins that take advantage of Persistence.

    And.... finally, I finished implementing contained objects. It was a lot of work, and needs a lot more testing, but hopefully it will be useful for something.

    I'm now moving on to flushing out the framework, and then I'm hoping to move on to implementing my first plugin that makes use of Persistence- NetherPortal!
    --- merged: Feb 4, 2011 6:42 PM ---
    Turns out NetherGate wanted to use some pretty complex data structures, right off the bat. To make life easier, and because I love OO, the basic structure looks like this:
    Nether (id : int, area : BoundingBox)
    BoundingBox (min : Position, max : Position)
    Position (x : int, y : int, z : int)
    This meant adding Persistence support for a couple of new concepts in 0.22:
    • "Pure" contained classes. You can now specify "contained=true" on a PersistClass tag, and that class can then go without an id. You won't be able to get() instances of these classes directly from the cache (since they don't have a unique id to look up by), they are meant to be contained in other persisted objects.
    • "BoundingBox" and "Position" are both global contained objects, built-in to Persistence. You can use them as helper classes that are also persistable if you want to define in-game locations and areas.
    • Tighten up the abstraction to support crazy things like containers of containers of containers.
    The latter was pretty tricky, but it works great now. For instance, the schema generated for the "Nether" object looks like:
    nether : (areaMaxX, areaMaxY, areaMaxZ, areaMinX, areaMinY, areaMinZ)
    You can see how it combined that entire class structure into a single table- since all of the sub-objects are contained, it can do this. The objects are really just an OO-organizational mechanism, from a data perspective it's no different than having the fields all directly in Nether.

    Overall, I'm really happy with the current architecture- it seems to do the right thing in all the cases I've exercised so far.
    --- merged: Feb 5, 2011 12:46 AM ---
    0.23 : Persistence now simplifies handling complex trees of command and sub-commands, including dynamic support of CommandSender types.
  16. Offline


    This looks really interesting, but I worry about ease of access out of game or through the servers normal command line.
  17. Offline


    There is already a basic interface for accessing data via the in-game or server console- some examples are given above for accessing the built-in player data and such, like this:

    /persist list global.player.NathanWolf
    This same interface works for your data, as well, automatically. So, you could do:

    /persist list dynmap.sign.MyCoolSign
    And, if dynmap had Persistence intergration for map sign storage, you'd be able to see that sign's location, message, and any other persisted data.

    I plan on adding a web UI eventually...

    Is that along the lines of what you had in mind, or is there something else? I'm definitely open to suggestions for improvements or features!
  18. Offline


    My issue is that if I am storing configuration data, I need access to it from the same ways I access my config files.. like from the linux command line. I don't always have access to the game client, but a SSH connection works even when I am at work and get a text message about the server.
  19. Offline


    Ah- there is a command-line interface for SQLLite you can use in that case. Just access the data directly! :)

    You can modify data that way as well, just be careful if you start modifying reference fields and that sort of thing.

    It takes a little bit of learning if you're not familiar with SQL, but once you learn it I think you'll be really happy with the power provided over a flat file.

    I also plan on supporting YML file importing eventually, so you could also manage your data "the old fashioned way" by editing text files. I'm hoping I can provide more appealing options- though I think this could be very handy for bulk setting up groups, permissions, that sort of thing.
    --- merged: Feb 5, 2011 3:38 PM ---
    I just realized I glossed over the most important part of this statement- configuration data!

    Persistence is not really meant for configuration data. I plan on implementing a configuration sub-system, at least experimentally- if I like it, I'll use it myself and keep it as an optional sub-system.

    However, Persistence is meant for game state, not configuration data. It's for easily storing complex, object-oriented data structures. If you've just got a handful of flags or configuration values, I'd recommend to keep on keepin' on with however you've been doing it :)

    If, however, you have complex game state you want to store and manage in a data-driven way, Persistence can help you.

    Maybe an example would help! I'm working on NetherGate right now, it'll be the first "official" plugin to really use Persistence.

    It has some configuration data- default values for how to create the nether area, that sort of thing. Right now, these are hard-coded- I have no plans to have Persistence manage them. I may make a properties file or something eventually, I'm not sure.

    However, NetherGate does use Persistence to manage its actual data. So, I've got a "Nether" object, which has:
    • An owner (reference to a PlayerData object)
    • An "internal" (nether) and "external" (earth) BoundingBox
    • A list of Portals for both the nether and the earth
    • A couple other random fields
    PlayerData and BoundingBox are built-in persistence types.

    Portal is another NetherGate type, it has its own bounding box, a reference to its target portal, an owner, etc.

    Persistence will automatically save all this data, and restore it then next time Bukkit runs. It maintains all of the references properly, and handles "containing" the BoundingBoxes inside of their parent objects, since that is a data structure and not a unique entity.

    Is this making more sense, or am I just muddying the waters? :)
    --- merged: Feb 6, 2011 1:22 PM ---
    I've seen some really cool commits fly by recently!

    There is now a BlockVector class, meant for hashing! This is exactly the kind of thing I was trying to do in BlockList and UndoableBlock. I can't make use of it directly (at least, unless Persistence gets integrated at some point)- but I can extend it and markup the getters and setters, which is, I think, exactly what I'm going to do.

    It's really perfect timing, one of my next TODO items is moving the undo block / block list functionality from Spells into Persistence- it's so handy, and making them persistable is the super bomb.

    The other cool commit that's gone by is write support for Configuration! This, I think, means I can now easily make a read/write YML-based store.

    I'm still thinking about this, but I'm thinking now I may just make a configuration file that lets admins assign each schema to a different store type- supporting yml and sqllite at first.

    If I could pull that off seamlessly, I'd be convinced that I'd want to let Persistence handle my config data- since all you have to do is flip a switch to go back and forth from YML to db storage. How cool would that be?
  20. Offline


    Instead of marking the needed getters/fields, maybe it's a nice idea to provide some other way to mark the getters/setters/fields with the necessary information. This way people don't have to use the extended version of the class and can use the Bukkit API like intended combined with using Persistence like intended.
  21. Offline


    Welll... my hope is that Persistence will get accepted as core tech one day, but I guess I shouldn't count on that.

    A way to, at least programmatically, set up a persisted class from a built-in one is a really good idea.

    Ok, I say "a way to", but I really mean "an easier way to" - of course it would be possible, since this is all built-in to Persistence. It's just a matter of how the API should work, in case I or someone else ever wants to use this externally- could be really handy to be able to persist objects from some third-party lib, for instance.
    --- merged: Feb 6, 2011 3:06 PM ---
    Upon further consideration, I'm upgrading the status of this request from "good" to "excellent" :)

    Thinking about, there's basically already a really useable API set up- the Annotations! They're just Classes, like anything else, and you could instantiate one programmatically. All I'd have to do is refactor PersistedClass a little bit, and you could easily create and register your own, based on any class.

    It'd look something like this:

    PersistClass persistInfo = new PersistInfo();
    persistInfo.schema = "global";
    persistInfo.name = "vector";
    persistInfo.contained = true;
    PersistedClass vectorClass = new PersistedClass(BlockVector.class, persistInfo);
    You've not got a new persistable class type- you could then add fields to it like so:
    vectorClass.persistField("x", new Persist());
    It'd look for public getters/setters first (getX(), setX()) and use those- failing that, it'd try to bind directly to the field.

    This is perfect, IMO- it lets you set up a class just like you would with the Annotations. It'd even let you create an entity from an external class as long as it had some kind of id you could use- you could even set it up to autogen that id, if that were appropriate!

    Expect this to be in the next release of Persistence! I'm not even going to open an issue, I'm just going to do it. Hopefully direct BlockVector persistence and my undo system will be in there, as well.

    I also want persisted materials and material variants, with built-in support for global and private material lists. This tech might help with that, too- but since I planned on making a MaterialVariant already, it's not as big a deal. But I guess if someone wants to persist Material directly, they could!
  22. Offline


    I cannot get my object to persist correctly. here is my class
    package com.bukkit.WinSock.ProtectedDoors;
    import java.util.List;
    import com.elmakers.mine.bukkit.plugins.persistence.annotation.*;
    import com.bukkit.WinSock.ProtectedDoors.DoorLocation;
    @PersistClass(name = "DoorObject", schema = "ProtectedDoors")
    public class DoorObject {
    	public void setLocation(DoorLocation loc)
    		this.loc = loc;
    	public DoorLocation getLocation()
    		return loc;
    	public void setUsers(List<String> users)
    		this.users = users;
    	public List<String> getUsers()
    		return users;
    	public void setGroups(List<String> groups)
    		this.groups = groups;
    	public List<String> getGroups()
    		return groups;
    	private DoorLocation loc;
    	private List<String> users;
    	private List<String> groups;
    Its not making the DoorObject correctly and im getting an error like this:
     2011-02-06 11:25:31 [WARNING] Persistence: Error updating table DoorObject: no s
    uch table: DoorObject
    2011-02-06 11:25:31 [INFO] INSERT OR REPLACE INTO "DoorObject" ("locationId") VA
    LUES (?)
    Here is the created structure:
  23. Offline


    A customer! Awesome!

    Looking at that, I think I see the problem- but Persistence should have spit out a more useful error if I'm correct- along the lines of "DoorLocation is not a persistable class" - assuming that you haven't marked up DoorLocation...

    If you have marked up DoorLocation, then you've just explored new territory- I have been meaning to test out using a Class as an Id- it should work, and if it doesn't I can make it work :)

    In the meantime, you can modify DoorObject so that it's id is the same type as the id of DoorLocation, and then keep a separate, non-id reference to DoorLocation.

    This would work in the meantime- and if you name your new id field the same as the id field of DoorLocation, the data (assuming it gets created correctly now) should carry over properly when I fix the bug and you put your code back to using DoorLocation as an id.

    Persistence would then ignore the extra DoorLocation reference if you drop it from your class- and, eventually, Persistence will drop the column altogether, once I have data migration working.

    Make sense?

    Let me know what DoorLocation is about- and thanks for trying this out!

    Either way, I need to at least look into that error message- it's supposed to check to make sure any persisted Class references are also persistable.
  24. Offline


    This is DoorLocation all annotated

    And here is my GitHub:

    package com.bukkit.WinSock.ProtectedDoors;
    import com.elmakers.mine.bukkit.plugins.persistence.annotation.*;
    @PersistClass(name = "DoorLocation", schema = "ProtectedDoors")
    public class DoorLocation {
    	@Persist(id=true, auto=true)
    	public int id;
    	public void setX(int x)
    		this.x = x;
    	public int getX()
    		return x;
    	public void setY(int y)
    		this.y = y;
    	public int getY()
    		return y;
    	public void setZ(int z)
    		this.z = z;
    	public int getZ()
    		return z;
    	private int x;
    	private int y;
    	private int z;
    Found another error in the log:
    2011-02-06 11:24:58 [SEVERE] Peristence: error creating table: near ")": syntax
  25. Offline


    Oh, and are you planning on using Persistence for making a lockable door system? (Kinda what it looks like)

    That would be really cool, if so!

    I do plan on having a built-in user/group/permission system- you may want to look at and and consider using the built-in PlayerData and PlayerGroup persistable classes, that way your plugin would integrate, and save you a lot of time- you won't have to implement management commands or data for all that complexity.

    I plan on integrating or transitioning to the built-in Bukkit permissions system when it's ready- but if you're using Persistence, that would be a seamless transition for you.

    Also, it's worth mentioning that I've got a bunch of good changes in the queue- as soon as I have the changes done to allow for using BlockVector directly, I'm going to publish an update.

    You're always welcome to pull from source if you can't wait! I try to never check in broken code.
  26. Offline


    Awesome, i'm already implementing your command system. And the permissions system would b awesome but everyone is using iPermissions
  27. Offline


    Nice, thanks! I'll pull that in and use it test using a Class as an id :)

    Because... it looks like you've done everything right, and that SQL error looks like mis-constructed PRIMAY KEY statement. So, Persistence is losing its mind trying to figure out an id for your class, basically... I'll get it working ASAP.

    At which point, though- you could actually ditch DoorLocation altogether and use the built-in BlockVector class as an id.

    I'm really making your life simpler here, I promise! :)
    --- merged: Feb 6, 2011 6:33 PM ---
    Cool! I really like the way the command-dispatch system turned out. It feels a little script-y to bind callbacks by name, but I think it works out really well.

    As for Permissions- I will also support that, so again if you use the built-in stuff you'll also automatically support Permissions :)

    It's all just YML file importing, basically, it should be the same thing as supporting the built-in framework when it's ready. (Unless there's an API that provides everything I need, in which case I'll make a custom store for it).

    The code is really close to being ready so support multiple data stores- and now that the built-in Configuration object is read/write, creating a YML store should be easy.

    Then, I just need to write some basic commands to merge data from one table to another (regardless of the schema or store they come from), and I will be able to cover automatic data migration (using a temp backup table) and YML file importing in one fell swoop. Should be sweet.
  28. Offline


    Awesome! I <3 you, no homo :p
  29. Offline


    --- merged: Feb 6, 2011 6:38 PM ---
    FWIW, I am hoping I can get a new release out tonight, but it may or may not happen.

    This is mainly for selfish reasons- I want to release NetherGate, and I need a stable release of Persistence to do it. NetherGate now relies on the core Position and BoundingBox objects.... and I've decided to get rid of Position to use BlockVector directly instead.

    So, now it's all help up on that :)
  30. Offline


    Well i hope your selfish reasons get it out fast :p
    --- merged: Feb 6, 2011 6:50 PM ---
    i'm going to just make the location a string delimited by commas for now so i can test this :p

Share This Page