@ -9,6 +9,7 @@ static func lookup(id: int) -> Shape:
static var EMPTY : Shape
static var EMPTY : Shape
static var FULL : Shape
static var FULL : Shape
## Default shape to return when chunk or layer is not found.
static var DEFAULT : Shape
static var DEFAULT : Shape
var id : int
var id : int
@ -34,12 +35,14 @@ func _init(base: Base, mirror: bool, angle: int, shape: Shape2D, points: PackedV
uvs . append ( ( Vector2 . ONE / 2 ) + point )
uvs . append ( ( Vector2 . ONE / 2 ) + point )
## Represents a base shape, before it has been rotated and mirrored
## (if applicable) to create a number of variants based on that shape.
class Base :
class Base :
static var EMPTY : = Base . new ( " empty " )
static var EMPTY : = Base . new ( " empty " )
static var FULL : = Base . new ( " full " , _rect ( ) )
static var FULL : = Base . new ( " full " , _rect ( ) )
static var HALF : = Base . new ( " half " , [ 0 , 1 , 2 , 1 , 2 , 2 , 0 , 2 ] , true )
static var HALF : = Base . new ( " half " , [ 0 , 1 , 2 , 1 , 2 , 2 , 0 , 2 ] , true )
static var SLOPE : = Base . new ( " slope " , [ 0 , 1 , 1 , 0 , 1 , 1 ] , true )
static var SLOPE : = Base . new ( " slope " , [ 0 , 1 , 1 , 0 , 1 , 1 ] , true )
static var HALF_SLOPE : = Base . new ( " half_slope " , [ 0 , 2 , 1 , 0 , 2 , 2 ] , true , true )
static var HALF_SLOPE : = Base . new ( " half_slope " , [ 0 , 2 , 2 , 1 , 2 , 2 ] , true , true )
static var HALF_SLOPE_BIG : = Base . new ( " half_slope_big " , [ 0 , 1 , 2 , 0 , 2 , 2 , 0 , 2 ] , true , true )
static var HALF_SLOPE_BIG : = Base . new ( " half_slope_big " , [ 0 , 1 , 2 , 0 , 2 , 2 , 0 , 2 ] , true , true )
static func _static_init ( ) - > void :
static func _static_init ( ) - > void :
@ -60,28 +63,25 @@ class Base:
shape = _rotate ( shape ) # rotate by 90 degrees (swap x and y components)
shape = _rotate ( shape ) # rotate by 90 degrees (swap x and y components)
variants . append ( Shape . new ( self , false , 0 , shape , _points ( shape ) ) )
variants . append ( Shape . new ( self , false , 0 , shape , _points ( shape ) ) )
elif shape is Array :
elif shape is Array :
# Convert points (pairs of ints) in array to convex shape.
# Convert points (pairs of `int`s) in `Array` to convex shape.
var factor : = float ( shape . max ( ) )
var factor : = float ( shape . max ( ) )
var points : = PackedVector2Array ( )
var points_orig : = PackedVector2Array ( ) # untransformed points
for i in range ( 0 , shape . size ( ) , 2 ) :
for i in range ( 0 , shape . size ( ) , 2 ) :
var point : = Vector2 ( shape [ i ] / factor , shape [ i + 1 ] / factor )
var point : = Vector2 ( shape [ i ] / factor , shape [ i + 1 ] / factor )
points . append ( point - ( Vector2 . ONE / 2 ) ) # ensure shape is centered
points_orig . append ( point - ( Vector2 . ONE / 2 ) ) # ensure shape is centered
# Add variations of the shape (rotated, mirrored), including the standard shape.
# Add variations of the shape (rotated, mirrored), including the standard shape.
for mirror in [ false , true ] if mirrored else [ false ] :
for mirror in [ false , true ] if mirrored else [ false ] :
if mirror :
# Mirror (flip) points along the X axis.
points = points . duplicate ( )
for i in points . size ( ) :
points [ i ] = points [ i ] * Transform2D . FLIP_X
for angle in [ 0 , 90 , 180 , 270 ] if rotated else [ 0 ] :
for angle in [ 0 , 90 , 180 , 270 ] if rotated else [ 0 ] :
if angle != 0 :
var points : = points_orig . duplicate ( ) # transformed points
# Rotate points around the center.
# Technically we could skip `duplicate()` if not mirrored and not rotated, but eh.
if mirror : # Mirror (flip) points along the X axis.
for i in points . size ( ) : points [ i ] *= Transform2D . FLIP_X
if angle != 0 : # Rotate points around the center.
var transform : = Transform2D ( deg_to_rad ( angle ) , Vector2 . ZERO )
var transform : = Transform2D ( deg_to_rad ( angle ) , Vector2 . ZERO )
points = points . duplicate ( )
for i in points . size ( ) : points [ i ] *= transform
for i in points . size ( ) :
points [ i ] = points [ i ] * transform
var shape_points : PackedVector2Array
var shape_points : PackedVector2Array
for point in points : shape_points . append ( point * Block . SIZE )
for point in points : shape_points . append ( point * Block . SIZE )
@ -130,16 +130,17 @@ class Layer extends StaticBody2D:
@ rpc ( " reliable " )
@ rpc ( " reliable " )
func set_id_at ( pos : Vector2i , id : int ) - > void :
func set_id_at ( pos : Vector2i , id : int ) - > void :
var index : = Chunk . array_index ( pos )
var index : = Chunk . array_index ( pos )
if data [ index ] != id :
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
# 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.
# Send change to every player tracking this chunk.
if multiplayer . is_server ( ) :
for player in chunk . get_players_tracking ( ) :
for player in chunk . get_players_tracking ( ) :
if player . network . is_local : continue # skip server player
if player . network . is_local : continue # skip server player
set_id_at . rpc_id ( player . network . peer_id , pos , id )
set_id_at . rpc_id ( player . network . peer_id , pos , id )
func _ready ( ) - > void :
func _ready ( ) - > void :
@ -155,14 +156,12 @@ class Layer extends StaticBody2D:
if child is CollisionShape2D :
if child is CollisionShape2D :
child . queue_free ( )
child . queue_free ( )
for x in Chunk . SIZE :
for pos in BlockRegion . LOCAL_CHUNK :
for y in Chunk . SIZE :
var shape : = get_at ( pos )
var pos : = Vector2i ( x , y )
if shape . shape == null : continue
var shape : = get_at ( pos )
if shape . shape == null : continue
var shape2d : = CollisionShape2D . new ( )
shape2d . name = " Block %s " % pos
var shape2d : = CollisionShape2D . new ( )
shape2d . position = ( Vector2 ( pos ) + ( Vector2 . ONE / 2 ) ) * Block . SIZE - CHUNK_HALF_SIZE
shape2d . name = " Block %s " % pos
shape2d . shape = shape . shape
shape2d . position = ( Vector2 ( pos ) + ( Vector2 . ONE / 2 ) ) * Block . SIZE - CHUNK_HALF_SIZE
add_child ( shape2d )
shape2d . shape = shape . shape
add_child ( shape2d )