Code Monkey home page Code Monkey logo

voxelthingyeah's Introduction

VoxelThingYeah

VTY Is a game engine built from the ground up for Meegreef. As little as possible is hard-coded, and the engine sets out to allow as much moddability/customisability as possible.

voxelthingyeah's People

Contributors

acbob avatar

Stargazers

 avatar

Watchers

 avatar

voxelthingyeah's Issues

Player Input through ConCommands

Needs #3 - Use Commands that are bound to keys to shoot player input at the server, Much like how the Source:tm: Engine or Quake(?) does it.

This avoids absorbing the bandwidth like a sponge but keep player input.

I'm not sure if a player's looking should be bound by some ConCommand system, I'm banking on 'probably not'.

Full ConCommand / ConVar System

Using either Quake 2 or Source SDK as reference, ideally we want to fully actualise the ConVar system to also include ConCommands.
I've had an idea of having ConVars have a 'Set' & 'Get' custom function that you can use to override, i.e making commands just a custom set function to vars (such that they don't set any values, they just run a function with it as arguments or something)

Physics Improvements

Collision

  • Collision testing all chunks that the Collision Box is in
  • Rotate-able Collisions
  • More shapes
    • Sphere
    • Mesh

Physics

  • Friction
  • Gravity modifier (water lowering it, etc.)

Immediate Mode GUI

ImGui's cool, but rather bland and un-customisable.
Nuklear's cool, but wouldn't fit into the InputManager system very well from a glance.
(Also something something bloat)

But boy can we copy some concepts.

The game needs an interface. Simple enough to do, just slap some quads together and present to the screen.
Then there's the case of input, which can be handled with the InputManager, as ALL client-side input should be.
There's a VERY simple setup here, but it's very simple. It has some buttons, labels, and shitty text input (#16) - but isn't very useable.

API Design

Every element should be a function of the CGui class, and it will present the control to the screen, returning anything if it can.
I.E For the case of the button, It takes the position & size, and then draws a button, returning if it has been clicked.

bool CGui::Button(CVector vPosition, CVector vSize); // TRUE if clicked

In the case of something like a Text Input, where the state should be preserved through frames, there would be a buffer variable that would take the ID and store it. In the case of a Text Input, there is the m_textBuffers vector which stores the char arrays.

Calling Update at the end should require no arguments, and will actually push the vertex data towards OpenGL, along with updating stuff like the hovered element or the selected element.

Elements

The necessary elements would be as such:

  • Window
    • Tabs
    • Dialog Box
  • Generic Menu (Tool-tip?)
  • Image
    • Model renderer?
  • Labels
  • Buttons
    • Text Button
    • Image Button (Technically done, just weird)
  • Check Box/Toggle Box
  • Progress Bar
  • #22
  • Scrollbar

Other Points

  • Z-Coordinate for depth testing
  • 3D Modes
    • In-World 3D (i.e applied to a surface)
    • Cool:tm: perspective "depthed" 3D, where every element is a cube

State Machine

The API and Design are out of the way, but now how do I handle it for the game? A state machine.
Two, to be exact. One would handle the base game state, Playing, Loading, Menu-ing, etc. But they'd have their own classes to use, like a CGuiMainMenu for example.
Each of these classes would have their own states, in something akin to CGuiPlaying would have 'playing', 'inventory', 'pause' and 'chatting'. An options menu would have 'overview', 'controls', etc. etc.

Modding API

Modding API.

Built into resource packs (#13) allowing scripts - this would require servers to have resource pack support, something needed if we want to also send a sever-mandated resource pack.

Designing around this, we'd have the root resource pack directory and then a 'scripts' folder. Inside this would be some kind of allowance for organisation, but that brings up questions of what do we do for modpacks, just merge resource packs? or put them on top?

Scripting language of choice will be Lua, if not support for multiple languages (Putting the C++ portion of the API behind some heavy abstraction), main.lua in a folder of scripts/ will then be executed at launch, allowing the file to call other files in its' mod directory.

Now, the actual design of the API, that's a massive TODO.

Improve shader #include

GLSL Is fine and dandy and all, but we've got a LOT of repeated code.
We need some kind of pre-processor with an #include directive. Although similar functionality may be achieved with Open GL 4.5's new shiny feature to compile multiple shaders together, but that's boring (and not at all portable to something like vulcan).

This is a stupid easy concept, simply take a file, search it for #include, use the second argument as a file path, handle that file and its' #includes, and then glue together by replacing each #include with the file at the end.
Handling circular includes should be easy, just see if any of the included files cause the file to include itself.

Implementation? Regex or something.

Better world handling

Not a complete list at the moment by any means!

  • Not have all chunks in memory at a time
  • Better world saving/loading (Separate Issue due to depth?)
  • Map for accessing instead of looping over all chunks

☠️ 🎃 Multithreaded!

Ooo Ooo, spooky!

For real though, this will probably be extremely hard, but it's also esssntial for good performance.

Good Skin Support

Skin support currently is a quick hack and needs to be rewritten.

Skin data isn't tested for validation, and leads to bugs.

Chunk Data

Currently just a flat array of Block IDs, it may be useful to expand this.
Perhaps we provide 8 bits per block for variation values, like storing the direction, maybe water level values, etc.
This'd get limiting, so perhaps we have two values up to a total of 16 bits to control various things.

Another consideration is a second block ID, which would facilitate 'water-logging', carpets on stairs, snow on slabs, etc. etc.
It would simply be two blocks in one position, which wouldn't necessarily mean anything, the first block would take precedence and it would be on a block-per-block basis on how to treat it.
More likely, it'd be down to the block features on how to treat it. Non-solid blocks like fences, slabs and leaves would get marked as "flowable" or something, allowing water to pass into the second block, or slabs and stairs would have a 'carpetable' quality that would swap out for a carpet variant of the block model.

Breaking a block should yield the drops of the first and second block, in the case of Liquids it should drop the first and push the liquid to the first block.
But if you place, it should be on a block-by-block basis, where you cannot place water inside, say, planks, but can place it inside something like slabs or stairs.

Ideally #23 would be addressed before this, but it's not really dependent.

Proper separation of Client/Server code

I had the novel idea of using one source file for networking and various other things - a folder dubbed shared. Similar design philosophy to Source SDK, but I did it wrong.

Where the Source SDK has a client, server and shared version of things, I just have the shared one it seems.

ALL of the networking & server code is held in shared/network and it's bad and reaching unmaintainable. Needs to be separated out better.

Lighting engine ideas

Instead of having lighting handled by the chunk, move responsibility to the World. The world handles all of the lighting as it knows about every chunk.

We start sunlight in a kind-of odd way. At the top of every chunk. If there is no chunk above us, assume every block at the top has full sunlight and no artificial light. If there's a chunk above us, use the sunlight value of the air.

Sunlight propagation should be handled thusly; at the top of every chunk, loop down until we hit a block that does not allow sunlight to propagate. after that, set the sunlight value of the block to 0.

These should be different steps! If a non-solid block (i.e not a cube) is broken, don't try to re-calculate sunlight. If it is, make sure there's even a little bit of sunlight. This should loop down to the bottom of the loaded chunks.

lighting data gets saved to the disk along with worlds (important for #8), the server also calculates sunlight and sends it to the client.

Particles!

Somehow I'd completely forgotten I have some stub code for a particle system.
Always facing the camera, in a mock-modifier setup like Source:tm:.

Particle definitions handled by TOML, the code just knows when to use them;

[block.break]
# for regular particles (see explosion), there'd be a tex variable. It doesn't matter here as it is set by code.
# Also omitted: texatlas, texdiv, texatlasrand
num=125 # 5 * 5 * 5
explode=[-5,-5,-5, 5,5,5] # As a first go, launch immediately from X,Y,Z to X,Y,Z
linear=[0.0,-9.8,0.0]# Apply linearly every frame (multiplied by delta), One set of X,Y,Z means no random
collision=true

[explosion]
tex="explosion.png"
# [ [X,Y, SX, SY] ], If multiple it randomly chooses.
texatlas=[[0,0, 2,2], [0,2, 2,2], [0,2, 2,2], [2,2, 2,2]]
texdiv=8 # How many textures there are in the atlas
texatlasrand=false # If true, the U/V Is then randomised in the atlas chunk
explode=[-2,-2,-2, 2,3,2]
linear=[0.0,3.25,0.0]
collision=false

Correct Keyboard Input

Works fine for game input, but when it comes to typing things go wee woo.

Particularly this bad apple here. (Which needs to be rewritten to support focus anyway) where it's all bad.

Potentially bInGui in InputManager also controls SDL's unicode support? Adding a buffer for input text and then putting that in text inputs that we have focused, with the key SDL tells us was hit. This might cause desync with the game input system? In that case that'll need to be rewritten.

World Generation system

Ideally we'd make it easy to write new forms of world generation and have them easily set (via a world setting or something).

The great model catch-all

  • Skeletal Animation
  • Vertex Animation (for faces and stuff)
    • Vertex Tagging (Vertices grouped by some kind-of ID)
  • Smooth Lighting
  • Multiple Resources
    • Multiple Textures
    • Multiple Shaders
  • Frustum Culling

Network Protocol

I need to define a proper protocol for the network, Looking at Minecraft it seems to have a shitton of packet types without much care in the world for saving them (Cuberite as reference on 1.8) so I can do the same, right? Right?

This doesn't clear up how MC does player input, I'm still thinking looking should be 100% client-side (and set to the server, although this might have issues if the client lies) and use a source-like ConCommand system where inputs are commands executed on the server.

Fix Liquids

Liquids are cool and work like Minecraft Classic save for one thing:
They hardly obey ticks.

I can only assume it's because it indexes the blocks linearly, so it spreads one block and goes to a block it just spread.

A fix would be to store the positions of blocks that are marked as 'Liquid' in BlockFeatures (along with the blocktype maybe) and then spread those after indexing the chunk.

Entity System

Need a full entity system working, that includes networking. Requires #2 and #1 to fully function.

Reorganize code

  • Separate Client/Server Code
  • Segment code into key DLLs loaded by an "Engine"
    • Rendering (See #12)
    • Windowing
    • Utility Stuff (such as math, parsers, etc.)
    • Client
    • Server
    • Shared (Between client/server, so stuff like the ConVar system and some chunk/world code)

World saving and loading

The world format should be easy to decipher.

Look into NBT, SQLite or similar.
Packet serializer may work, but is not entirely portable as I have no idea what it does to data.

Resource Pack Support

A big part of what made Minecraft special is that you could just replace all most of its' assets.
These were called Resource Packs, and allowed replacing the font atlas, textures, models, sounds, etc.

Handled either as zip files or just folders laying around.

With PhysFS this is stupid easy. And I made sure the wrapper supported it.
Literally just mount a path:

// Note that this will place TakeALootAtMy.wad as the top-most pack,
// Then Zippy.zip and CoolResourcePack - and finally the game's actual assets.
fileSystem::Mount("packs/CoolResourcePack", "/", true);
fileSystem::Mount("packs/Zippy.zip", "/", true);
fileSystem::Mount("packs/TakeALootAtMy.wad", "/", true); // Wad File supported because of PhysFS

This will place the resource pack, be it ZIP, Folder or even WAD(!!)

All that really needs to be dealt with is other issues such as:

  • Resource pack menu
  • Changing while running
  • Identifying Packs

I have some ideas for the last two issues. Changing while running would mean unmounting every directory we have mounted so far, sans the game's assets. - Then going back through and mounting them in the correct order (probably reverse order with prepend set to true).
i.e

for (int i = loadedPacks.size(); i > 0; i--)
{
    fileSystem::Mount(loadedPacks[i], "/", true);
}

For identifying, we'd need some kind of pack manifest. As much as I'd love to use ConVars everywhere, this needs another format.
I refuse to use JSON. TOML Is an option, as it's practically INI:

[resource-pack]
name = "Cool Pack"
desc = "My cool pack"
hasSounds = true
hasTextures = true
hasModels = false

Note that for that, I toy with the idea of mounting just specific folders, as to have the manifest file, we'd need to somehow mount a manifest.toml without replacing all the other ones.... Maybe mount a cfg directory of the pack to packs/ and then mount the individual textures & sounds folders? This could also allow for enabling/disabling certain aspects of pack replacement, or make one pack's sounds more important than another's...

Arbitrary fonts

Specify character ranges and specific characters that render with X texture. Internally stitch it into one.

[fonts] # Note that named ones (such as ascii, cp437, etc.) are hard-coded to 16x16 tiles.
ascii="" # Give a path to make a texture treated as ASCII (0-127)
cp437="font.png" # Maps characters to use the right positions as if we use CP437. 0,0 is NUL, 1,0 is Smiley, etc.
jap="" # Japanese or whatever
manual="blah.png" # Specify custom positions on the texture file for characters.

[blah.png]
'a' = [0,0]
'0x2593' = [1,0]

Why would we want it?
Different, arbitrary language support.

image
Public Domain, https://commons.wikimedia.org/w/index.php?curid=10573855

Infinite World

Each player up to their render distance (and up to the server's forced render distance) will load chunks around them from the server

Requires #6 ideally so we can see some cool shit and not an empty plane of grass

Localisation

Translation into arbitrary languages.

How it is done, is up in the air. GNU GetText looks interesting, but doesn't seem like it'd merge well with the TOML I want at all. It may be worth committing the sin of rolling our own translation library. ⛈️

languages.toml & language files?
e.g

[en_gb]
friendly_name = "English (British)"
lang_file = "lang/en-gb.toml"

[en_us]
friendly_name = "English (Simplified)"
lang_file = "lang/en-us.toml"

[da]
friendly_name = "Dansk"
lang_file = "lang/da.toml"

and then en_gb.toml

[gui]
done = "Done"
confirm = "OK"
cancel = "Cancel"
exit = "Back"

and posterity, da.toml

[gui]
done = "Gjort"
confirm = "Bekræfte"
cancel = "Aflyse"
exit = "Udgang"

There should be no limit! I want custom languages to be supported. adding something like

[yarr]
friendly_name = "The Seven Seas"
lang_file = "yarr.toml"

To be possible in someone's resource pack for a pirate themed game.

Rendering Module

  • Separate rendering to separate DLL
  • Backends
    • OpenGL 4.5 (Kinda)
    • OpenGL 3
    • OpenGL 1??
    • Vulkan?
    • DirectX?
  • Shader Language*
  • #20

*Shader language would translate between GLSL, whatever Vulkan uses & HLSL. It would be simple and fragile possibly but the idea is one shader file for all the renderers.

Chunk Updates, Block Updates and Rebuilding

Changes to the world should be separated into two:

  • Chunk Updates
  • Block Updates

Block updates should always lead to Chunk Updates, but Chunk Updates won't necessarily lead to Block Updates.
A block update should mark a chunk "dirty", which will lead the world to cast its' chunk updates. Duplicate block updates will only ever cause the chunk to update once.

Chunk updates should rebuild the chunk representation, and should be called anytime something in the chunk changes, be it lighting, block types, or what-have-you. Chunk updates should also mark the chunk outdated, causing the server to schedule a re-send of it.

Chunk updates can also lead to more block updates, in such a case the chunk isn't unmarked, and is left for the next tick to deal with.

Block updates should update their neighbours in-case they care about what is next to them, I.e stairs or fences or whatever.
Water/Liquid will flow on chunk updates. Water should cause block updates.

Singleplayer

Client creates a thread for the server and runs the server main loop on it, communicating with it.
Probably randomise the Port number used, like MC does. (Open To Lan maybe changes the server port, and allow a custom one?)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.