Implementation Structure Templates

Florian

Active Member
Contributor
Architecture
Module name: Structure Templates
GitHub: https://github.com/Terasology/StructureTemplates
Status: Usable

This module can be used to create structure templates in game.

Structure templates allow you to place multiple copies of the same structure multiple times into the world.

For example you could just build one small section of a wall and then create a item that allows you to place that wall section multiple times to create a wall:




Structure templates can be created via the following steps:
  1. You use the command `giveItem structureTemplateGenerator` to get yourself a structure template generator item
  2. You click with that item a ground block infront of the building you want to copy. You get a structure template editor item.
  3. Activating (right clicking) the structure editor item opens a minimalistic UI, that can be used to define the region that you want to create a structure template item from.


  4. The same UI also offers you a button that can be used to create a item that spawns the structure
  5. While you hold the structure spawning item you see a outline of where the structure will appear:

  6. You can select the spawn location of the structure by moving around with your character
  7. The structure appears always infront of you, by rotating your character can choose the rotation of the structure as the structures front will always look towards you
  8. Right clicking with that item spawn the structure.
The module is a side product of my Gooey's Quests module where I needed a better way of creating dungeon room templates.
 

Florian

Active Member
Contributor
Architecture
I made the structure template module use the the default Region3i serializer.

Sadly this means that the format how regions get stored changed from min + max to min + size. I adjusted the Gooey's Quest module accordingly. If you made some nice templates already with it, let me know and I can give some conversion help.

As a small bonus of this, the edit region editor now protects itself against max values that are greater than min by swapping min/max.
 

Cpt. Crispy Crunchy

Member
Contributor
Nice Stuff!
Just tried it out and works pretty good ! :)
Only the clipping of the structure onto the bottom of the focused block is a bit unintuitive. I would prefer the structure to be spawned on top of the focused block but thats just personal taste I guess.
How/where do you save the created structures? Would it be possible to have them as sort of Prefab? I could imagine this to get well along the dynamic city generation project. Maybe it would be possible some time in the future to get players design some house in-game, assign properties like what type of building it is and then it will be added as possible building type for cities afterwards. Could become very intuitive to non-programming players :)
 

Florian

Active Member
Contributor
Architecture
Nice Stuff!
Just tried it out and works pretty good ! :)
Only the clipping of the structure onto the bottom of the focused block is a bit unintuitive. I would prefer the structure to be spawned on top of the focused block but thats just personal taste I guess.
How/where do you save the created structures? Would it be possible to have them as sort of Prefab? I could imagine this to get well along the dynamic city generation project. Maybe it would be possible some time in the future to get players design some house in-game, assign properties like what type of building it is and then it will be added as possible building type for cities afterwards. Could become very intuitive to non-programming players :)
There was already some confusion about the bounding boxes that are initially in the ground. So I made the default edit region now be above the ground.

The editor that opens when you right click the blue item has at the top left also a button called "Selected -> Clipboard". This button copies the blocks in the selected region to the clipboard in a format that is usable in prefabs.

The copied text look like this:
Code:
  { "blockType": "core:stone", "region": { "min": [-1, 1, 0], "size": [1, 2, 1]}},
  { "blockType": "core:stone", "region": { "min": [-1, 3, 0], "size": [3, 1, 1]}},
  { "blockType": "core:stone", "region": { "min": [1, 1, 0], "size": [1, 2, 1]}},
@Cpt. Crispy Crunchy: You can use it in prefabs like I have done in my gooeys quests module:
https://github.com/Terasology/GooeysQuests/blob/master/assets/prefabs/dungeonEntranceSpawner.prefab

To spawn the prefab you simply send a SpawnStructureEvent event to it:

Code:
CheckSpawnConditionEvent checkConditionEvent = new CheckSpawnConditionEvent(transformList);
entranceSpawner.send(checkConditionEvent);
(Code is from https://github.com/Terasology/GooeysQuests/blob/40e5381cbcd9f2bba7f3229a58fdaccc32f38f56/src/main/java/org/terasology/gooeysQuests/quests/dungeon/DungeonQuestSystem.java#L182)

Code:
BlockRegionTransformationList transformList = new BlockRegionTransformationList();
transformList.addTransformation(
HorizontalBlockRegionRotation.createRotationFromSideToSide(Side.FRONT, side));
transformList.addTransformation(new BlockRegionMovement(spawnPosition));
The transformations currently support positioning and rotation, but it is trival to also add mirroring should there be need.
 

Cpt. Crispy Crunchy

Member
Contributor
There was already some confusion about the bounding boxes that are initially in the ground. So I made the default edit region now be above the ground.
Cool thanks! :)


Wow, that looks like there's a lot of potential. I'll try to give the spawning building process a strategy, so that one can choose which instantiation to use (yours or the method in cities so far).
I think it'll make a good fit :).
 

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
Quick related FYI: I fixed up a tiny bit of API drift in this module and GooeysQuests, the bit where a protected method had changed to public. Also added StructureTemplates to the module lineup and made it a job in Jenkins so it'll be available for dependency resolution and bundle with the game :)
 

Florian

Active Member
Contributor
Architecture
I pushed a new version to the git repository:

Change Log:
  • The module contains now utility classes that allow other modules to check spawn conditions for structures.
  • When you hold a item with a spawn condition, and that spawn condition is not met, then the region where the spawn conditions failed will be highlighted

  • When you try to activate the spawn item anyway, it will show you an error dialog that explains what blocks it expected in the highlighted region. In addition to that after a failed structure placement the problematic region will remain, so that you can have a closer look at that region from different angles. When you activate the item again, the region will vanish again and you can go back to structure placement.

  • To try the feature out, activate the newest Gooey's Quest module and get yourself a structure spawn item via "giveItem dungeonEntranceSpawner"
Technical details:

The structure spawn conditions can be defined like this:
Code:
"CheckBlockRegionCondition" : {
    "checksToPerform": [
        {"condition": "StructureTemplates:IsGroundLike", "region" :{ "min": [-1, 0, 0], "size": [3, 1, 1]}},
        {"condition": "StructureTemplates:IsGroundLike", "region" :{ "min": [-2, 0, 1], "size": [5, 2, 1]}},
        {"condition": "StructureTemplates:IsAirLike", "region" :{ "min": [-1, 4, 1], "size": [3, 1, 1]}}
    ]
}
The condition attribute is a reference to a prefab that defines a condition for a block. (A full example can be found at https://github.com/Terasology/GooeysQuests/blob/master/assets/prefabs/dungeonEntranceSpawner.prefab)

It can look like this:
Code:
{
   "RequiredBlockProperties": {
        "penetrable": true,
        "liquid": false
    },
    "DisplayName": {
        "name": "Air like blocks", // Text gets used in a message like "Red region must contain: <name>"
        "description": "Blocks that act like air: e.g. they are penetratable and replaceable with other blocks"
}
}
Modules can also define their own block condition prefabs if they want to.

It is also possible to define your own block condition component, you just then have to create a handler for a
GetBlockPredicateEvent event. The handler has just to add it's condition to the event.

It is also possible to define non block based custom spawn conditions by adding a event handler for
CheckSpawnConditionEvent events that get sent to custom components with custom conditions. (e.g. it might be reasonable to add at some point the condition that there is no character in the spawn area)
 
Last edited:

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
This looks hugely useful, first thing that comes to mind is placing "workshops" in a DF/DK sort of way. Could we mix it with a grammar like how @Skaldarnar had a way to indicate a range for some dimensions, maybe with a multi-step process or selectable way to adjust the desired dimensions one by one?

We badly need to push that further, get a nice tutorial going, then apply it in other places :D
 

Florian

Active Member
Contributor
Architecture
Pushed a new version to the repository.

Change Log:
  • A way to have structures spawn other structures has been added. You can basically specify that one structure spawns a certain type of structure, and each structure template can specify of which type it is.
  • Fixed some multiplayer issues. One of the fixed problems used to prevent a headless server from starting properly
  • The structure template editor now copies also air blocks. The copied json is sorted by block type, so it is easy to delete one block type out.
  • Added a button for copying the current region of the structure template editor as "this region needs to be ground" condition for the prefab.
 

oniatus

Member
Contributor
Architecture
Would be awesome to combine the planning feature with the behavior module. Imagine some tiny helpers which collect the required materials from your storage, jump up the walls or build tiny scaffoldings and then build the final stuff :)
Castle Story / Stonehearth like.
 

Skaldarnar

Development Lead
Contributor
Art
World
SpecOps
@Cervator I have the templates high up on my list to look into. I definitely want to integrate the grammar system/building generation so that we can test it easily and of course can use it in the city generation process.

@Florian What do you think about extracting gameplay information from the templates, e.g., when the structure "workshop" spawns another structure for "smithing utilities" in some free space? Could this be used to easily customize/configure generic building templates for specific use cases?
 

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
Would be awesome to combine the planning feature with the behavior module. Imagine some tiny helpers which collect the required materials from your storage, jump up the walls or build tiny scaffoldings and then build the final stuff :)
Castle Story / Stonehearth like.
Yes! The ancient Miniion module did this in a lesser fashion, where at least little Oreons would build a structure block by block, but there was occasionally some teleporting involved rather than scaffolding.

Also, great to see you again! Any free time coming up to help make that happen? :D
 

Florian

Active Member
Contributor
Architecture
@oniatus: I don't plan to do any minion builds something features right now. If you are interested in doing it feel free to go for it.

@skaldanar: The dungeon generation in Gooey's Quests works exactly like that. Basically only just a dungeon entrance gets placed, that has the information in that that it should be extended by a "cooridor". The corridor is chosen randomly from all prefabs that have delcared themself of type corridor. The chosen corridor might be a "corridor that makes a right turn" structure that itself again declares that it can be extended by another structure of type corridor. Since this can cause a chain reaction and result in a lot of potentially spawned buildings the algorithm tries to spawn only 1 building per system update cycle.

Structures templates can spawn other structures via ScheduleStructurePlacement component

Code:
"ScheduleStructurePlacement" : {
    "placementsToSchedule": [
    {
        "structureTemplateType": "GooeysQuests:dungeon1x2StoneDoorFrame",
        "front": "RIGHT",
        "position": [-1, 0, 3]
    },
    {
       "structureTemplateType": "GooeysQuests:dungeon3x3StoneCorridor",
        "front": "FRONT",
        "position": [0, 0, 7]
    }]
},
The section is from dungeonCorridorWithRightDoor.prefab
 
Last edited:

Florian

Active Member
Contributor
Architecture
I just pushed a new version to the repository:

Change Log:
  • It is now possible to specify how often a structure spawns compared to others ofthe same type. this is done via a spawnChance attribute in the StructureTemplate component. By default it is 100. If you set it to 200 then the structure spawns twice as often as other normal structures. If it is set to 50, then it spawns half as often as other normal structures.
 

oniatus

Member
Contributor
Architecture
Also, great to see you again! Any free time coming up to help make that happen? :D
In around 6-7 weeks after my own GSOC. The tutorials for asset/entity-System are still on my tasklist (thanks for linking the asset tutorial in the alpha news :thumbsup:).

@Florian
Sounds good. How hard would it be to reuse the wired templates for direct building without predefined sizes?
 

Florian

Active Member
Contributor
Architecture
@oniatus Tutorials for asset/entity-Systems are really usefull again, there are some basic onces but nothing that guides you fully though.

About direct building without predefined sizes: I am not sure what you would mean with that.

You can have an item that shows a resizeable region outline in the world (the structure template editor) does that already. Filling then that area with a single block type would be simple.
You can also make a template of a part of a building, and the n place that part again and again to create also non fixed size buildings. (Like I did with the wall in the first screenshot).

It would also be possible (just via prefab!) to make for example a bridge head, that when placed will automatically extend itself with further bridge parts till it has created a whole bridge to the other wise at dynamic distance.

It is also possible to create templates that can only be placed at certain positions. So you could make different building parts and only allow the user to attach them to other existing building parts. e.g. A tower that can only be placed on a wall. Or a wall part that can be only placed on a starting stone or next to another wall block.

The dungeon entrance structure from Gooey's Quests has for example a very complex spawn condition that allows you to only place it at the side of hills in a way that look natural.
 

Florian

Active Member
Contributor
Architecture
I pushed up a new version:

Change Log:
  • Long durations for spawning a structure get now logged (may be removed again in future)
  • Large spawn chance differences can now be used without performance penality
Previously the algorithm for spawning a structure for a ScheduleStructurePlacement component was like this:
  1. Select an outstanding structure placement
  2. Select a random structure of a given type, based on spawn chance
  3. If it can be spawned, spawn it
  4. If it can't be spawned, go back to step 1 (in next update cyclus)
So if there was a structure template with a high spawn chance, but with a very unlikly spawn condition, then the algorithm would try very often to spawn it. So it might take quite long till the algorithm might pick an actually spawnable structure template for a given structure type.

The new algorithm is like this:

  1. Select an outstanding structure placement
  2. Determine a list of structure templates that have the requested type
  3. Select a random structure from the list based on spawn chance
  4. If it can be spawned, spawn it
  5. If it can't be spawned, remove it from the list and go to stpe 3 (in next update cyclus).
  6. If the list is empty, stop trying to spawn the given structure type at the given location
So if a building with a (high spawn chance) can't be spawned at a given location, it won't be tried again to spawn it again. This makes it possible to structure templates with a very small spawn chance that act as a fallback.
 

Florian

Active Member
Contributor
Architecture
I recently pushed a version with the following changes:
  • Fixed a bug that caused chests to be empty in multiplayer till you replace them ( https://github.com/MovingBlocks/Terasology/issues/2474)
  • Introduced a GetStructureTemplateBlocksEvent event, that can potentially be used to introduce components that replace blocks placed by other components
  • Introduced also a StructureBlocksSpawnedEvent and a StructureSpawnStartedEvent that event handlers should now use instead of SpawnStructureEvent. This is a preparation to make it in future possible to have a delayed/animated block placement.
  • The module uses now setBlocks method, which drastically increases the performance(thanks to @Skaldarnar for his PR). Sadly it is currently missing some logic which is why it is so fast... So the performance advantage will be gone when we decide to merge PR https://github.com/MovingBlocks/Terasology/pull/2481
 
Top