Portals and fun with architecture

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
Okay - here's one piece of my last bit of creative crude work before switching back into infrastructure mode for a while.

https://github.com/Cervator/Blockmania/ ... a8f21747ce

I've implemented a half-working Portal concept including the spawning of mobs (slimes) without player interaction. Updated the terrain.png to get at a "portal like" block I could add to the Groovy file, probably not really what the real portal block is, but hey, this one looks weird enough ;) Moved some other related stuff around a bit with a new "game" package for core game content.

On game startup I check to see if an actual Portal object exists in the new PortalManager (over time there might be multiple Portals) and if not (which is currently always the case as Portals are not persisted) a new one will be created both in Block and Portal shape (relative to player position). If you manage to save the game and reload you might then manage to get a new Block and keep the old one as the Portal doesn't persist. So there's some strangeness to it.

I was trying to make two distinct spawning setups work, one "wild" type (goal is to spawn mid-far away from a Portal), one "local" type (goal is to only spawn locally if there's an "attracting" element present near the Portal, like a player estate / workshop). Currently that is only manifested by making the wild type spawn above the Portal and the local type below it. This will likely go totally weird in a new world.

Some things that need more thought / feedback

* What's up with the y = 32 on the player spawn location? I was trying to base the portal off the player's spawn location, but that embedded it deep within rock. I later accidentally spawned slimes in the same deep rock, which made them pop to the surface, is that the trick used to get the player in a valid spot? What's a better strategy to place the "default" Portal in a world that makes sense, like overwriting the block immediately below where the player ends up? One tricky bit seems to be finding a good time during load before the game loop begins where you have enough data available to intelligently place the block (with a brand new world there aren't any blocks yet?).

* While the portal block persists the Portal object and their relationship do not. We don't save Blueprints either, so I guess it is time to find a way to persist extra data like this to disk - any thoughts on easy (and efficient) architecture?

* Currently the Portal object stores its position as a Vector3f (is that the right way to do it?), but there might be a disconnect between it and its portal block. Would it be smarter to generate / reload the portal block based off a position stored in the Portal object? I was thinking about making Portal extend Block, but not sure how that architecture would work out and we may end up with a Portal object consisting of multiple blocks anyway.

* Alternatively, should there even be a standard portal block (player shouldn't be able to place one easily if at all) owned by the BlockManager? Are we looking at a block-like alternative, one loaded differently, or something?

* I need to calculate distance from the Portal object when determining where to spawn mobs. What's the best way to do that, and would a circle or a square be better? I'm thinking only two dimensions matter and height can be figured out somehow (tho it needs to account for any valid block position in the height layer, including caves, possibly varying what to spawn based on depth and exposure to sunlight). Reason I'm considering a square is from future thinking - in multiplayer the world might get cut into independent pieces based around a Portal each for efficiency reasons. Think keeping one set of mobs per Portal area, then maybe one global set for creatures that wander outside a Portal area (a player walks into the wilderness, still need to spawn mobs somehow). Transferring mobs between square area Sets rather than circular ones seems "easier" to me?

Portals are very much key to the game concept I have in mind - both for gameplay reasons and architectural reasons behind the scene, such as the multiplayer note above. In theory you could probably even run a multi-node server for larger player bases by dividing the portal areas between the nodes. Portals are also going to be the center of player-made "cities" and serve lots of other functions.

Next up: Workshops! These will piggy-back on the Blueprint concept by being defined as a blueprint in space, enclosing whatever is inside them. So another reason we need to be able to persist Blueprints :)
 

begla

Project Founder and Lead Developer
Contributor
Architecture
Logistics
Like it. So many slimes invading my sweet forest! Shush! Shush! :shock:

What's up with the y = 32 on the player spawn location? I was trying to base the portal off the player's spawn location, but that embedded it deep within rock. I later accidentally spawned slimes in the same deep rock, which made them pop to the surface, is that the trick used to get the player in a valid spot? What's a better strategy to place the "default" Portal in a world that makes sense, like overwriting the block immediately below where the player ends up? One tricky bit seems to be finding a good time during load before the game loop begins where you have enough data available to intelligently place the block (with a brand new world there aren't any blocks yet?)
That is more or less a hack to find a valid spawning point. Finding the actual surface position only using the noise generators etc. can be a bit tricky, since the heightmap and volume based part get both thrown together in the end (and are also influenced by the biomes and...). As you pointed out relying on the chunks on the other hand is not a valid solution either, since they can be generated at any time using separate threads. The "popping" to the surface is more or less a nice side effect of my entity physics code. If you get stuck in something, the entity is moved upwards until the intersection is resolved. I abused this to find a valid spawning point. That is also the reason why players can spawn in caves btw. I'll give this a bit more thought and write a function that pin points the actual spawning position with blocky precision.

While the portal block persists the Portal object and their relationship do not. We don't save Blueprints either, so I guess it is time to find a way to persist extra data like this to disk - any thoughts on easy (and efficient) architecture?
I love the idea of not having to write any extra code for persisting data or objects. But using something like db4o does not seem like a valid solution to me because of its licensing model (I could be wrong though). Maybe there is something light-weight that allows the storage of objects as simple as storage.put(myInstance) without defining the actual code in put?

Currently the Portal object stores its position as a Vector3f (is that the right way to do it?), but there might be a disconnect between it and its portal block. Would it be smarter to generate / reload the portal block based off a position stored in the Portal object? I was thinking about making Portal extend Block, but not sure how that architecture would work out and we may end up with a Portal object consisting of multiple blocks anyway.
I used Vector3f for storing positions myself, but this is not the best way to do it. There is a new class called BlockPosition available, which I initially used for writing the entity collision detection. But it can be used to store positions using integers instead of floating point values. The problem might become the removing of portal blocks if the player moved too far away (so the chunks are no longer available in memory). But the caching system should allow the deletion of blocks in areas outside of the player's reach (load the chunk, remove the block and directly write it back to the disk).

I need to calculate distance from the Portal object when determining where to spawn mobs. What's the best way to do that, and would a circle or a square be better? I'm thinking only two dimensions matter and height can be figured out somehow (tho it needs to account for any valid block position in the height layer, including caves, possibly varying what to spawn based on depth and exposure to sunlight). Reason I'm considering a square is from future thinking - in multiplayer the world might get cut into independent pieces based around a Portal each for efficiency reasons. Think keeping one set of mobs per Portal area, then maybe one global set for creatures that wander outside a Portal area (a player walks into the wilderness, still need to spawn mobs somehow). Transferring mobs between square area Sets rather than circular ones seems "easier" to me?
Can be easily done using the Vector2f class using only the x- and z-coordinates: "(vPosition2 - vPosition1).length()". This returns the Euclidean distance between the two points. Another measurement might be the Manhattan distance (Taxicab geometry :laugh:). But how this works out in practice has to be evaluated.
 

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
Interestingly enough db4o sounds a lot like the Red Dwarf Server (formerly Project Darkstar, formerly Sun Game Server) project I mentioned earlier, because that's exactly what it was meant to do - persist objects over the network with no additional code. And it was started by Sun so I figured they knew what they were doing

What was so neat about it was the simplicity, so I was sad when Oracle bought out Sun and cut support for the project. It seems like they were at a fairly mature level for single-node servers, working on multi-node servers using a concept termed "affinity" to intelligently move data around behind the scenes, again without any custom code.

I could try to explain it here, but I'm rather rusty on the exact terminology and don't want to screw it up. In short the server hosts whatever objects you define as needed, automatically reading from and writing to disk with everything implementing Serializable. Clients connect and simply request Java objects/references, modify them as plain code as if you were running in a single local thread with no external concerns, and the framework takes care of communication, persisting, synchronization, and conflict resolution between clients. Here's a tutorial doc (Open Office): https://sourceforge.net/apps/trac/reddw ... torial.odt

It was about a year ago I really tried getting into it, but back then I didn't have a shiny game to get excited about enough to keep going. I did manage to retrieve most the related code, documents, plans, extra frameworks, and a sample game called Project Snowman - some of that stuff has been a little scattered after the Oracle cut. I could try to pick it back up and present a more coherent description (and get us all the right pieces), or even try to implement it - I've been eager to try that, but imagine it is probably a pretty solid project and so far I've just looked for chunks of time where I can do small stuff :)

The community is still around and does answer questions now and then, but open source development is in hibernation. There seem to be commercial products out there that use the framework.
 
Top