Developing an example Protection plugin
#11
Storage revision
While coding the cStorage:AddArea(), I found out that the initial DB structure was not thought out thoroughly. The protection areas will be specific to a world in which they're created, so each area needs to know its world as well. Either we need to store the world name for each area, too, or we need to have a separate DB file for each world.
The first approach is better when we think about the planned ProtRemUserAll command - it will be able to remove the user from all areas in all worlds easily.
The second approach is better when we think of each world as a closed entity, theoretically being able to migrate an entire world to a different server. Another plus points are for DB performance - the DB won't have so many rows, thus the queries will run faster. On the other hand, this approach would require a separate "SQLite DB handle" for each world, making things complicated.

I decided to take the first path now, with a change to the second path being still available later on in the development.
Reply
Thanks given by:
#12
Finishing the commands
The next few commits (rev 1560 - 1568) do a rather monotonous work. Each command is implemented, then the corresponding cStorage function is written to handle the appropriate DB access. There was a lot of trial and error, and many stupid errors popped up during testing each command. What most of it boiled down to was "Use defensive coding!" Since Lua isn't type-safe and not even parameter-matching, it's very easy to call a function with the wrong number or wrong type of arguments. Such an error can lurk silently in the shadow, manifesting itself only two more function calls later. Such bugs are difficult to debug, so it's better to avoid them in advance. That's why it's a good idea to use the assert() function to check the parameters.

With rev 1568, the commands are all done. One more command was identified as potentially useful and implemented: "ProtUsers", to list all allowed users for a particular area. The original idea was to list the users together with the list of areas in "ProtList", but that has proven to produce too much textual data at once, usually the VIP's game console was flooded.

There are several outstanding issues which will need to be addressed later on:
- The player names are treated case-sensitive. This is usually not good for human interface
- All the texts will need to be moved into the CurrentLng.lua file to be able to translate them
- Since I'm not so "fluent" with databases, I don't know whether it's better to do a JOIN in a single query, or to make multiple queries (cStorage:LoadPlayerAreas() calling cStorage:IsAreaAllowed() ) This will probably need to be analysed under some stress-tests

Area reloading
Now that we have the commands to manipulate the areas, we can go implement the fun part: the area reloading optimization. In the current state, the plugin reads the areas once and then uses it for all subsequent queries. But a player may move out of the space for which we queried the areas, so we need to check against that and reload the areas when it happens.

One thing that needs to be avoided is making a fixed grid of these spaces. This means, there must not be a line which would cause the area reload each time a player crossed it. Imagine that we partitioned the spaces in 50x50 block grids. Then anytime a player goes from X=49.99 to X=50.01, the areas will be reloaded. But then, a player might have a road going along X=50, and simply following that road will cause the player to cross the boundary several times (no-one will walk a perfectly straight line - or at least the plugin must not make such an assumption).

To fix this, we implement a "buffer zone" - when we reload a space, we center it on the player's coords. So when we have a space at X = 0 .. 50 , and the player crosses the X = 50 line, say at X = 50, Y = 0, we reload the areas centered around their position: X = 25 .. 75. Then the player crosses the X = 50 line back to X = 49, but no reload happens, because we have a buffer zone till X = 25:
[Image: ProtectionAreasReload.jpg]

One more thing to remember is that the players can reach several blocks away from their current position, so we need to actually load areas a bit further away, just to be sure.
Reply
Thanks given by:
#13
The final touch
Now that the plugin is mostly complete in its core functionality, it's time to add some small details - make all user-visible strings easily translate-able, read through and improve the command help strings, add a license.
Then, it's off to the forums to create the plugin description thread: https://forum.cuberite.org/showthread.php?tid=1155

Rev 1581 concludes this tutorial. Feel free to tell me how you like it, what you want added, what you want removed.
Reply
Thanks given by:




Users browsing this thread: 3 Guest(s)