mirror of
https://git.xeondev.com/LR/S.git
synced 2026-03-21 23:22:21 +01:00
refactor(scene): factor out player location into a persistent component
This commit is contained in:
@@ -20,6 +20,9 @@ const char_bag_teams_file = "teams";
|
|||||||
const char_bag_meta_file = "meta";
|
const char_bag_meta_file = "meta";
|
||||||
const item_bag_path = "item_bag";
|
const item_bag_path = "item_bag";
|
||||||
const item_bag_weapon_depot_file = "weapon_depot";
|
const item_bag_weapon_depot_file = "weapon_depot";
|
||||||
|
const scene_path = "scene";
|
||||||
|
const scene_current_file = "current";
|
||||||
|
const default_level = "map02_lv001";
|
||||||
|
|
||||||
const default_team: []const []const u8 = &.{
|
const default_team: []const []const u8 = &.{
|
||||||
"chr_0026_lastrite",
|
"chr_0026_lastrite",
|
||||||
@@ -85,6 +88,11 @@ pub fn loadPlayer(io: Io, gpa: Allocator, assets: *const Assets, uid: []const u8
|
|||||||
else => |e| return e,
|
else => |e| return e,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
result.scene = loadSceneComponent(io, data_dir, uid) catch |err| switch (err) {
|
||||||
|
error.NeedsReset => try createDefaultSceneComponent(io, data_dir, assets),
|
||||||
|
else => |e| return e,
|
||||||
|
};
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -446,6 +454,75 @@ fn createDefaultBitsetComponent(io: Io, data_dir: Io.Dir, assets: *const Assets)
|
|||||||
return bitset;
|
return bitset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn loadSceneComponent(io: Io, data_dir: Io.Dir, uid: []const u8) !Player.Scene {
|
||||||
|
const scene_dir = data_dir.openDir(io, scene_path, .{}) catch |err| switch (err) {
|
||||||
|
error.FileNotFound => return error.NeedsReset,
|
||||||
|
error.Canceled => |e| return e,
|
||||||
|
else => return error.InputOutput,
|
||||||
|
};
|
||||||
|
|
||||||
|
defer scene_dir.close(io);
|
||||||
|
|
||||||
|
const current = fs.loadStruct(Player.Scene.Current, io, scene_dir, scene_current_file) catch |err| switch (err) {
|
||||||
|
inline error.FileNotFound, error.ChecksumMismatch, error.ReprSizeMismatch => |e| {
|
||||||
|
if (e == error.ChecksumMismatch) {
|
||||||
|
log.err(
|
||||||
|
"checksum mismatched for current scene data of player {s}, resetting to defaults.",
|
||||||
|
.{uid},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e == error.ReprSizeMismatch) {
|
||||||
|
log.err(
|
||||||
|
"struct layout mismatched for current scene data of player {s}, resetting to defaults.",
|
||||||
|
.{uid},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return error.NeedsReset;
|
||||||
|
},
|
||||||
|
error.Canceled => |e| return e,
|
||||||
|
else => return error.InputOutput,
|
||||||
|
};
|
||||||
|
|
||||||
|
return .{ .current = current };
|
||||||
|
}
|
||||||
|
|
||||||
|
fn createDefaultSceneComponent(io: Io, data_dir: Io.Dir, assets: *const Assets) !Player.Scene {
|
||||||
|
const scene_dir = data_dir.createDirPathOpen(io, scene_path, .{}) catch |err| switch (err) {
|
||||||
|
error.Canceled => |e| return e,
|
||||||
|
else => return error.InputOutput,
|
||||||
|
};
|
||||||
|
|
||||||
|
const default_level_config = assets.level_config_table.getPtr(default_level).?;
|
||||||
|
|
||||||
|
const current: Player.Scene.Current = .{
|
||||||
|
.level_id = default_level_config.idNum,
|
||||||
|
.position = .{
|
||||||
|
default_level_config.playerInitPos.x,
|
||||||
|
default_level_config.playerInitPos.y,
|
||||||
|
default_level_config.playerInitPos.z,
|
||||||
|
},
|
||||||
|
.rotation = .{
|
||||||
|
default_level_config.playerInitRot.x,
|
||||||
|
default_level_config.playerInitRot.y,
|
||||||
|
default_level_config.playerInitRot.z,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
try fs.saveStruct(Player.Scene.Current, ¤t, io, scene_dir, scene_current_file);
|
||||||
|
return .{ .current = current };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn saveSceneComponent(io: Io, data_dir: Io.Dir, component: *const Player.Scene) !void {
|
||||||
|
const scene_dir = data_dir.createDirPathOpen(io, scene_path, .{}) catch |err| switch (err) {
|
||||||
|
error.Canceled => |e| return e,
|
||||||
|
else => return error.InputOutput,
|
||||||
|
};
|
||||||
|
|
||||||
|
try fs.saveStruct(Player.Scene.Current, &component.current, io, scene_dir, scene_current_file);
|
||||||
|
}
|
||||||
|
|
||||||
fn loadArray(
|
fn loadArray(
|
||||||
comptime T: type,
|
comptime T: type,
|
||||||
io: Io,
|
io: Io,
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ pub const Unlock = @import("Player/Unlock.zig");
|
|||||||
pub const CharBag = @import("Player/CharBag.zig");
|
pub const CharBag = @import("Player/CharBag.zig");
|
||||||
pub const ItemBag = @import("Player/ItemBag.zig");
|
pub const ItemBag = @import("Player/ItemBag.zig");
|
||||||
pub const Bitset = @import("Player/Bitset.zig");
|
pub const Bitset = @import("Player/Bitset.zig");
|
||||||
|
pub const Scene = @import("Player/Scene.zig");
|
||||||
|
|
||||||
base: Base,
|
base: Base,
|
||||||
game_vars: GameVars,
|
game_vars: GameVars,
|
||||||
@@ -17,6 +18,7 @@ unlock: Unlock,
|
|||||||
char_bag: CharBag,
|
char_bag: CharBag,
|
||||||
item_bag: ItemBag,
|
item_bag: ItemBag,
|
||||||
bitset: Bitset,
|
bitset: Bitset,
|
||||||
|
scene: Scene,
|
||||||
|
|
||||||
pub fn deinit(player: *Player, gpa: Allocator) void {
|
pub fn deinit(player: *Player, gpa: Allocator) void {
|
||||||
player.game_vars.deinit(gpa);
|
player.game_vars.deinit(gpa);
|
||||||
|
|||||||
9
gamesv/src/logic/Player/Scene.zig
Normal file
9
gamesv/src/logic/Player/Scene.zig
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
const Scene = @This();
|
||||||
|
|
||||||
|
current: Current,
|
||||||
|
|
||||||
|
pub const Current = struct {
|
||||||
|
level_id: i32,
|
||||||
|
position: [3]f32,
|
||||||
|
rotation: [3]f32,
|
||||||
|
};
|
||||||
@@ -15,32 +15,10 @@ pub const PlayerId = struct {
|
|||||||
uid: mem.LimitedString(max_length),
|
uid: mem.LimitedString(max_length),
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: this can be made a persistent Player component.
|
|
||||||
pub const Location = struct {
|
|
||||||
const default_level = "map02_lv001";
|
|
||||||
|
|
||||||
level: i32,
|
|
||||||
position: [3]f32,
|
|
||||||
|
|
||||||
fn createDefault(assets: *const Assets) Location {
|
|
||||||
const level_config = assets.level_config_table.getPtr(default_level).?;
|
|
||||||
|
|
||||||
return .{
|
|
||||||
.level = level_config.idNum,
|
|
||||||
.position = .{
|
|
||||||
level_config.playerInitPos.x,
|
|
||||||
level_config.playerInitPos.y,
|
|
||||||
level_config.playerInitPos.z,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
player_id: PlayerId,
|
player_id: PlayerId,
|
||||||
session: *Session, // TODO: should it be here this way? Do we need an abstraction?
|
session: *Session, // TODO: should it be here this way? Do we need an abstraction?
|
||||||
res: logic.Resource,
|
res: logic.Resource,
|
||||||
player: logic.Player,
|
player: logic.Player,
|
||||||
location: Location,
|
|
||||||
|
|
||||||
pub fn init(
|
pub fn init(
|
||||||
session: *Session,
|
session: *Session,
|
||||||
@@ -56,7 +34,6 @@ pub fn init(
|
|||||||
.session = session,
|
.session = session,
|
||||||
.player = player,
|
.player = player,
|
||||||
.res = .init(assets, io),
|
.res = .init(assets, io),
|
||||||
.location = .createDefault(assets),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,7 +48,6 @@ pub const GetComponentError = error{
|
|||||||
pub fn getComponentByType(world: *World, comptime T: type) GetComponentError!T {
|
pub fn getComponentByType(world: *World, comptime T: type) GetComponentError!T {
|
||||||
switch (T) {
|
switch (T) {
|
||||||
PlayerId => return world.player_id,
|
PlayerId => return world.player_id,
|
||||||
*Location, *const Location => return &world.location,
|
|
||||||
*Session => return world.session,
|
*Session => return world.session,
|
||||||
*logic.Resource.PingTimer => return &world.res.ping_timer,
|
*logic.Resource.PingTimer => return &world.res.ping_timer,
|
||||||
*const Assets => return world.res.assets,
|
*const Assets => return world.res.assets,
|
||||||
|
|||||||
@@ -2,12 +2,14 @@ const std = @import("std");
|
|||||||
const pb = @import("proto").pb;
|
const pb = @import("proto").pb;
|
||||||
const logic = @import("../../logic.zig");
|
const logic = @import("../../logic.zig");
|
||||||
const Assets = @import("../../Assets.zig");
|
const Assets = @import("../../Assets.zig");
|
||||||
|
|
||||||
|
const Player = logic.Player;
|
||||||
const messaging = logic.messaging;
|
const messaging = logic.messaging;
|
||||||
|
|
||||||
pub fn onSceneSetTrackPoint(
|
pub fn onSceneSetTrackPoint(
|
||||||
request: messaging.Request(pb.CS_SCENE_SET_TRACK_POINT),
|
request: messaging.Request(pb.CS_SCENE_SET_TRACK_POINT),
|
||||||
assets: *const Assets,
|
assets: *const Assets,
|
||||||
location: *logic.World.Location,
|
scene: Player.Component(.scene),
|
||||||
change_scene_tx: logic.event.Sender(.change_scene_begin),
|
change_scene_tx: logic.event.Sender(.change_scene_begin),
|
||||||
) !void {
|
) !void {
|
||||||
const log = std.log.scoped(.scene_set_track_point);
|
const log = std.log.scoped(.scene_set_track_point);
|
||||||
@@ -36,8 +38,8 @@ pub fn onSceneSetTrackPoint(
|
|||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
location.level = level_config.idNum;
|
scene.data.current.level_id = level_config.idNum;
|
||||||
location.position = .{
|
scene.data.current.position = .{
|
||||||
validation_config.position.x,
|
validation_config.position.x,
|
||||||
validation_config.position.y,
|
validation_config.position.y,
|
||||||
validation_config.position.z,
|
validation_config.position.z,
|
||||||
@@ -47,6 +49,6 @@ pub fn onSceneSetTrackPoint(
|
|||||||
|
|
||||||
log.info(
|
log.info(
|
||||||
"transitioning to scene '{s}', position: {any}",
|
"transitioning to scene '{s}', position: {any}",
|
||||||
.{ validation_config.sceneId, location.position },
|
.{ validation_config.sceneId, scene.data.current.position },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,26 +19,26 @@ pub fn enterSceneOnLogin(
|
|||||||
pub fn beginChangingScene(
|
pub fn beginChangingScene(
|
||||||
rx: logic.event.Receiver(.change_scene_begin),
|
rx: logic.event.Receiver(.change_scene_begin),
|
||||||
session: *Session,
|
session: *Session,
|
||||||
base_comp: Player.Component(.base),
|
base: Player.Component(.base),
|
||||||
location: *const logic.World.Location,
|
scene: Player.Component(.scene),
|
||||||
) !void {
|
) !void {
|
||||||
_ = rx;
|
_ = rx;
|
||||||
|
|
||||||
const position: pb.VECTOR = .{
|
const position: pb.VECTOR = .{
|
||||||
.X = location.position[0],
|
.X = scene.data.current.position[0],
|
||||||
.Y = location.position[1],
|
.Y = scene.data.current.position[1],
|
||||||
.Z = location.position[2],
|
.Z = scene.data.current.position[2],
|
||||||
};
|
};
|
||||||
|
|
||||||
try session.send(pb.SC_CHANGE_SCENE_BEGIN_NOTIFY{
|
try session.send(pb.SC_CHANGE_SCENE_BEGIN_NOTIFY{
|
||||||
.scene_num_id = location.level,
|
.scene_num_id = scene.data.current.level_id,
|
||||||
.position = position,
|
.position = position,
|
||||||
.pass_through_data = .init,
|
.pass_through_data = .init,
|
||||||
});
|
});
|
||||||
|
|
||||||
try session.send(pb.SC_ENTER_SCENE_NOTIFY{
|
try session.send(pb.SC_ENTER_SCENE_NOTIFY{
|
||||||
.role_id = base_comp.data.role_id,
|
.role_id = base.data.role_id,
|
||||||
.scene_num_id = location.level,
|
.scene_num_id = scene.data.current.level_id,
|
||||||
.position = position,
|
.position = position,
|
||||||
.pass_through_data = .init,
|
.pass_through_data = .init,
|
||||||
});
|
});
|
||||||
@@ -62,8 +62,8 @@ pub fn syncSelfScene(
|
|||||||
rx: logic.event.Receiver(.sync_self_scene),
|
rx: logic.event.Receiver(.sync_self_scene),
|
||||||
session: *Session,
|
session: *Session,
|
||||||
arena: logic.Resource.Allocator(.arena),
|
arena: logic.Resource.Allocator(.arena),
|
||||||
char_bag: logic.Player.Component(.char_bag),
|
char_bag: Player.Component(.char_bag),
|
||||||
location: *const logic.World.Location,
|
scene: Player.Component(.scene),
|
||||||
assets: *const Assets,
|
assets: *const Assets,
|
||||||
) !void {
|
) !void {
|
||||||
const reason: pb.SELF_INFO_REASON_TYPE = switch (rx.payload.reason) {
|
const reason: pb.SELF_INFO_REASON_TYPE = switch (rx.payload.reason) {
|
||||||
@@ -72,16 +72,16 @@ pub fn syncSelfScene(
|
|||||||
};
|
};
|
||||||
|
|
||||||
const position: pb.VECTOR = .{
|
const position: pb.VECTOR = .{
|
||||||
.X = location.position[0],
|
.X = scene.data.current.position[0],
|
||||||
.Y = location.position[1],
|
.Y = scene.data.current.position[1],
|
||||||
.Z = location.position[2],
|
.Z = scene.data.current.position[2],
|
||||||
};
|
};
|
||||||
|
|
||||||
const team_index = char_bag.data.meta.curr_team_index;
|
const team_index = char_bag.data.meta.curr_team_index;
|
||||||
const leader_index = char_bag.data.teams.items(.leader_index)[team_index];
|
const leader_index = char_bag.data.teams.items(.leader_index)[team_index];
|
||||||
|
|
||||||
var self_scene_info: pb.SC_SELF_SCENE_INFO = .{
|
var self_scene_info: pb.SC_SELF_SCENE_INFO = .{
|
||||||
.scene_num_id = location.level,
|
.scene_num_id = scene.data.current.level_id,
|
||||||
.self_info_reason = @intFromEnum(reason),
|
.self_info_reason = @intFromEnum(reason),
|
||||||
.teamInfo = .{
|
.teamInfo = .{
|
||||||
.team_type = .CHAR_BAG_TEAM_TYPE_MAIN,
|
.team_type = .CHAR_BAG_TEAM_TYPE_MAIN,
|
||||||
@@ -111,7 +111,7 @@ pub fn syncSelfScene(
|
|||||||
.templateid = char_template_id,
|
.templateid = char_template_id,
|
||||||
.position = position,
|
.position = position,
|
||||||
.rotation = .{},
|
.rotation = .{},
|
||||||
.scene_num_id = location.level,
|
.scene_num_id = scene.data.current.level_id,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user