M2.3: the shared world (trees, pickups, pieces, chests, fires, doors, graves, clock on the server)
This commit is contained in:
@@ -53,6 +53,12 @@ func _give(player: Node, id: String, n: int) -> int:
|
||||
notify.emit("Inventory full")
|
||||
return got
|
||||
|
||||
## Playing on a server: changes to the island go to it (world_net.gd), and
|
||||
## come back to everyone, us included. Our own inventory and stats stay here
|
||||
## until M2.4.
|
||||
func _online() -> bool:
|
||||
return WorldNet.is_client()
|
||||
|
||||
func _in_reach(player: Node3D, target: Node3D, extra: float = 0.0) -> bool:
|
||||
return player.global_position.distance_to(target.global_position) <= REACH + 2.5 + extra
|
||||
|
||||
@@ -104,6 +110,12 @@ func pickup(player: Node3D, pickup_node: Node3D) -> bool:
|
||||
if not is_instance_valid(pickup_node) or not _in_reach(player, pickup_node):
|
||||
return false
|
||||
var id: String = pickup_node.item_id
|
||||
if _online():
|
||||
if player.inventory.space_for(id) < 1:
|
||||
notify.emit("Inventory full")
|
||||
return false
|
||||
WorldNet.take(pickup_node) # first come, first served: the server decides
|
||||
return true
|
||||
if _give(player, id, pickup_node.amount) <= 0:
|
||||
return false
|
||||
pickup_node.collected()
|
||||
@@ -123,6 +135,9 @@ func harvest_hit(player: Node3D, node: Node3D, hit_point: Vector3) -> bool:
|
||||
if not player.survival.use_stamina(6.0):
|
||||
notify.emit("Too tired")
|
||||
return false
|
||||
if _online():
|
||||
WorldNet.hit(node, float(tool.get("damage", 1.0)), hit_point)
|
||||
return true
|
||||
var drops: Dictionary = node.hit(float(tool.get("damage", 1.0)), hit_point, player.global_position)
|
||||
for id in drops:
|
||||
_give(player, id, int(drops[id]))
|
||||
@@ -145,6 +160,9 @@ func place(player: Node3D, slot: int, xf: Transform3D, world: Node3D) -> bool:
|
||||
notify.emit("Can't place that here")
|
||||
return false
|
||||
player.inventory.take_from(slot, 1)
|
||||
if _online():
|
||||
WorldNet.place(id, xf) # (given back if the server says no)
|
||||
return true
|
||||
world.spawn_piece(def, xf)
|
||||
return true
|
||||
|
||||
@@ -165,6 +183,9 @@ func dismantle(player: Node3D, piece: Node3D) -> bool:
|
||||
if player.inventory.space_for(piece.item_id) < 1:
|
||||
notify.emit("Inventory full")
|
||||
return false
|
||||
if _online():
|
||||
WorldNet.dismantle(piece)
|
||||
return true
|
||||
_give(player, piece.item_id, 1)
|
||||
piece.get_parent().get_parent().remove_piece(piece, player)
|
||||
return true
|
||||
@@ -172,6 +193,9 @@ func dismantle(player: Node3D, piece: Node3D) -> bool:
|
||||
func toggle_door(player: Node3D, door: Node3D) -> bool:
|
||||
if not is_instance_valid(door) or not _in_reach(player, door, 1.0):
|
||||
return false
|
||||
if _online():
|
||||
WorldNet.door(door)
|
||||
return true
|
||||
door.set_open(not door.open)
|
||||
return true
|
||||
|
||||
@@ -353,6 +377,9 @@ func take_off(player: Node3D) -> bool:
|
||||
func forage(player: Node3D, bush: Node3D) -> bool:
|
||||
if not is_instance_valid(bush) or not _in_reach(player, bush) or not bush.ripe():
|
||||
return false
|
||||
if _online():
|
||||
WorldNet.forage(bush)
|
||||
return true
|
||||
var got: Dictionary = bush.harvest()
|
||||
for id in got:
|
||||
_give(player, id, int(got[id]))
|
||||
@@ -385,7 +412,10 @@ func add_fuel(player: Node3D, fire: Node3D) -> bool:
|
||||
for id in ["wood", "stick", "fiber"]:
|
||||
if player.inventory.count(id) > 0:
|
||||
player.inventory.remove(id, 1)
|
||||
fire.add_fuel(float(ItemDB.get_item(id).get("fuel", 10)))
|
||||
if _online():
|
||||
WorldNet.fuel(fire, id)
|
||||
else:
|
||||
fire.add_fuel(float(ItemDB.get_item(id).get("fuel", 10)))
|
||||
notify.emit("Added %s to the fire" % ItemDB.item_name(id).to_lower())
|
||||
return true
|
||||
notify.emit("Nothing to burn (wood or sticks)")
|
||||
@@ -396,4 +426,14 @@ func add_fuel(player: Node3D, fire: Node3D) -> bool:
|
||||
func transfer(player: Node3D, from: Inventory, slot: int, to: Inventory, container: Node3D = null) -> void:
|
||||
if container != null and not _in_reach(player, container, 1.0):
|
||||
return
|
||||
if _online() and container != null:
|
||||
var s = from.get_slot(slot)
|
||||
if s == null:
|
||||
return
|
||||
if from == player.inventory:
|
||||
from.set_slot(slot, null)
|
||||
WorldNet.chest_put(container, s) # what doesn't fit comes back
|
||||
else:
|
||||
WorldNet.chest_take(container, slot, to.space_for(s.id))
|
||||
return
|
||||
from.quick_move(slot, to)
|
||||
|
||||
@@ -58,6 +58,22 @@ func create_world(world_name: String, seed: int) -> String:
|
||||
})
|
||||
return id
|
||||
|
||||
## The world slot called exactly `id` (a server's world), made with `seed` if
|
||||
## it doesn't exist yet. An existing world keeps its own seed.
|
||||
func open_or_create(id: String, seed: int) -> String:
|
||||
if not read_meta(id).is_empty():
|
||||
var had := int(read_meta(id).get("seed", seed))
|
||||
if had != seed:
|
||||
print("Saves: world '%s' was made with seed %d, so it keeps it (the config says %d)" % [id, had, seed])
|
||||
return id
|
||||
DirAccess.make_dir_recursive_absolute(_dir(id))
|
||||
var now := Time.get_unix_time_from_system()
|
||||
_write_json(_dir(id).path_join("meta.json"), {
|
||||
"name": id, "seed": seed, "created": now, "last_played": now,
|
||||
"play_time": 0.0, "version": VERSION,
|
||||
})
|
||||
return id
|
||||
|
||||
func delete_world(id: String) -> void:
|
||||
var dir := _dir(id)
|
||||
var d := DirAccess.open(dir)
|
||||
|
||||
Reference in New Issue
Block a user