Implementation Portals

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
Name: Portals
Summary: Core gameplay concept - provides spawning of creatures, estate/village management, travel, etc
Scope: Core Content
Current Goal: Iterate! Lots of little tasks, see below (and feel free to join in)
Phase: Implementation
Curator: Cervator + anybody else interested (open invite)
Related: #276, creature definitions, ...

GUIDE
  • Be sure to actually enable the new mod when creating a new world ("Mod" button)
  • Mod provides the portal block which you can get with /giveBlock "portal" from the console
    • New portals have been added that spawn different gellies. Try the "cyanportal" or "greenportal"
  • Placed portals will start as Spawners that are listed as able to spawn different categories of Gelatinous Cubes
    • In addition to plain GelCubes there are also "Hoppers" (that unsurprisingly are great at jumping) and "DangerCubes" - both these types are rather poisonous and will do bad things to the player if they get too close. Thanks Esereja !
  • An assortment of differently colored GelCube prefabs are included and assigned to different Spawnable categories - any Spawner able to spawn them will do so
  • There's a limit on total mobs that can spawn to keep the game from slowing down. The exact details are in flux but you can likely just keep placing portals forever, to still can grind the game to a halt if you wish!
  • You can activate/deactivate a portal from spawning or not by pressing the activate key ('e') when targeting a portal block (but reactivation currently only creates an empty spawner so nothing spawns - bug). Also: "Bloop".
  • Destroying a portal block also correctly cleans out the Spawner
  • Note: There is a non-existent "creature" in the spawn list just to highlight what happens in that case via logging. Some spawn cycles thus spawn nothing.
TASKS
  • Bundle existing portals and gelcubes into a mod instead of living in main source
  • Allow prefabs to define themselves as Spawnable and/or Spawners (portal prefab as first Spawner)
  • Tidy up logging some more (too much going to info)
  • Fix that re-attached SpawnerComponents are blank - they should grab some data from somewhere
  • Figure out prefab parenting (plain gelatinouscube as parent of the chromatic and metallic gellies) to cut down on clutter in groups of prefabs
  • Sort out the relationship between creature definitions and spawning / portals
  • Enhance Spawners to include range, probabilities / speed of spawning - partially done
  • Do more with the portals themselves, like multi-block options - for instance a plain portal block can only spawn basic gelcubes, add a frame around the portal and it can spawn advanced gelcubes
    • This could lead to more use of blueprints, or the grammar system Skaldarnar prepared so fancy multi-block portals can be randomly generated / placed in the world
    • Can we detect, for instance, a vertical portal frame for making chromatics and a horizontal portal frame for making metallics?
  • Update spawn ticking (may depend on an updated / different flavor SubscriberSystem) - partially done
  • Refactor the factory for GelCubes - may not truly be needed or may be able to support more generic entities instead - partially done
  • Look at doing some color constants for the gellies
  • (advanced) Hook portals into other game concepts (workshops, estates, creature helpers, etc)
  • (advanced) Travel-based options to move between portals
  • (advanced) Region-based options on world portals (relates to notes elsewhere)
Funny thing - the little portal block tied to gelcube spawning might have been the first bit of content beyond the very terrain of the world - yet it pretty much took a year for the concept to get an incubator thread :)

There's a big design behind this one little word, some details scattered in assorted text files, some in old wiki pages, etc, and to not lose myself in administrative work I'm going to poke at this content feature now and then, sharing the design but keeping it optional as a mod rather than make people suffer through annoying indestructible purple cubes cluttering up their constructions ;)

Immortius - after really trying to implement something from scratch with the ES available and the modding setup initially prepared - I am impressed. I had a hell of a time way back in the pre-ES days trying to make portals fancier in this hacked together half-implementation of Artemis I was playing with. This was a piece of cake after getting over the initial understanding. Make a couple components, a prefab, a subscriber system with an update method and an event system to make portal blocks clickable with 'e' and done! It practically worked on the first try (typo'ed some stuff, as expected). Thank you for your great work - I can't wait to see what serious modders can do with that one day :)

I have a few more passes to do before pushing this to our organization repo so I'm tinkering with it in my personal so I can rebase away some gibberish. The commit is here - fully functional, although there is a quirky bug.

So far I've just made it so placing a portal block in the world (get some with getBlock "portal") creates an entity that is both a Portal and a Spawner (and a BlockComponent, since the portal.json block definition links it to a portal.prefab). The portal part allows it to be clickable with 'e' to toggle whether the portal spawns GelCubes or not (by removing/adding the SpawnerComponent to the entity), the spawner part hooks into a subscription system that spawns a GelCube every 5 seconds.

Here's the weirdness - when you place a single portal, you end up with two entities with SpawnerComponents, so the spawning triggers twice. Clicking the portal with 'e' removes one spawner correctly, but the other entity is unaffected. I checked using /dumpEntities and the before/after follows:

Code:
{
  "id": 1725,
  "parentPrefab": "portals:portal"
},
{
  "id": 1724,
  "BlockItem": {
    "placedEntity": 1725,
    "blockFamily": "portals:portal"
  },
  "Item": {
    "icon": "",
    "stackCount": 16,
    "container": 3,
    "name": "Portal",
    "baseDamage": 1,
    "usage": "ON_BLOCK",
    "renderWithIcon": false,
    "consumedOnUse": true,
    "stackId": "block:portals:portal"
  }
},
 
{
  "name": "portals:portal",
  "persisted": true,
  "Portal": {},
  "Spawner": {}
}
After placing a portal:

Code:
{
  "id": 1725,
  "parentPrefab": "portals:portal",
  "Health": {
    "regenRate": 2.0,
    "timeSinceLastDamage": 0.0,
    "currentHealth": 3,
    "maxHealth": 3,
    "waitBeforeRegen": 1.0,
    "fallingDamageSpeedThreshold": 20.0,
    "partialRegen": 0.0,
    "excessSpeedDamageMultiplier": 10.0
  },
  "Block": {
    "position": [
      9,
      171,
      5
    ],
    "temporary": false
  }
},
{
  "id": 1724,
  "BlockItem": {
 
    "blockFamily": "portals:portal"
  },
  "Item": {
    "icon": "",
    "stackCount": 15,
    "container": 3,
    "name": "Portal",
    "baseDamage": 1,
    "usage": "ON_BLOCK",
    "renderWithIcon": false,
    "consumedOnUse": true,
    "stackId": "block:portals:portal"
  }
},
 
{
  "id": 2854,
  "parentPrefab": "portals:portal",
  "Health": {
    "regenRate": 2.0,
    "timeSinceLastDamage": 0.0,
    "currentHealth": 3,
    "maxHealth": 3,
    "waitBeforeRegen": 1.0,
    "fallingDamageSpeedThreshold": 20.0,
    "partialRegen": 0.0,
    "excessSpeedDamageMultiplier": 10.0
  },
  "Location": {
    "position": [
      9.0,
      171.0,
      5.0
    ],
    "scale": 1.0,
    "rotation": [
      0.0,
      0.0,
      0.0,
      1.0
    ]
  },
  "Block": {
    "position": [
      9,
      171,
      5
    ],
    "temporary": false
  }
},
 
{
  "name": "portals:portal",
  "persisted": true,
  "Portal": {},
  "Spawner": {}
},
Before placing a portal there's an entity purely with an ID and the portal prefab as a parent. When placed that entity looks to have a BlockComponent added (which I filter by - must be Spawner + Block to trigger spawning). In addition a brand new entity is created that also has a Location. Not sure what that's all about but I figure only the second is a valid world object with the first some sort of phantom. Any ideas?

Final bonus round question: Can we load sound assets out of mod dirs yet? :geek:
 

Immortius

Lead Software Architect
Contributor
Architecture
GUI
Hmm, I'll have to look into that one. I gather I've forgotten to have an intermediate state between blocks having temporary entities created when interacted with, and blocks having a permanent entity that follows them when held. It defaults to the latter, and I doubt it behaves properly with stacks. Really there should be a setting where blocks have permanent entities but only when placed.

Sounds should work out of the mod dirs.
 

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
Great :)

I did notice that the held stack entity didn't count as a Spawner. Still had two of those if I got rid of the stack.
 

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
Work continues - getting closer to having something solid to push to our main develop branch. I'll have to catch up with the latest first and see if Portals will behave.
 

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
First goal is functionally complete and working now :)

Aiming to rebase and clean up tomorrow, maybe make everything a little more sturdy. But the code achieves extraction of portals and spawning into a mod, with what I hope is decent future potential of making Spawners spawn Spawnables of various types merely by matching category tags :geek:

Happy to hear any initial code review before I make final adjustments. Still rusty, taking forever to code, and unaware of a lot of both new Java tech and new fancy stuff we have available ;)

In short: Portals now spawn four different types of Spawnables, three of which are GelCubes and one is non-existent just for demonstration (so nothing is spawned). Two new flavors of GelCubes come in specific colors while the base GelCube gets a "random" color (which is really just a random pick of a tiny list). Can easily make the portal spawn only a subset of that or new things, although currently the system is tied directly to GelCubes and block-based spawners.
 

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
First round of portal updates have been integrated and built - yay!

Adeon - I changed the PrefabManager method to return a Collection instead of an Iterable (not sure why Iterable in the first place, but it wasn't previously used anywhere). The version that filters by Component is also available for your use :thumbsup:

Immortius - I double checked against your entity persistence tweak - that funny double-spawning bug is all gone, huzzah! It didn't seem to matter if I explicitly set the mode in the prefab, looks like persistent is default, so should we take that off chest + furnace if it is excessive? Not sure if you have other plans :)

Skaldarnar - I included a note above about using your grammar system to generate simple portals that might differ in size and orientation, might be a nice easy test of the system? Could even do multi-story portals, because why not? ;)

Known bug: If you deactivate ('e') a portal then reactivate it a blank SpawnerComponent is attached (by PortalSystem). At first that resulted in a crash due to division by zero trying to get a type to spawn when there are none (since the portal prefab data isn't used). I've applied a check to avoid that, but am not totally sure how to best reactivate a portal from its original prefab definition. It probably is straight forward as long as you can identify the original state, but I just haven't looked at it in depth yet - must go spend time on other stuff for a while :)
 

Adeon

terasology.ru
Contributor
Architecture
GUI
Logistics
@Adeon - I changed the PrefabManager method to return a Collection instead of an Iterable (not sure why Iterable in the first place, but it wasn't previously used anywhere). The version that filters by Component is also available for your use :thumbsup:
Cervator Ok. Thanks! =)
 

Immortius

Lead Software Architect
Contributor
Architecture
GUI
I tend to return Iterable rather than Collection because of encapsulation. Collections allow items to be added and removed directly, which is bad if they need to be added through an method for correct behaviour. Iterables are much safer since they (mostly) just allow observing the contents. If the prefab manager is copying the internal collection into a new collection that it returns that is fine though. But because that can be costly I would tend to leave it to users of the method to copy the iterable into a new collection as they desire:

Code:
List<Prefab> prefabs = Lists.newArrayList(prefabManager.listPrefabs());
Technically iterators still allow items to be removed, although many implementations don't support that feature.

What particular feature of Collection were you after Adeon ?
 

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
Oh okay. I don't mind Iterable, I just didn't know of a reason that was in use and thought it was effectively abandoned code if it was originally t3hk0d3 who did the prefab stuff. We can put it back - Adeon didn't ask for it to be a Collection, I had just created a new method that filtered so I was using a Set at that point anyway and thought I might as well return it as a Set. But then there was some warning (forgot details) and I made it a Collection instead.

That's why I'm very happy to have my code reviewed :D
 

Esereja

Active Member
Contributor
I included lot of changes to portals(honestly don't know if all changes are in beter direction), including ranged spawning, spawning only when player near, and diferent speed spawning. Renamed gelCubeFactory to defaultMobFactory(as it ccan create anything by prefab).
and broke something. As when loading world again from save, it doesn't start spawn again. Can't find why yet.

And Id like to join spawning system planing and coding(just lets plan clear structure so I don't code lasange code(too eager to code)).

I'd like to include spaning system that would allow rare spawning AI around player where ever player is. So that world seems to be populated. It would activate when even one prefab includes this system. and spawn only those AI that include it.
But proplem is how I structure this code. Will I have combonent for that and heve system inculde spawning or something bit more comblicated?

and my idea out about natural selection on AIs:
http://forum.movingblocks.net/threads/three-tier-ai.637/
 

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
Finally got a chance to review the pending pull request - am really appreciative to have you enhance the setup, I wanted to do ranged spawning and such myself, so you're saving me precious time. Now it is 1 am though and I need to work the rest of the week, so I'll try to get around to posting some design notes as soon as I can find the time :)

As a quick primer we can do "world spawning" simply by attaching a SpawnerComponent to the player entity itself, making sure to only enable ranged spawning, not local (the player itself probably shouldn't spontaneously reproduce by budding Gooeys). There you can also configure what should spawn in the world as opposed to coming from out of a portal. So you wouldn't even need any new Components or Systems for that. That's the power of our entity system :)
 

Esereja

Active Member
Contributor
Git hub pull fixed.
I can't get world spawning work just by attaching it to player. I made changes at my own combuter to spawner system to allow player to get this combonent but still it doesn't spawn anything. It seems spawner system gets no updates. so any ideas how to get result of world spawning?

My next priority is to get world spawning to work.
(must go to sleep too much coding for this, ummm, day)
 

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
Pulled - thanks :)

Not sure on your question though - I spent a little time on extra but it is getting late.

I'll put some updates in the original post including details on the new gellies :D
 

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
Bump! Time for a little update.

Yesterday I actually pushed some code - woo! I had been reintroducing my good friend Stuthulhu to the codebase and approaching the topic of Holdings from a slightly different angle. Here the focus is on creatures and social stuff while the other thread is more focused on players/locations/hierarchical connections between holdings.

SpawnSystem needs some work as it is still pretty raw and these changes moves it along a little bit. Mainly it introduces parent links from Spawnables (creatures) to Spawners (portals or just about anything else). That allows binding some creatures to an artificial Holding entity and doing stuff based on group details like total count (population)

Specifically the new HoldingSystem will check through Holdings, of which the first example is just the mundane Portal, and if more than 10 GelCubes have been spawned it'll turn one of them into a queen by attaching a Spawner to it ;)

Beyond that it'll increase a threshold for another queen to be nominated, but that's really just an example. Point is - this is a tiny but useful foundation for doing something specific related to a grouping of creatures and/or a location. This should get along nicely with some of the stuff in Miniions as the next two likely goals are making threshold triggers for shelter construction and food gathering (which could be farming)

For those wanting to play with it just grab the latest dev build, enable Portals, and place one or more portals (/giveBlock "portal"). Each will keep a separate count from the others and upgrade a gelcube to queen after 10 spawns. To keep counts a little easier to sort out I've been blowing holes in the ground for them (pens) and world spawning (the player's SpawnerComponent) has been temporarily disabled.

Note that when a queen does come into play it'll spawn more gelcubes, faster, with a very high limit. Didn't take it to the next level to have those groupings spin up queens of their own :D
 

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
Minor update: Hacked together spawning Oreons via portal with Stuthulhu so there's some more flexibility in playing with creatures :)

Probably cleaner ways to do it, not sure how needed the approach in DefaultMobFactory really is or how likely plain Mesh == GelCube and SkeletalMesh == other stuff. Easy minimal impact type stuff for now.

Was nice and easy to make the Oreons bounce around like GelCubes, but that's just a demonstration hack so they'll do something :D
 

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
Eep, cobwebs, be gone! :eek:

Slowly started working on Portals again. Got very basic functionality working - there is now a dependency on LASR (L&S art) and the basic "portal" will spawn the red team. They'll have the old simple AI attached that just makes them run around goofily.

GelCubes are more in trouble as their rendering was old and hacky, and has since gone poof. Will need to sort something out, but don't need them right now. So the other portals are mothballed along with some other fancy stuff.

Working toward a new chest that'll spawn L&S stuff when you put stuff in said chest. Can do that with what's available now, just need the time to play with it. Another idea is upgrading them from goofy old AI to shiny new pathfinding fun :)
 

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
The quest for pawn-spawning toy boxes moves on!

I've got an initial implementation that adds an additional check for an item that must be present in an inventory of a spawner if the chosen spawnable calls for it - but my "mastery" of inventory magic was dubious enough before the multiplayer changes and now I'm fairly lost :D

I have a chest that's also a spawner. I can get its inventory component but ... then what?
  • Use the inventory component directly somehow?
  • Use the CoreInventoryManager class somehow?
  • Use events somehow?
The manager looks tasty but I'm not sure how to get at it

Comcast is failing hard tonight and I ran into a quirk where some of the L&S prefabs got capitalization-duplicated somehow. Deleted the dupes directly on GitHub, but of course Windows being Windows my local workspace is all messed up now thinking the deletion of one case should be deleting something locally of whatever case. Yay! Turning in for tonight ;)
 

Immortius

Lead Software Architect
Contributor
Architecture
GUI
In general you would want to listen for the inventory events to determine when some action may be required. These need some work, but InventorySlotChangedEvent at least should be useful.

The InventoryManager can be obtained using @In. You would get either InventoryManager or SlotBasedInventoryManager, not the implementation.

And yes, you can directly access the inventory component.
 

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
Thanks Immortius - I got it working :)

Tripped myself a few times just getting used to things again. For a while I was trying to do a removeItem with a brand new EntityRef referring to dirt - when that method only works if it is the exact same entity reference, I think. Eventually did a String compare of the names instead then a remove from the stack I retrieved from the chest. I dropped down to a one-slot chest so I would know what slot to check - seems like it would be kinda brute-force'ish to manually check each slot - or am I missing some utility method somewhere?

Another spot was how itemSlots in InventoryComponent is package private scope - I figured that was to force use to go through the inventory manager(s). Wasn't sure what to think about the accessors

Either way it works as a proof of concept. Not pretty or elegant yet but then I'm only just getting started. Made a quick demo video:


SuperSnark also prepped some block replacements that'll be put to use soon:

LASR_blocks_small.png
 
Top