126 lines
5.1 KiB
GDScript
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
|