Block worlds
A block world is terrain made of 1 m blocks. Players dig with the left mouse button and build with the right one; GAMPEON draws the world, sends changes to everyone nearby and saves them. Your scripts decide the game: what digging gives, what players may place, prices, recipes, rules.
Every server can have one block world. You switch it on from a server script:
EnableBlockWorld({ seed = 20261106, -- the terrain: same seed, same world save = 'main', -- keep changed blocks between restarts (Saved/VoxelWorlds/main.gpvox) zones = { -- a flat area without blocks, for example a city. Nobody digs or builds here, scripts neither. { minX = -48, minY = -48, maxX = 48, maxY = 48, groundZ = 8 }, },})Call it when your resource starts, before players spawn. Players then spawn on the surface, in the middle of the first zone (or at 0, 0 without zones). Calling it again with the same options does nothing, so restarting your resource is safe. Other options need a server restart. Around each zone, the terrain slopes smoothly into the flat ground over blend blocks (default 24).
Inside a zone, a hidden foundation that nobody can dig ends at groundZ - 2, in case someone falls through the city. If your own map has water or low ground inside the zone, set floorZ lower, for example below the sea floor, so the foundation does not cover it: { minX = -340, minY = -350, maxX = 280, maxY = 330, groundZ = 0, floorZ = -14 }. Players spawn at groundZ in a zone. See Bring your own map.
Coordinates
Section titled “Coordinates”Blocks have whole-number coordinates, and 1 block is 1 m, like the meters of GetEntityCoords. Block (x, y, z) fills the space from x to x + 1 and so on; z is up. Decimals are rounded down, so GetBlock(GetEntityCoords(ped)) is the block the feet of a character are in.
The world reaches from -4096 to 4095 on x and y and from -64 to 63 on z. The bottom layer cannot change, so nobody falls out of the world.
Blocks
Section titled “Blocks”GetBlockTypes() lists all blocks. The list only grows.
| Block | Players can dig | Players can place |
|---|---|---|
turf, soil, stone, sand, snow |
yes | yes |
planks, brick, clay |
yes | yes |
charstone, copper_vein, iron_vein, crystal |
yes | no (ores) |
deepstone |
no | no |
Scripts can set any block with SetBlock, also ores.
Digging and building
Section titled “Digging and building”Players use built-in controls, you do not write input code:
| Input | Action |
|---|---|
| Left mouse button | Dig the block under the crosshair (hold to repeat) |
| Right mouse button | Place the selected hotbar block on the side the crosshair points at |
| Mouse wheel, 1 to 9 | Pick a hotbar slot |
The hotbar comes from your client script. Without one, players can only dig.
-- Show what the player owns, with counts. The server still decides in blockPlace.RegisterNetEvent('mygame:inventory', function(inv) SetBlockHotbar({ { block = 'stone', count = inv.stone or 0 }, { block = 'planks', count = inv.planks or 0 }, })end)Every action goes to the server first. The server checks reach (6 m from the eyes), speed (10 actions per second), zones, block type, free space, a solid neighbor and that no character stands in the way. Then it asks your scripts:
AddEventHandler('blockBreak', function(x, y, z, block) -- source is the player. CancelEvent keeps the block. if block == 'crystal' and not HasPickaxe(source) then CancelEvent() return end AddItem(source, block, 1)end)
AddEventHandler('blockPlace', function(x, y, z, block) if not RemoveItem(source, block, 1) then CancelEvent() -- the player sees the block disappear again endend)Call CancelEvent before any Wait. After the change, blockChanged arrives in the next server tick, for players and for SetBlock:
AddEventHandler('blockChanged', function(x, y, z, oldBlock, newBlock, player) -- player is 0 when a script changed itend)Your own interface
Section titled “Your own interface”SetBlockHudVisible(false)hides the built-in hotbar and the outline, for example when you draw your own hotbar with a web interface. The controls keep working;GetBlockHotbarSlot()and the eventblockHotbarSelecttell you the selection.SetBlockControlsEnabled(false)stops digging and building, for example while a menu is open. The controls also pause on their own while the mouse cursor is visible.GetBlockTarget()returns the block under the crosshair and the side it points at, ornil.
Saving
Section titled “Saving”With save, the server stores changed blocks and loads them on the next start. Unchanged terrain is never stored; it comes from the seed. If you change the seed but keep the save name, the server moves the old save aside (<save>.seed<old>.gpvox) and starts a new world.
Before the map has loaded (while your resource starts), GetBlock shows the generated terrain and your own SetBlock calls. Saved changes appear once the world is there.
Player data such as inventories is yours to save, for example with SaveResourceFile or the database.
Test without the game
Section titled “Test without the game”gampeon-server has the same block world, without graphics. It keeps changed blocks only while it runs; save works on the game server. Fake players dig and build like with the mouse:
| Command | Effect |
|---|---|
gp_fakeplayer break <id> [x y z] |
Dig, by default the block straight below the player’s eyes |
gp_fakeplayer place <id> [x y z [block]] |
Place, by default the selected hotbar block |
gp_fakeplayer slot <id> <n> |
Pick hotbar slot n |
gp_block <x> <y> <z> |
Print the block and the surface height there |
See Test without the game for the rest.
Not there yet
Section titled “Not there yet”- Your own block types with your own colors or textures.
- Water and other liquids, falling blocks, blocks that give light.
- More than one block world per server.
All functions with their arguments are in the Lua API reference.