Ok, so apparently I'm "Lead Software Architect". Previously things have been fairly quiet so I have been dedicating time to realising the architecture rather than writing up reports on it (or just generally been slack), but things are picking up now. So in this thread I wanted to share details on the architectural vision and what this means for developers. Feel free to chip in with any questions, suggestions or such.
First, some general goals of the architecture:
The modules contain:
The entity system is a central mechanism in all of this. The strong persistence mechanisms we have around components and entities enable saving and loading, prefabs and network serialization. Being able to mix existing components with new components allows granular reuse. New systems can be added to change the behaviour of existing entities or react to existing events. And prefabs allow the creation of new objects, using new or existing assets, with a mashup of existing behaviours - providing codeless modding.
The engine will supply a set of components and events to link entities to the core capabilities - rendering, audio, physics and collision, input. It will also provide APIs for working with them - such as the Physics API for doing traces, or a Time API to get ingame and real times.
The voxel world is the other major pillar. The World API is provided for gameplay interaction, with single and batch block changes. Underlying this is all our chunk logic. This hides most of the implementation details, although some knowledge of whether chunks are loaded is needed. Individual blocks are also provided as temporary and occasionally persistent entities for interactions.
Assets are loaded through an asset manager, which ties into the module system to make available assets from the currently active modules. All assets are identified by a uri - this allows them to be persisted and restored when used in components. Supported AssetTypes are currently hard coded in the AssetType enumeration, but this can be refactored to allow extension. AssetLoaders provide the loading implementation.
Networking is under active development, and is described further in the incubator thread.
For rendering, we have the primary assets of mesh, skeletal mesh, animation, texture, shader and material. Materials provide the combination of the shader + shader params. The mesh and skeletal mesh components provide the ability to make an entity visible with these assets. World rendering is also handled in the engine itself.
The engine uses a combination of discovery through annotations/interface implementation to find components/systems/events, and reflection for instantiation and generic interaction with them - this drives serialization. The use of reflection is not ideal in some areas, and will be replaced with bytecode manip in the future to improve performance (particularly serialization as it will be used heavily in multiplayer).
First, some general goals of the architecture:
- Strong modding support. There are a number of aspects to this
- Avoiding conflicts - things like not fixing blocks to specific ids and namespacing all assets
- Allowing the introduction of new behaviour and assets outside of the engine (so no jar modification hacks needed)
- Allow some modding without java coding - instead using data to drive things (prefabs, block definitions)
- When coding is involved make things modular, easy to use, powerful and with a good system for plugging in to existing systems.
- Resilience to errors and change. An exception in a mod should not bring down the entire game. If a mod is updated with components changed, existing saves should not break.
- Reasonably secure. This is particularly important if we want quality of life features like automatically downloading plugins from servers - we need to ensure that those mods can't format harddrives or do other such things.
- Clear, well document API (not done yet) - describing what can be used, and what can't in mods
- Separation between engine concerns and game logic/assets. This ties into modding support, but the engine should be concerned with core features like rendering, audio and voxel world support. Game logic comes through modules, which means that the entire set of modules can be changed to achieve completely different game play.
- A core engine (Terasology.jar + underlying jars)
- A number of modules (Core, TestMod, Minerals, etc)
- Module loading
- Asset Management
- Core Asset Types
- Audio
- Input
- Network
- Console (not the commands, but the console itself)
- Physics
- Rendering
- GUI
- Voxel World
- Entity System
- Event System
- Persistence
- Main Menu / World creation and loading
- Maths
- Engine state (driving everything)
- Time
- Particle System (currently not present)
The modules contain:
- Assets
- Gameplay related components/systems/events
- Chunk Generators and simulation systems (this needs work)
- Potentially other extensions, such as new asset handles, new type handlers (for supporting new types in components)
The entity system is a central mechanism in all of this. The strong persistence mechanisms we have around components and entities enable saving and loading, prefabs and network serialization. Being able to mix existing components with new components allows granular reuse. New systems can be added to change the behaviour of existing entities or react to existing events. And prefabs allow the creation of new objects, using new or existing assets, with a mashup of existing behaviours - providing codeless modding.
The engine will supply a set of components and events to link entities to the core capabilities - rendering, audio, physics and collision, input. It will also provide APIs for working with them - such as the Physics API for doing traces, or a Time API to get ingame and real times.
The voxel world is the other major pillar. The World API is provided for gameplay interaction, with single and batch block changes. Underlying this is all our chunk logic. This hides most of the implementation details, although some knowledge of whether chunks are loaded is needed. Individual blocks are also provided as temporary and occasionally persistent entities for interactions.
Assets are loaded through an asset manager, which ties into the module system to make available assets from the currently active modules. All assets are identified by a uri - this allows them to be persisted and restored when used in components. Supported AssetTypes are currently hard coded in the AssetType enumeration, but this can be refactored to allow extension. AssetLoaders provide the loading implementation.
Networking is under active development, and is described further in the incubator thread.
For rendering, we have the primary assets of mesh, skeletal mesh, animation, texture, shader and material. Materials provide the combination of the shader + shader params. The mesh and skeletal mesh components provide the ability to make an entity visible with these assets. World rendering is also handled in the engine itself.
The engine uses a combination of discovery through annotations/interface implementation to find components/systems/events, and reflection for instantiation and generic interaction with them - this drives serialization. The use of reflection is not ideal in some areas, and will be replaced with bytecode manip in the future to improve performance (particularly serialization as it will be used heavily in multiplayer).