Godot-Voxel-Prototype/core.gd

126 lines
5.1 KiB
GDScript

extends Node
var chunk #noderef functions
var chunks = {} #contains all chucks, using Vector3() as keys or "id"
var chunk_size=8#16 are more common for this kind of game, but is 4X slower to update
var default_texture = load("res://res/stone.png")#used if we are unable to get the nodes tiles
var player = {name="singleplayer",object=null,inventory=["stone","dirt","grassy","water_source"],inventory_index=0}
var map = {}#contains all nodes, using Vector3() as keys or "id", contains a number/node id, strings would use too much memory
var collision_map = {}
var settings = {
full_3d_cubes=false,
update_chunk_rules=[Vector3(-1,0,0),Vector3(1,0,0),Vector3(0,0,-1),Vector3(0,0,1),Vector3(0,-1,0),Vector3(0,1,0)],
ganerate_chunk_range=4,
max_update_nodes=512,
}
var default_node_id = 7
var mapgen = {}
var current_mapgen # funcref
var register = {
nodes = {
none={id=0,name="none",drawtype="none",tiles=[]},
air={id=1,name="air",drawtype="none",tiles=[],collidable=false,solid_surface=false},
stone={id=2,name="stone",drawtype="default",tiles=[load("res://res/stone.png")]},
grassy={id=3,name="grassy",drawtype="default",tiles=[
load("res://res/grass.png"),
load("res://res/dirt.png"),
load("res://res/grass_dirt.png"),
load("res://res/grass_dirt.png"),
load("res://res/grass_dirt.png"),
load("res://res/grass_dirt.png"),
]},
dirt={id=4,name="dirt",drawtype="default",tiles=[load("res://res/dirt.png")]},
water_source={id=5,name="water_source",replaceable=true,drawtype="liquid",collidable=false,transparent=true,solid_surface=false,tiles=[load("res://res/water.png")]},
},
id = {0:"none",1:"air",2:"stone",3:"grassy",4:"dirt",5:"water_source"},
}
var default_node = {
uv = [Vector2(0,0),Vector2(0,1),Vector2(1,1),Vector2(1,0)],
dir = [Vector3(0,1,0),Vector3(0,-1,0),Vector3(1,0,0),Vector3(-1,0,0),Vector3(0,0,-1),Vector3(0,0,1)],
faces = [
[Vector3(1,0,0),Vector3(1,0,1),Vector3(0,0,1),Vector3(0,0,0)], #up y+
[Vector3(0,-1,0),Vector3(0,-1,1),Vector3(1,-1,1),Vector3(1,-1,0)], #down y-
[Vector3(1,0,0),Vector3(1,-1,0),Vector3(1,-1,1),Vector3(1,0,1)], #north x+
[Vector3(0,0,1),Vector3(0,-1,1),Vector3(0,-1,0),Vector3(0,0,0)], #south x-
[Vector3(0,0,0),Vector3(0,-1,0),Vector3(1,-1,0),Vector3(1,0,0)], #east z+
[Vector3(1,0,1),Vector3(1,-1,1),Vector3(0,-1,1),Vector3(0,0,1)], #west z-
]
}
#returns name of node you are pointing at, pos would be more usefull i think
#use the penultimate pos to get the node next to it
func pointed_at_node():
var pos = player.object.get_translation()
var aim = player.object.get_node("head/Camera").get_global_transform().basis
var hpos = player.object.get_node("head").get_translation()
for i in range(-1,-500,-1):
var p = (pos + hpos+(aim.z*Vector3(i*0.01,i*0.01,i*0.01)))#.round()
var rp = p.round()
var id = map.get(rp)
var reg = get_node_reg(id)
if reg != null and reg.get("drawtype") != "none" and reg.get("collidable") != false:
if (p.x >= rp.x-0.5 and p.x <= rp.x+0.5) and (p.y >= rp.y-0.5 and p.y <= rp.y+0.5) and (p.z >= rp.z-0.5 and p.z <= rp.z+0.5):
return reg.name
return "none"
#problity you finds a better way to use this
#but this is what i used while testing
func pointed_node_action(n):
var pos = player.object.get_translation()
var aim = player.object.get_node("head/Camera").get_global_transform().basis
var hpos = player.object.get_node("head").get_translation()
var lpos = (pos + hpos+aim.z).round()
for i in range(-1,-500,-1):
var p = (pos + hpos+(aim.z*Vector3(i*0.01,i*0.01,i*0.01)))#.round()
var rp = p.round()
var id = map.get(rp)
if id and id != 1:
if core.chunk.get_chunk_at_pos(rp):
if (p.x >= rp.x-0.5 and p.x <= rp.x+0.5) and (p.y >= rp.y-0.5 and p.y <= rp.y+0.5) and (p.z >= rp.z-0.5 and p.z <= rp.z+0.5):
var node = player.inventory[player.inventory_index] if n == 0 else "air"
var pp = rp
if n == 0:
var Name = register.id[id]
var reg = register.nodes[Name]
pp = rp if reg.get("replaceable") == true else lpos
set_node({name=node,pos=pp})
return
lpos = rp
func get_node_reg(v):#a flexible way to get node properties by pos, id or name
if v is Vector3:
v = v.round()
v = map.get(v)
elif v is String:
return register.nodes.get(v)
var n = register.id.get(v)
return register.nodes.get(n)
func get_node(pos):#returns node id
assert(typeof(pos) == TYPE_VECTOR3,"ERROR: set_node: pos required!")
return map.get(pos)
func set_node(def:Dictionary):# set node
assert(typeof(def.get("pos")) == TYPE_VECTOR3 and typeof(def.get("name")) == TYPE_STRING,"ERROR: set_node: def.pos & def.name required!")
var n = register.nodes.get(def.name)
assert(n != null,str('ERROR: set_node: "',def.name,'"', " doesn't exists"))
var rpos = def.pos.round()
map[rpos] = get_node_reg(def.name).id
#check if chunks around the node need to be updated
var cid = chunk.pos_to_chunkid(rpos)
for r in settings.update_chunk_rules.size():
var near_chunk = rpos+settings.update_chunk_rules[r]
if chunk.pos_to_chunkid(near_chunk) != cid:
chunk.update(near_chunk)
#check the chunk
chunk.update(rpos)
func inset_map_node_id(id,pos):# easyer to use
map[pos] = id