Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions assets/cubyz/blocks/bad_respawn_anchor.zig.zon
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
.{
.tags = .{.mineable},
.blockHealth = 10,
.drops = .{
.{.items = .{.auto}},
},
.model = "cubyz:cube",
.rotation = "cubyz:stairs",
.texture = "cubyz:bad_respawn_anchor",
.blockEntity = "cubyz:respawn_anchor",
.onInteract = .{
.type = .set_spawn,
.respawnEffeciency = 0.1,
},
}
14 changes: 14 additions & 0 deletions assets/cubyz/blocks/respawn_anchor.zig.zon
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.{
.tags = .{.mineable},
.blockHealth = 10,
.drops = .{
.{.items = .{.auto}},
},
.model = "cubyz:cube",
.rotation = "cubyz:stairs",
.texture = "cubyz:respawn_anchor",
.blockEntity = "cubyz:respawn_anchor",
.onInteract = .{
.type = .set_spawn,
},
}
Binary file added assets/cubyz/blocks/textures/bad_respawn_anchor.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/cubyz/blocks/textures/respawn_anchor.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
22 changes: 22 additions & 0 deletions src/block_entity.zig
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,28 @@ pub const BlockEntityTypes = struct { // MARK: BlockEntityTypes
}
}
};

pub const @"cubyz:respawn_anchor" = struct { // MARK: cubyz:respawn_anchor

pub fn init() void {}
pub fn deinit() void {}
pub fn reset() void {}

pub fn onLoadClient(_: Vec3i, _: *Chunk, _: *BinaryReader) ErrorSet!void {}
pub fn onUnloadClient(_: BlockEntity) void {}
pub fn onLoadServer(_: Vec3i, _: *Chunk, _: *BinaryReader) ErrorSet!void {}

pub fn onUnloadServer(_: BlockEntity) void {}
pub fn onStoreServerToDisk(_: BlockEntity, _: *BinaryWriter) void {}
pub fn onStoreServerToClient(_: BlockEntity, _: *BinaryWriter) void {}

pub fn updateClientData(_: Vec3i, _: *Chunk, _: UpdateEvent) ErrorSet!void {}
pub fn updateServerData(_: Vec3i, _: *Chunk, _: UpdateEvent) ErrorSet!void {}
pub fn getServerToClientData(_: Vec3i, _: *Chunk, _: *BinaryWriter) void {}
pub fn getClientToServerData(_: Vec3i, _: *Chunk, _: *BinaryWriter) void {}

pub fn renderAll(_: Vec3f) void {}
};
};

var blockyEntityTypes: std.StringHashMapUnmanaged(BlockEntityType) = .{};
Expand Down
1 change: 1 addition & 0 deletions src/callbacks/block/client/_list.zig
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub const edit_sign = @import("edit_sign.zig");
pub const open_chest = @import("open_chest.zig");
pub const open_window = @import("open_window.zig");
pub const set_spawn = @import("set_spawn.zig");
22 changes: 22 additions & 0 deletions src/callbacks/block/client/set_spawn.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const std = @import("std");

const main = @import("main");
const Block = main.blocks.Block;
const vec = main.vec;
const Vec3i = vec.Vec3i;
const ZonElement = main.ZonElement;

respawnEffeciency: f32,

pub fn init(zon: ZonElement, _: main.callbacks.Creator) ?*anyopaque {
const result = main.worldArena.create(@This());
result.* = .{
.respawnEffeciency = zon.get(f32, "respawnEffeciency") orelse 1.0,
};
return result;
}

pub fn run(self: *@This(), params: main.callbacks.ClientBlockCallback.Params) main.callbacks.Result {
main.sync.setSpawn(params.blockPos, self.respawnEffeciency, .client, main.game.Player.id);
return .handled;
}
4 changes: 2 additions & 2 deletions src/game.zig
Original file line number Diff line number Diff line change
Expand Up @@ -200,11 +200,11 @@ pub const Player = struct { // MARK: Player
inventory.placeBlock(selectedSlot);
}

pub fn kill(spawnPos: Vec3d) void {
pub fn kill(spawnPos: Vec3d, respawnEffeciency: f32) void {
Player.super.pos = spawnPos;
Player.super.vel = .{0, 0, 0};

Player.super.health = Player.super.maxHealth;
Player.super.health = std.math.clamp(Player.super.maxHealth*respawnEffeciency, 0, Player.super.maxHealth);
Player.super.energy = Player.super.maxEnergy;

Player.eye = .{};
Expand Down
25 changes: 24 additions & 1 deletion src/server/server.zig
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ pub const User = struct { // MARK: User
lastPos: Vec3i = @splat(0),
gamemode: std.atomic.Value(main.game.Gamemode) = .init(.creative),
spawnPos: ?Vec3d = null,
respawnEffeciency: ?f32 = null,
worldEditData: WorldEditData = undefined,

playerIndex: PlayerIndex = undefined,
Expand Down Expand Up @@ -544,7 +545,29 @@ pub const User = struct { // MARK: User
}

pub fn getSpawnPos(user: *User) Vec3d {
return user.spawnPos orelse @floatFromInt(main.server.world.?.spawn);
const defaultSpawn = @as(Vec3d, @floatFromInt(main.server.world.?.spawn));
if (user.spawnPos == null) user.spawnPos = @floatFromInt(main.server.world.?.spawn);
const userSpawn = @as(Vec3i, @intFromFloat(user.spawnPos orelse defaultSpawn));
const targetBlock = main.game.getBlockWithSide(main.sync.Side.server, userSpawn[0], userSpawn[1], userSpawn[2]) orelse return defaultSpawn;

if (targetBlock.blockEntity() == null) {
user.sendRawMessage("Could Not Find Spawnpoint, Teleporting back to world spawn");
return defaultSpawn;
}
if (!std.mem.eql(u8, targetBlock.blockEntity().?.id, "cubyz:respawn_anchor")) user.spawnPos = defaultSpawn;
return user.spawnPos orelse defaultSpawn;
}

pub fn getRespawnEffeciency(user: *User) f32 {
const defaultSpawn = @as(Vec3d, @floatFromInt(main.server.world.?.spawn));
const defaultRespawnEffeciency = main.server.world.?.respawnEffeciency;
if (user.spawnPos == null) user.spawnPos = @floatFromInt(main.server.world.?.spawn);
const userSpawn = @as(Vec3i, @intFromFloat(user.spawnPos orelse defaultSpawn));
const targetBlock = main.game.getBlockWithSide(main.sync.Side.server, userSpawn[0], userSpawn[1], userSpawn[2]) orelse return defaultRespawnEffeciency;

if (targetBlock.blockEntity() == null) return defaultRespawnEffeciency;
if (!std.mem.eql(u8, targetBlock.blockEntity().?.id, "cubyz:respawn_anchor")) user.respawnEffeciency = defaultRespawnEffeciency;
return user.respawnEffeciency orelse defaultRespawnEffeciency;
}

pub fn format(user: User, writer: *std.Io.Writer) std.Io.Writer.Error!void {
Expand Down
3 changes: 3 additions & 0 deletions src/server/world.zig
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,7 @@ pub const ServerWorld = struct { // MARK: ServerWorld
path: []const u8,
name: []const u8 = &.{},
spawn: Vec3i = undefined,
respawnEffeciency: f32 = undefined,

mutex: main.utils.Mutex = .{},

Expand Down Expand Up @@ -647,6 +648,7 @@ pub const ServerWorld = struct { // MARK: ServerWorld
self.doGameTimeCycle = worldData.get(bool, "doGameTimeCycle") orelse true;
self.gameTime = worldData.get(i64, "gameTime") orelse 0;
self.spawn = worldData.get(Vec3i, "spawn") orelse .{0, 0, 0};
self.respawnEffeciency = worldData.get(f32, "respawnEffeciency") orelse 1.0;
self.biomeChecksum = worldData.get(i64, "biomeChecksum") orelse 0;
self.name = main.globalAllocator.dupe(u8, worldData.get([]const u8, "name") orelse self.path);
self.tickSpeed = .init(worldData.get(u32, "tickSpeed") orelse 12);
Expand All @@ -661,6 +663,7 @@ pub const ServerWorld = struct { // MARK: ServerWorld
worldData.put("doGameTimeCycle", self.doGameTimeCycle);
worldData.put("gameTime", self.gameTime);
worldData.put("spawn", self.spawn);
worldData.put("respawnEffeciency", self.respawnEffeciency);
worldData.put("biomeChecksum", self.biomeChecksum);
worldData.put("name", self.name);
worldData.put("lastUsedTime", std.Io.Clock.Timestamp.now(main.io, .real).raw.toMilliseconds());
Expand Down
60 changes: 59 additions & 1 deletion src/sync.zig
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,15 @@ pub fn addHealth(health: f32, cause: main.game.DamageType, side: Side, entity: m
}
}

pub fn setSpawn(position: Vec3i, respawnEffeciency: f32, side: Side, entity: main.entity.Entity) void {
threadContext.assertCorrectContext(side);
if (side == .client) {
client.executeCommand(.{.setSpawn = .{.target = entity, .position = position, .respawnEffeciency = respawnEffeciency}});
} else {
server.executeCommand(.{.setSpawn = .{.target = entity, .position = position, .respawnEffeciency = respawnEffeciency}}, null);
}
}

pub fn setGamemode(user: ?*main.server.User, gamemode: Gamemode) void {
if (user == null) {
client.setGamemode(gamemode);
Expand Down Expand Up @@ -241,6 +250,7 @@ pub const Command = struct { // MARK: Command
updateBlock = 9,
addHealth = 10,
chatCommand = 12,
setSpawn = 18,
};
pub const Payload = union(PayloadType) {
open: Open,
Expand All @@ -261,6 +271,7 @@ pub const Command = struct { // MARK: Command
updateBlock: UpdateBlock,
addHealth: AddHealth,
chatCommand: ChatCommand,
setSpawn: SetSpawn,
};

const BaseOperationType = enum(u8) {
Expand Down Expand Up @@ -355,6 +366,7 @@ pub const Command = struct { // MARK: Command
kill: struct {
target: ?*main.server.User,
spawnPoint: Vec3d,
respawnEffeciency: f32,
},
energy: struct {
target: ?*main.server.User,
Expand Down Expand Up @@ -401,7 +413,7 @@ pub const Command = struct { // MARK: Command
main.game.Player.super.health = std.math.clamp(main.game.Player.super.health + health.health, 0, main.game.Player.super.maxHealth);
},
.kill => |kill| {
main.game.Player.kill(kill.spawnPoint);
main.game.Player.kill(kill.spawnPoint, kill.respawnEffeciency);
},
.energy => |energy| {
main.game.Player.super.energy = std.math.clamp(main.game.Player.super.energy + energy.energy, 0, main.game.Player.super.maxEnergy);
Expand Down Expand Up @@ -472,6 +484,7 @@ pub const Command = struct { // MARK: Command
return .{.kill = .{
.target = null,
.spawnPoint = try reader.readVec(Vec3d),
.respawnEffeciency = try reader.readFloat(f32),
}};
},
.energy => {
Expand Down Expand Up @@ -507,6 +520,7 @@ pub const Command = struct { // MARK: Command
},
.kill => |kill| {
writer.writeVec(Vec3d, kill.spawnPoint);
writer.writeFloat(f32, kill.respawnEffeciency);
},
.energy => |energy| {
writer.writeFloat(f32, energy.energy);
Expand Down Expand Up @@ -788,6 +802,7 @@ pub const Command = struct { // MARK: Command
self.syncOperations.append(allocator, .{.kill = .{
.target = info.target.?,
.spawnPoint = info.target.?.getSpawnPos(),
.respawnEffeciency = info.target.?.getRespawnEffeciency(),
}});
} else {
self.syncOperations.append(allocator, .{.health = .{
Expand Down Expand Up @@ -1761,6 +1776,49 @@ pub const Command = struct { // MARK: Command
};
}
};

const SetSpawn = struct { // MARK: SetSpawn
target: main.entity.Entity,
position: Vec3i,
respawnEffeciency: f32,

pub fn run(self: SetSpawn, ctx: Context) error{serverFailure}!void {
var target: ?*main.server.User = null;

if (ctx.side == .server) {
const userList = main.server.getUserList(main.stackAllocator);
defer main.stackAllocator.free(userList);
for (userList) |user| {
if (user.id == self.target) {
target = user;
break;
}
}

if (target == null) return error.serverFailure;

target.?.spawnPos = @floatFromInt(self.position);
target.?.respawnEffeciency = self.respawnEffeciency;
target.?.sendRawMessage("Set New SpawnPoint");
}
}

fn serialize(self: SetSpawn, writer: *BinaryWriter) void {
writer.writeEnum(main.entity.Entity, self.target);
writer.writeVec(Vec3i, self.position);
writer.writeFloat(f32, self.respawnEffeciency);
}

fn deserialize(reader: *BinaryReader, _: Side, user: ?*main.server.User) !SetSpawn {
const result: SetSpawn = .{
.target = try reader.readEnum(main.entity.Entity),
.position = try reader.readVec(Vec3i),
.respawnEffeciency = try reader.readFloat(f32),
};
if (user.?.id != result.target) return error.Invalid;
return result;
}
};
};

pub threadlocal var threadContext: ThreadContext = .other;
Expand Down
Loading