You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
95 lines
2.7 KiB
95 lines
2.7 KiB
class_name Matter |
|
|
|
static var REGISTRY := Registry.new() |
|
|
|
static var NONE := Matter.new("none") |
|
static var PLASTIC := Matter.new("plastic") |
|
|
|
## Default matter to return when chunk or layer is not found. |
|
static var DEFAULT := NONE |
|
|
|
var id : int |
|
var name : String |
|
|
|
func _init(name: String) -> void: |
|
REGISTRY.add(name, self) |
|
|
|
class Layer extends MeshInstance2D: |
|
var data: PackedByteArray |
|
|
|
var chunk: Chunk: |
|
get: return get_parent() |
|
|
|
func _init() -> void: |
|
data.resize(Chunk.SIZE * Chunk.SIZE) |
|
texture = preload("res://world/blocks/plastic.png") |
|
|
|
static func load(buffer: StreamBuffer) -> Layer: |
|
var result := Layer.new() |
|
buffer.read_raw_buffer_into(result.data) |
|
return result |
|
|
|
func save(buffer: StreamBuffer) -> void: |
|
buffer.write_raw_buffer(data) |
|
|
|
func get_at(pos: Vector2i) -> Matter: |
|
var index := Chunk.array_index(pos) |
|
var id := data[index] |
|
return Matter.REGISTRY.lookup_by_id(id) |
|
|
|
func set_at(pos: Vector2i, value: Matter) -> void: |
|
set_id_at(pos, value.id) |
|
@rpc("reliable") |
|
func set_id_at(pos: Vector2i, id: int) -> void: |
|
var index := Chunk.array_index(pos) |
|
if data[index] == id: return |
|
|
|
# TODO: Keep track of how many non-air blocks are present, to allow for cleaning empty chunks. |
|
data[index] = id |
|
chunk.dirty = true |
|
|
|
if multiplayer.is_server(): |
|
# Send change to every player tracking this chunk. |
|
for player in chunk.get_players_tracking(): |
|
if player.network.is_local: continue # skip server player |
|
set_id_at.rpc_id(player.network.peer_id, pos, id) |
|
|
|
|
|
func _ready() -> void: |
|
chunk.clean.connect(_update_mesh) |
|
_update_mesh() |
|
|
|
func _update_mesh() -> void: |
|
const CHUNK_HALF_SIZE := (Vector2.ONE * Chunk.SIZE * Block.SIZE) / 2 |
|
|
|
var any_blocks := false |
|
var m := ImmediateMesh.new() |
|
m.surface_begin(Mesh.PRIMITIVE_TRIANGLES) |
|
|
|
var shapes: Shape.Layer = chunk.get_layer_or_null(Shape) |
|
if shapes: # Should exist, but let's sanity check. |
|
for pos in BlockRegion.LOCAL_CHUNK: |
|
var offset := (Vector2.ONE / 2) + Vector2(pos) |
|
|
|
# TODO: Support different matter. |
|
# var matter := get_at(pos) |
|
var shape := shapes.get_at(pos) |
|
if shape.points.is_empty(): continue |
|
any_blocks = true |
|
|
|
for i in range(2, shape.points.size()): |
|
var uv0 := shape.uvs[0 ] |
|
var uv1 := shape.uvs[i-1] |
|
var uv2 := shape.uvs[i ] |
|
var p0 := (offset + shape.points[0 ]) * Block.SIZE - CHUNK_HALF_SIZE |
|
var p1 := (offset + shape.points[i-1]) * Block.SIZE - CHUNK_HALF_SIZE |
|
var p2 := (offset + shape.points[i ]) * Block.SIZE - CHUNK_HALF_SIZE |
|
m.surface_set_uv(uv0); m.surface_add_vertex_2d(p0) |
|
m.surface_set_uv(uv1); m.surface_add_vertex_2d(p1) |
|
m.surface_set_uv(uv2); m.surface_add_vertex_2d(p2) |
|
|
|
if any_blocks: |
|
m.surface_end() |
|
mesh = m |
|
else: |
|
mesh = null
|
|
|