Network
Spent a few weeks clearing out netty completely and replacing the network with ktor, it wasn't really necessary but it gave me the opportunity to clean up the login queue in particular which was a whole mess. I wanted to use ktor as it's more straight foward and the coroutine suspending IO comes with advantages which allow adjacent systems to be simplified too. Login for example no longer needs a request queue to obtain player saves, or a pool of threads to process password hash checks, because each client connection is it's own coroutine they can be processed blocking and simply sync up with the game tick when the account is ready to receive a pid.
Same thing happens with "handshake packets" which traditionally have to be handled with a bunch of state and protocol changing before reaching the logged-in final game protocol; they're now just an if statement.
The whole things a lot cleaner now. I also took the opportunity to rejig the architecture, pushing the boundary between client and player further apart in preparation for bots.
Spawns
While the server is an emulation, I don't want to be caught up with tiny implementation quirks and instead focusing on practical content creation. For example I've added npc and item spawns based on larger areas insetad of specific tiles. So rather than having to record or manually place the spawn points of every npc in lumbridge, I just specify "this area is a chicken pen it should have 10 chickens in" or "this is a cow field put some cows in it" the system will handle the rest, spawning npcs in places they can fit, for now it's random but I might improve it down the road to a distribution of some kind.
Code:
- name: Lumbridge east cow field
area:
x: [ 3253, 3253, 3251, 3251, 3249, 3246, 3244, 3244, 3240, 3240, 3242, 3242, 3240, 3240, 3241, 3256, 3257, 3260, 3261, 3263, 3265, 3265, 3266, 3266, 3265, 3265, 3266, 3266, 3265, 3265, 3264 ]
y: [ 3255, 3272, 3274, 3276, 3278, 3278, 3280, 3281, 3285, 3286, 3288, 3294, 3296, 3297, 3298, 3298, 3299, 3299, 3298, 3298, 3296, 3293, 3292, 3286, 3285, 3276, 3275, 3272, 3271, 3256, 3255 ]
spawns:
- name: cow
weight: 10
limit: 5
- name: cow_brown
weight: 10
limit: 5
- name: cow_light
weight: 10
limit: 5
- name: cow_calf
weight: 5
limit: 4
[Only registered and activated users can see links. Click Here To Register...]
The weight parameter allows manipulation of the likelyhood of what npc re-spawn, and same applies to item spawns too.
Bots
This is where things start to come together, I did a lot of back and forth on the structure of the data for the ai navigation graph but for now I've settled on a simple yml list of steps a bot can take to get from one place to another
Code:
- from: [ 3236, 3205 ]
to: [ 3231, 3203 ]
cost: 5
steps:
- type: "object"
object: 45476
tile: [ 3234, 3203 ]
option: "Open"
- type: "walk"
tile: [ 3231, 3203 ]
[Only registered and activated users can see links. Click Here To Register...]
This tells a bot; if it's in the road outside lumbridge church it can open a door and walk to a tile to get inside bobs brilliant axes shop.
For now I've just mapped out lumbridge castle to bobs axes and from there to the trees north of lumbridge castle and back, the graph will expand as more features and content is added.
Now I've brought it all together into a proof of concept woodcutting bot,
It's given a handful of options:
* Go to shop and "buy" hatchets better than your own (shops not yet implemented so hatchets are floor item spawns for now)
* Drop old hatchets
* Go to trees and chop them down when you have space
* Bank or drop logs if you haven't got a lot of inventory space (which is does depends on personality)
To clarify, these are not pre-programmed sequences of actions, but a list of potential options it evaluates and independently picks the best choice out of.
[Only registered and activated users can see links. Click Here To Register...]
It's pretty basic to begin with, it does make some odd choices of tree to cut due to distance calculations but I'm not too worried about that for now. Writing some actual content for the system did expose some areas for improvements in entity querying but overall I'm happy with how it's turned out.
Moving forward I'll be fleshing out the bot with choosing different types of trees to cut, and multiple areas to cut them before moving onto adding more content and skills, slowly growing the complexity of what the bot is capable of.