mirror of
https://github.com/PixelGuys/Cubyz.git
synced 2025-08-03 11:17:05 -04:00
Modernize genericUpdate
protocol (#1257)
* Modernize genericUpdate protocol * Do not complicate sendGamemode * Apply review change requests * Yeet cure * Rename to biomesByIndex * Update src/network.zig Co-authored-by: IntegratedQuantum <43880493+IntegratedQuantum@users.noreply.github.com> * Use @typeInfo(T).vector * Update src/network.zig Co-authored-by: IntegratedQuantum <43880493+IntegratedQuantum@users.noreply.github.com> * Undo blind remove of TODO * Update src/server/terrain/biomes.zig Co-authored-by: IntegratedQuantum <43880493+IntegratedQuantum@users.noreply.github.com> * Remove defaultIndex argument from getByIndex * Make biomesByIndex a ListUnmanaged --------- Co-authored-by: IntegratedQuantum <43880493+IntegratedQuantum@users.noreply.github.com>
This commit is contained in:
parent
098115ad53
commit
92fcd10069
116
src/network.zig
116
src/network.zig
@ -974,15 +974,13 @@ pub const Protocols = struct {
|
||||
pub const genericUpdate = struct {
|
||||
pub const id: u8 = 9;
|
||||
pub const asynchronous = false;
|
||||
const type_gamemode: u8 = 0;
|
||||
const type_teleport: u8 = 1;
|
||||
const type_cure: u8 = 2;
|
||||
const type_worldEditPos: u8 = 3;
|
||||
const type_reserved3: u8 = 4;
|
||||
const type_reserved4: u8 = 5;
|
||||
const type_reserved5: u8 = 6;
|
||||
const type_reserved6: u8 = 7;
|
||||
const type_timeAndBiome: u8 = 8;
|
||||
|
||||
const UpdateType = enum(u8) {
|
||||
gamemode = 0,
|
||||
teleport = 1,
|
||||
worldEditPos = 2,
|
||||
timeAndBiome = 3,
|
||||
};
|
||||
|
||||
const WorldEditPosition = enum(u2) {
|
||||
selectedPos1 = 0,
|
||||
@ -991,30 +989,19 @@ pub const Protocols = struct {
|
||||
};
|
||||
|
||||
fn receive(conn: *Connection, reader: *utils.BinaryReader) !void {
|
||||
switch(try reader.readInt(u8)) {
|
||||
type_gamemode => {
|
||||
switch(try reader.readEnum(UpdateType)) {
|
||||
.gamemode => {
|
||||
if(conn.user != null) return error.InvalidPacket;
|
||||
main.items.Inventory.Sync.setGamemode(null, try reader.readEnum(main.game.Gamemode));
|
||||
},
|
||||
type_teleport => {
|
||||
game.Player.setPosBlocking(Vec3d{
|
||||
@bitCast(try reader.readInt(u64)),
|
||||
@bitCast(try reader.readInt(u64)),
|
||||
@bitCast(try reader.readInt(u64)),
|
||||
});
|
||||
.teleport => {
|
||||
game.Player.setPosBlocking(try reader.readVec(Vec3d));
|
||||
},
|
||||
type_cure => {
|
||||
// TODO: health and hunger
|
||||
},
|
||||
type_worldEditPos => {
|
||||
.worldEditPos => {
|
||||
const typ = try reader.readEnum(WorldEditPosition);
|
||||
switch(typ) {
|
||||
.selectedPos1, .selectedPos2 => {
|
||||
const pos = Vec3i{
|
||||
try reader.readInt(i32),
|
||||
try reader.readInt(i32),
|
||||
try reader.readInt(i32),
|
||||
};
|
||||
const pos = try reader.readVec(Vec3i);
|
||||
switch(typ) {
|
||||
.selectedPos1 => game.Player.selectionPosition1 = pos,
|
||||
.selectedPos2 => game.Player.selectionPosition2 = pos,
|
||||
@ -1027,15 +1014,11 @@ pub const Protocols = struct {
|
||||
},
|
||||
}
|
||||
},
|
||||
type_reserved3 => {},
|
||||
type_reserved4 => {},
|
||||
type_reserved5 => {},
|
||||
type_reserved6 => {},
|
||||
type_timeAndBiome => {
|
||||
.timeAndBiome => {
|
||||
if(conn.manager.world) |world| {
|
||||
const zon = ZonElement.parseFromString(main.stackAllocator, null, reader.remaining);
|
||||
defer zon.deinit(main.stackAllocator);
|
||||
const expectedTime = zon.get(i64, "time", 0);
|
||||
const expectedTime = try reader.readInt(i64);
|
||||
const biomeId = try reader.readInt(u32);
|
||||
|
||||
var curTime = world.gameTime.load(.monotonic);
|
||||
if(@abs(curTime -% expectedTime) >= 10) {
|
||||
world.gameTime.store(expectedTime, .monotonic);
|
||||
@ -1048,78 +1031,55 @@ pub const Protocols = struct {
|
||||
curTime = actualTime;
|
||||
}
|
||||
}
|
||||
const newBiome = main.server.terrain.biomes.getById(zon.get([]const u8, "biome", ""));
|
||||
|
||||
const newBiome = main.server.terrain.biomes.getByIndex(biomeId) orelse return error.MissingBiome;
|
||||
const oldBiome = world.playerBiome.swap(newBiome, .monotonic);
|
||||
if(oldBiome != newBiome) {
|
||||
main.audio.setMusic(newBiome.preferredMusic);
|
||||
}
|
||||
}
|
||||
},
|
||||
else => |unrecognizedType| {
|
||||
std.log.err("Unrecognized type for genericUpdateProtocol: {}. Data: {any}", .{unrecognizedType, reader.remaining});
|
||||
return error.Invalid;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn addHeaderAndSendImportant(conn: *Connection, header: u8, data: []const u8) void {
|
||||
const headeredData = main.stackAllocator.alloc(u8, data.len + 1);
|
||||
defer main.stackAllocator.free(headeredData);
|
||||
headeredData[0] = header;
|
||||
@memcpy(headeredData[1..], data);
|
||||
conn.sendImportant(id, headeredData);
|
||||
}
|
||||
|
||||
fn addHeaderAndSendUnimportant(conn: *Connection, header: u8, data: []const u8) void {
|
||||
const headeredData = main.stackAllocator.alloc(u8, data.len + 1);
|
||||
defer main.stackAllocator.free(headeredData);
|
||||
headeredData[0] = header;
|
||||
@memcpy(headeredData[1..], data);
|
||||
conn.sendUnimportant(id, headeredData);
|
||||
}
|
||||
|
||||
pub fn sendGamemode(conn: *Connection, gamemode: main.game.Gamemode) void {
|
||||
conn.sendImportant(id, &.{type_gamemode, @intFromEnum(gamemode)});
|
||||
conn.sendImportant(id, &.{@intFromEnum(UpdateType.gamemode), @intFromEnum(gamemode)});
|
||||
}
|
||||
|
||||
pub fn sendTPCoordinates(conn: *Connection, pos: Vec3d) void {
|
||||
var writer = utils.BinaryWriter.initCapacity(main.stackAllocator, networkEndian, 25);
|
||||
defer writer.deinit();
|
||||
writer.writeInt(u8, type_teleport);
|
||||
writer.writeInt(u64, @bitCast(pos[0]));
|
||||
writer.writeInt(u64, @bitCast(pos[1]));
|
||||
writer.writeInt(u64, @bitCast(pos[2]));
|
||||
conn.sendImportant(id, writer.data.items);
|
||||
}
|
||||
|
||||
pub fn sendCure(conn: *Connection) void {
|
||||
var data: [1]u8 = undefined;
|
||||
data[0] = type_cure;
|
||||
conn.sendImportant(id, &data);
|
||||
writer.writeEnum(UpdateType, .teleport);
|
||||
writer.writeVec(Vec3d, pos);
|
||||
|
||||
conn.sendImportant(id, writer.data.items);
|
||||
}
|
||||
|
||||
pub fn sendWorldEditPos(conn: *Connection, posType: WorldEditPosition, maybePos: ?Vec3i) void {
|
||||
var writer = utils.BinaryWriter.initCapacity(main.stackAllocator, networkEndian, 25);
|
||||
defer writer.deinit();
|
||||
writer.writeInt(u8, type_worldEditPos);
|
||||
|
||||
writer.writeEnum(UpdateType, .worldEditPos);
|
||||
writer.writeEnum(WorldEditPosition, posType);
|
||||
if(maybePos) |pos| {
|
||||
writer.writeInt(i32, pos[0]);
|
||||
writer.writeInt(i32, pos[1]);
|
||||
writer.writeInt(i32, pos[2]);
|
||||
writer.writeVec(Vec3i, pos);
|
||||
}
|
||||
|
||||
conn.sendImportant(id, writer.data.items);
|
||||
}
|
||||
|
||||
pub fn sendTimeAndBiome(conn: *Connection, world: *const main.server.ServerWorld) void {
|
||||
const zon = ZonElement.initObject(main.stackAllocator);
|
||||
defer zon.deinit(main.stackAllocator);
|
||||
zon.put("time", world.gameTime);
|
||||
const pos = conn.user.?.player.pos;
|
||||
zon.put("biome", (world.getBiome(@intFromFloat(pos[0]), @intFromFloat(pos[1]), @intFromFloat(pos[2]))).id);
|
||||
const string = zon.toString(main.stackAllocator);
|
||||
defer main.stackAllocator.free(string);
|
||||
addHeaderAndSendUnimportant(conn, type_timeAndBiome, string);
|
||||
var writer = utils.BinaryWriter.initCapacity(main.stackAllocator, networkEndian, 13);
|
||||
defer writer.deinit();
|
||||
|
||||
writer.writeEnum(UpdateType, .timeAndBiome);
|
||||
writer.writeInt(i64, world.gameTime);
|
||||
|
||||
const pos = @as(Vec3i, @intFromFloat(conn.user.?.player.pos));
|
||||
writer.writeInt(u32, world.getBiome(pos[0], pos[1], pos[2]).paletteId);
|
||||
|
||||
conn.sendImportant(id, writer.data.items);
|
||||
}
|
||||
};
|
||||
pub const chat = struct {
|
||||
|
@ -601,6 +601,7 @@ var finishedLoading: bool = false;
|
||||
var biomes: main.List(Biome) = undefined;
|
||||
var caveBiomes: main.List(Biome) = undefined;
|
||||
var biomesById: std.StringHashMap(*Biome) = undefined;
|
||||
var biomesByIndex: main.ListUnmanaged(*Biome) = .{};
|
||||
pub var byTypeBiomes: *TreeNode = undefined;
|
||||
|
||||
const UnfinishedSubBiomeData = struct {
|
||||
@ -648,6 +649,7 @@ pub fn reset() void {
|
||||
biomes.clearRetainingCapacity();
|
||||
caveBiomes.clearRetainingCapacity();
|
||||
biomesById.clearRetainingCapacity();
|
||||
biomesByIndex.clearRetainingCapacity();
|
||||
byTypeBiomes.deinit(main.globalAllocator);
|
||||
}
|
||||
|
||||
@ -658,6 +660,7 @@ pub fn deinit() void {
|
||||
biomes.deinit();
|
||||
caveBiomes.deinit();
|
||||
biomesById.deinit();
|
||||
biomesByIndex.deinit(main.globalAllocator);
|
||||
// TODO? byTypeBiomes.deinit(main.globalAllocator);
|
||||
SimpleStructureModel.modelRegistry.clearAndFree(main.globalAllocator.allocator);
|
||||
}
|
||||
@ -690,11 +693,15 @@ pub fn finishLoading() void {
|
||||
}
|
||||
}
|
||||
byTypeBiomes = TreeNode.init(main.globalAllocator, biomes.items[0..nonZeroBiomes], 0);
|
||||
biomesByIndex.resize(main.globalAllocator, biomes.items.len + caveBiomes.items.len);
|
||||
|
||||
for(biomes.items) |*biome| {
|
||||
biomesById.put(biome.id, biome) catch unreachable;
|
||||
biomesByIndex.items[biome.paletteId] = biome;
|
||||
}
|
||||
for(caveBiomes.items) |*biome| {
|
||||
biomesById.put(biome.id, biome) catch unreachable;
|
||||
biomesByIndex.items[biome.paletteId] = biome;
|
||||
}
|
||||
var subBiomeIterator = unfinishedSubBiomes.iterator();
|
||||
while(subBiomeIterator.next()) |subBiomeData| {
|
||||
@ -760,6 +767,11 @@ pub fn getById(id: []const u8) *const Biome {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn getByIndex(index: u32) ?*const Biome {
|
||||
std.debug.assert(finishedLoading);
|
||||
return biomesByIndex.items[index];
|
||||
}
|
||||
|
||||
pub fn getPlaceholderBiome() *const Biome {
|
||||
return &biomes.items[0];
|
||||
}
|
||||
|
@ -1416,6 +1416,23 @@ pub const BinaryReader = struct {
|
||||
return .{.remaining = data, .endian = endian};
|
||||
}
|
||||
|
||||
pub fn readVec(self: *BinaryReader, T: type) error{OutOfBounds, IntOutOfBounds}!T {
|
||||
const typeInfo = @typeInfo(T).vector;
|
||||
var result: T = undefined;
|
||||
inline for(0..typeInfo.len) |i| {
|
||||
switch(@typeInfo(typeInfo.child)) {
|
||||
.int => {
|
||||
result[i] = try self.readInt(typeInfo.child);
|
||||
},
|
||||
.float => {
|
||||
result[i] = try self.readFloat(typeInfo.child);
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn readInt(self: *BinaryReader, T: type) error{OutOfBounds, IntOutOfBounds}!T {
|
||||
if(@mod(@typeInfo(T).int.bits, 8) != 0) {
|
||||
const fullBits = comptime std.mem.alignForward(u16, @typeInfo(T).int.bits, 8);
|
||||
@ -1468,6 +1485,21 @@ pub const BinaryWriter = struct {
|
||||
self.data.deinit();
|
||||
}
|
||||
|
||||
pub fn writeVec(self: *BinaryWriter, T: type, value: T) void {
|
||||
const typeInfo = @typeInfo(T).vector;
|
||||
inline for(0..typeInfo.len) |i| {
|
||||
switch(@typeInfo(typeInfo.child)) {
|
||||
.int => {
|
||||
self.writeInt(typeInfo.child, value[i]);
|
||||
},
|
||||
.float => {
|
||||
self.writeFloat(typeInfo.child, value[i]);
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn writeInt(self: *BinaryWriter, T: type, value: T) void {
|
||||
if(@mod(@typeInfo(T).int.bits, 8) != 0) {
|
||||
const fullBits = comptime std.mem.alignForward(u16, @typeInfo(T).int.bits, 8);
|
||||
|
Loading…
x
Reference in New Issue
Block a user