mirror of
https://git.xeondev.com/LR/S.git
synced 2026-02-04 15:05:17 +01:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
23f9797a8a | ||
|
|
66dff8ddb1 | ||
|
|
3acc274a7d | ||
|
|
f0c3f57602 | ||
|
|
5dff70b504 | ||
|
|
f96fb51e3c | ||
|
|
7a91e1e975 | ||
|
|
b5012c03f4 | ||
|
|
3b20a381fa | ||
|
|
277d5f5573 | ||
|
|
104fcf4b95 |
@@ -4,7 +4,7 @@
|
||||
|
||||
# Getting Started
|
||||
## Requirements
|
||||
- Zig 0.16.0-dev.2368: [Linux](https://ziglang.org/builds/zig-x86_64-linux-0.16.0-dev.2368+380ea6fb5.tar.xz)/[Windows](https://ziglang.org/builds/zig-x86_64-windows-0.16.0-dev.2368+380ea6fb5.zip)
|
||||
- Zig 0.16.0-dev.2459: [Linux](https://ziglang.org/builds/zig-x86_64-linux-0.16.0-dev.2459+37d14a4f3.tar.xz)/[Windows](https://ziglang.org/builds/zig-x86_64-windows-0.16.0-dev.2459+37d14a4f3.zip)
|
||||
|
||||
#### For additional help, you can join our [discord server](https://discord.xeondev.com)
|
||||
|
||||
@@ -33,6 +33,8 @@ Currently supported client version is `1.0.14`, you can get it from 3rd party so
|
||||
|
||||
Next, you have to apply the necessary [client patch](https://git.xeondev.com/LR/C). It allows you to connect to the local server.
|
||||
|
||||
Once the patched game is running, you'll see a debug login window with a bunch of random characters. You should replace these with some numeric UID (digits only). After that, you can login normally.
|
||||
|
||||
## Community
|
||||
- [Our Discord Server](https://discord.xeondev.com)
|
||||
- [Our Telegram Channel](https://t.me/reversedrooms)
|
||||
|
||||
49132
assets/configs/LevelMapMark.json
Normal file
49132
assets/configs/LevelMapMark.json
Normal file
File diff suppressed because it is too large
Load Diff
2047
assets/configs/MapTeleportValidationDataTable.json
Normal file
2047
assets/configs/MapTeleportValidationDataTable.json
Normal file
File diff suppressed because it is too large
Load Diff
327
assets/tables/TrackMapPointTable.json
Normal file
327
assets/tables/TrackMapPointTable.json
Normal file
@@ -0,0 +1,327 @@
|
||||
[
|
||||
{
|
||||
"Key": "1",
|
||||
"Value": {
|
||||
"end": "map01_lv002",
|
||||
"pos": {
|
||||
"x": -660.3,
|
||||
"y": 119.32,
|
||||
"z": -126.9
|
||||
},
|
||||
"quest": "",
|
||||
"start": "map01_lv001"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Key": "24",
|
||||
"Value": {
|
||||
"end": "map02_lv004",
|
||||
"pos": {
|
||||
"x": 118.47,
|
||||
"y": 137.65,
|
||||
"z": 0.5
|
||||
},
|
||||
"quest": "",
|
||||
"start": "indie_dg007"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Key": "11",
|
||||
"Value": {
|
||||
"end": "map02_lv002",
|
||||
"pos": {
|
||||
"x": -961.8,
|
||||
"y": 263.46,
|
||||
"z": -895.33
|
||||
},
|
||||
"quest": "e6m5_q#3",
|
||||
"start": "map02_lv001"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Key": "15",
|
||||
"Value": {
|
||||
"end": "map02_lv002",
|
||||
"pos": {
|
||||
"x": -1711.17,
|
||||
"y": 408.86,
|
||||
"z": -338.58
|
||||
},
|
||||
"quest": "",
|
||||
"start": "indie_dg005"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Key": "3",
|
||||
"Value": {
|
||||
"end": "map01_lv005",
|
||||
"pos": {
|
||||
"x": 255.0,
|
||||
"y": 99.0,
|
||||
"z": -340.0
|
||||
},
|
||||
"quest": "",
|
||||
"start": "map01_lv001"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Key": "14",
|
||||
"Value": {
|
||||
"end": "map02_lv001",
|
||||
"pos": {
|
||||
"x": -718.6,
|
||||
"y": 256.91,
|
||||
"z": -896.89
|
||||
},
|
||||
"quest": "",
|
||||
"start": "map02_lv002"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Key": "2",
|
||||
"Value": {
|
||||
"end": "map01_lv003",
|
||||
"pos": {
|
||||
"x": 129.0,
|
||||
"y": 73.0,
|
||||
"z": -567.0
|
||||
},
|
||||
"quest": "",
|
||||
"start": "map01_lv001"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Key": "16",
|
||||
"Value": {
|
||||
"end": "indie_dg005",
|
||||
"pos": {
|
||||
"x": -1443.57,
|
||||
"y": 324.2216,
|
||||
"z": -336.5857
|
||||
},
|
||||
"quest": "",
|
||||
"start": "map02_lv002"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Key": "25",
|
||||
"Value": {
|
||||
"end": "map02_lv001",
|
||||
"pos": {
|
||||
"x": -1151.73,
|
||||
"y": 206.17,
|
||||
"z": -1355.25
|
||||
},
|
||||
"quest": "",
|
||||
"start": "map02_lv004"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Key": "13",
|
||||
"Value": {
|
||||
"end": "map02_lv002",
|
||||
"pos": {
|
||||
"x": -719.07,
|
||||
"y": 257.85,
|
||||
"z": -895.02
|
||||
},
|
||||
"quest": "",
|
||||
"start": "map02_lv001"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Key": "9",
|
||||
"Value": {
|
||||
"end": "map01_lv007",
|
||||
"pos": {
|
||||
"x": 127.0,
|
||||
"y": 93.5,
|
||||
"z": 711.0
|
||||
},
|
||||
"quest": "",
|
||||
"start": "map01_lv006"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Key": "23",
|
||||
"Value": {
|
||||
"end": "indie_dg007",
|
||||
"pos": {
|
||||
"x": -1087.61,
|
||||
"y": 38.05,
|
||||
"z": -864.19
|
||||
},
|
||||
"quest": "",
|
||||
"start": "map02_lv004"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Key": "8",
|
||||
"Value": {
|
||||
"end": "map01_lv005",
|
||||
"pos": {
|
||||
"x": 682.0,
|
||||
"y": 54.0,
|
||||
"z": -1.0
|
||||
},
|
||||
"quest": "",
|
||||
"start": "map01_lv006"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Key": "19",
|
||||
"Value": {
|
||||
"end": "map02_lv004",
|
||||
"pos": {
|
||||
"x": -1384.38,
|
||||
"y": 276.66,
|
||||
"z": -896.44
|
||||
},
|
||||
"quest": "",
|
||||
"start": "map02_lv002"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Key": "17",
|
||||
"Value": {
|
||||
"end": "map02_lv003",
|
||||
"pos": {
|
||||
"x": -529.4,
|
||||
"y": 262.25,
|
||||
"z": -1024.36
|
||||
},
|
||||
"quest": "",
|
||||
"start": "map02_lv001"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Key": "10",
|
||||
"Value": {
|
||||
"end": "map01_lv006",
|
||||
"pos": {
|
||||
"x": 129.0,
|
||||
"y": 93.5,
|
||||
"z": 714.0
|
||||
},
|
||||
"quest": "",
|
||||
"start": "map01_lv007"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Key": "20",
|
||||
"Value": {
|
||||
"end": "map02_lv002",
|
||||
"pos": {
|
||||
"x": -1383.36,
|
||||
"y": 278.66,
|
||||
"z": -895.34
|
||||
},
|
||||
"quest": "",
|
||||
"start": "map02_lv004"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Key": "18",
|
||||
"Value": {
|
||||
"end": "map02_lv001",
|
||||
"pos": {
|
||||
"x": -529.7,
|
||||
"y": 262.25,
|
||||
"z": -1023.57
|
||||
},
|
||||
"quest": "",
|
||||
"start": "map02_lv003"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Key": "22",
|
||||
"Value": {
|
||||
"end": "map02_lv002",
|
||||
"pos": {
|
||||
"x": -640.41,
|
||||
"y": 253.97,
|
||||
"z": -326.63
|
||||
},
|
||||
"quest": "",
|
||||
"start": "map02_lv005"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Key": "5",
|
||||
"Value": {
|
||||
"end": "map01_lv001",
|
||||
"pos": {
|
||||
"x": 127.0,
|
||||
"y": 73.0,
|
||||
"z": -567.0
|
||||
},
|
||||
"quest": "",
|
||||
"start": "map01_lv003"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Key": "4",
|
||||
"Value": {
|
||||
"end": "map01_lv001",
|
||||
"pos": {
|
||||
"x": -656.74,
|
||||
"y": 119.62,
|
||||
"z": -129.1
|
||||
},
|
||||
"quest": "",
|
||||
"start": "map01_lv002"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Key": "21",
|
||||
"Value": {
|
||||
"end": "map02_lv005",
|
||||
"pos": {
|
||||
"x": -639.63,
|
||||
"y": 253.97,
|
||||
"z": -326.32
|
||||
},
|
||||
"quest": "",
|
||||
"start": "map02_lv002"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Key": "7",
|
||||
"Value": {
|
||||
"end": "map01_lv006",
|
||||
"pos": {
|
||||
"x": 682.0,
|
||||
"y": 54.0,
|
||||
"z": 1.0
|
||||
},
|
||||
"quest": "",
|
||||
"start": "map01_lv005"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Key": "12",
|
||||
"Value": {
|
||||
"end": "map02_lv001",
|
||||
"pos": {
|
||||
"x": -961.8,
|
||||
"y": 264.13,
|
||||
"z": -897.53
|
||||
},
|
||||
"quest": "e6m5_q#3",
|
||||
"start": "map02_lv002"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Key": "6",
|
||||
"Value": {
|
||||
"end": "map01_lv001",
|
||||
"pos": {
|
||||
"x": 257.0,
|
||||
"y": 99.0,
|
||||
"z": -341.0
|
||||
},
|
||||
"quest": "",
|
||||
"start": "map01_lv005"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -1,7 +1,7 @@
|
||||
.{
|
||||
.name = .LR_S,
|
||||
.version = "0.1.0",
|
||||
.minimum_zig_version = "0.16.0-dev.2368+380ea6fb5",
|
||||
.minimum_zig_version = "0.16.0-dev.2471+e9eadee00",
|
||||
.paths = .{""},
|
||||
.fingerprint = 0x50ff8392fab61337,
|
||||
}
|
||||
|
||||
@@ -1721,16 +1721,6 @@ pub fn Poll(comptime io_options: IoOptions) type {
|
||||
return tio.vtable.dirCreateDirPathOpen(tio.userdata, dir, sub_path, perm, options);
|
||||
}
|
||||
|
||||
fn fileWriteStreaming(userdata: ?*anyopaque, file: Io.File, header: []const u8, data: []const []const u8, splat: usize) Io.File.Writer.Error!usize {
|
||||
const p: *ThisPoll = @ptrCast(@alignCast(userdata));
|
||||
try checkCancel(p);
|
||||
|
||||
var t: Io.Threaded = .init_single_threaded;
|
||||
const tio = t.io();
|
||||
|
||||
return tio.vtable.fileWriteStreaming(tio.userdata, file, header, data, splat);
|
||||
}
|
||||
|
||||
fn fileWritePositional(userdata: ?*anyopaque, file: Io.File, header: []const u8, data: []const []const u8, splat: usize, offset: u64) Io.File.WritePositionalError!usize {
|
||||
const p: *ThisPoll = @ptrCast(@alignCast(userdata));
|
||||
try checkCancel(p);
|
||||
@@ -1791,14 +1781,16 @@ pub fn Poll(comptime io_options: IoOptions) type {
|
||||
return tio.vtable.fileReadPositional(tio.userdata, file, data, offset);
|
||||
}
|
||||
|
||||
fn fileReadStreaming(userdata: ?*anyopaque, file: Io.File, data: []const []u8) Io.File.Reader.Error!usize {
|
||||
fn operate(userdata: ?*anyopaque, operation: Io.Operation) Io.Cancelable!Io.Operation.Result {
|
||||
// TODO: implement network operations once they're migrated to this API.
|
||||
|
||||
const p: *ThisPoll = @ptrCast(@alignCast(userdata));
|
||||
try checkCancel(p);
|
||||
|
||||
var t: Io.Threaded = .init_single_threaded;
|
||||
const tio = t.io();
|
||||
|
||||
return tio.vtable.fileReadStreaming(tio.userdata, file, data);
|
||||
return tio.vtable.operate(tio.userdata, operation);
|
||||
}
|
||||
|
||||
fn socketClose(socket: posix.socket_t) void {
|
||||
|
||||
2
envrc
2
envrc
@@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
# DEPENDS: curl, tar, xz, realpath
|
||||
|
||||
ZIG_VERSION="0.16.0-dev.2368+380ea6fb5"
|
||||
ZIG_VERSION="0.16.0-dev.2471+e9eadee00"
|
||||
ZIG_PLATFORM="x86_64-linux"
|
||||
ZIG_DIST="zig-${ZIG_PLATFORM}-${ZIG_VERSION}"
|
||||
ZIG_DIR="./.direnv/${ZIG_DIST}/"
|
||||
|
||||
@@ -7,6 +7,7 @@ pub const CharacterSkillMap = @import("Assets/CharacterSkillMap.zig");
|
||||
const Io = std.Io;
|
||||
const Allocator = std.mem.Allocator;
|
||||
const ArenaAllocator = std.heap.ArenaAllocator;
|
||||
const StringHashMap = std.StringArrayHashMapUnmanaged;
|
||||
|
||||
const meta = std.meta;
|
||||
const log = std.log.scoped(.assets);
|
||||
@@ -17,7 +18,12 @@ char_skill_map: CharacterSkillMap,
|
||||
str_to_num_dicts: IndexDictionaries.StrToNum,
|
||||
num_to_str_dicts: IndexDictionaries.NumToStr,
|
||||
common_skill_config: configs.CommonSkillConfig,
|
||||
level_config_table: std.StringArrayHashMapUnmanaged(configs.LevelConfig),
|
||||
level_config_table: StringHashMap(configs.LevelConfig),
|
||||
// Map mark groups as they're stored in LevelMapMark.json
|
||||
level_map_mark_groups: StringHashMap([]const configs.ClientSingleMapMarkData),
|
||||
// instId-to-data mapping
|
||||
map_mark_table: StringHashMap(*const configs.ClientSingleMapMarkData),
|
||||
teleport_validation_table: configs.TeleportValidationDataTable,
|
||||
|
||||
pub const IdGroup = enum {
|
||||
char_id,
|
||||
@@ -63,11 +69,27 @@ pub fn load(io: Io, gpa: Allocator) !Assets {
|
||||
configs.CommonSkillConfig.file,
|
||||
);
|
||||
|
||||
const level_config_table = try configs.loadJsonConfig(
|
||||
const level_config_table = (try configs.loadJsonConfig(
|
||||
std.json.ArrayHashMap(configs.LevelConfig),
|
||||
io,
|
||||
arena.allocator(),
|
||||
"LevelConfigTable.json",
|
||||
)).map;
|
||||
|
||||
const level_map_mark_groups = (try configs.loadJsonConfig(
|
||||
std.json.ArrayHashMap([]const configs.ClientSingleMapMarkData),
|
||||
io,
|
||||
arena.allocator(),
|
||||
"LevelMapMark.json",
|
||||
)).map;
|
||||
|
||||
const map_mark_table = try buildMapMarkTable(&level_map_mark_groups, arena.allocator());
|
||||
|
||||
const teleport_validation_table = try configs.loadJsonConfig(
|
||||
configs.TeleportValidationDataTable,
|
||||
io,
|
||||
arena.allocator(),
|
||||
"MapTeleportValidationDataTable.json",
|
||||
);
|
||||
|
||||
return .{
|
||||
@@ -77,10 +99,31 @@ pub fn load(io: Io, gpa: Allocator) !Assets {
|
||||
.str_to_num_dicts = str_to_num_dicts,
|
||||
.num_to_str_dicts = num_to_str_dicts,
|
||||
.common_skill_config = common_skill_config,
|
||||
.level_config_table = level_config_table.map,
|
||||
.level_config_table = level_config_table,
|
||||
.level_map_mark_groups = level_map_mark_groups,
|
||||
.map_mark_table = map_mark_table,
|
||||
.teleport_validation_table = teleport_validation_table,
|
||||
};
|
||||
}
|
||||
|
||||
fn buildMapMarkTable(
|
||||
groups: *const StringHashMap([]const configs.ClientSingleMapMarkData),
|
||||
arena: Allocator,
|
||||
) Allocator.Error!StringHashMap(*const configs.ClientSingleMapMarkData) {
|
||||
var map: StringHashMap(*const configs.ClientSingleMapMarkData) = .empty;
|
||||
|
||||
for (groups.values()) |group| for (group) |*mark| {
|
||||
const inst_id = try std.mem.concat(
|
||||
arena,
|
||||
u8,
|
||||
&.{ mark.basicData.templateId, mark.basicData.markInstId },
|
||||
);
|
||||
try map.put(arena, inst_id, mark);
|
||||
};
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
pub fn deinit(assets: *Assets) void {
|
||||
assets.owned_tables.deinit();
|
||||
assets.arena.deinit();
|
||||
|
||||
@@ -14,6 +14,7 @@ pub const SkillPatchDataBundleList = @import("Tables/SkillPatchDataBundleList.zi
|
||||
pub const WeaponBasicData = @import("Tables/WeaponBasicData.zig");
|
||||
pub const CharWpnRecommendData = @import("Tables/CharWpnRecommendData.zig");
|
||||
pub const DomainData = @import("Tables/DomainData.zig");
|
||||
pub const MapPointData = @import("Tables/MapPointData.zig");
|
||||
|
||||
pub const StrToNum = struct {
|
||||
pub const file = "StrIdNumTable.json";
|
||||
@@ -32,6 +33,7 @@ str_to_num: StringArrayHashMap(StrToNum),
|
||||
num_to_str: StringArrayHashMap(NumToStr),
|
||||
char_wpn_recommend: StringArrayHashMap(CharWpnRecommendData),
|
||||
domain_data: StringArrayHashMap(DomainData),
|
||||
track_map_point: StringArrayHashMap(MapPointData),
|
||||
|
||||
pub const LoadError = error{
|
||||
NotStarted,
|
||||
|
||||
10
gamesv/src/Assets/Tables/MapPointData.zig
Normal file
10
gamesv/src/Assets/Tables/MapPointData.zig
Normal file
@@ -0,0 +1,10 @@
|
||||
pub const file = "TrackMapPointTable.json";
|
||||
|
||||
start: []const u8,
|
||||
end: []const u8,
|
||||
quest: []const u8,
|
||||
pos: struct {
|
||||
x: f32,
|
||||
y: f32,
|
||||
z: f32,
|
||||
},
|
||||
@@ -3,6 +3,8 @@ const json = std.json;
|
||||
|
||||
pub const CommonSkillConfig = @import("configs/CommonSkillConfig.zig");
|
||||
pub const LevelConfig = @import("configs/LevelConfig.zig");
|
||||
pub const ClientSingleMapMarkData = @import("configs/ClientSingleMapMarkData.zig");
|
||||
pub const TeleportValidationDataTable = @import("configs/TeleportValidationDataTable.zig");
|
||||
|
||||
const Io = std.Io;
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
35
gamesv/src/Assets/configs/ClientSingleMapMarkData.zig
Normal file
35
gamesv/src/Assets/configs/ClientSingleMapMarkData.zig
Normal file
@@ -0,0 +1,35 @@
|
||||
const ClientSingleMapMarkData = @This();
|
||||
|
||||
basicData: MapMarkBasicData,
|
||||
detailedData: ?MapMarkDetailedData = null,
|
||||
|
||||
pub const MapMarkBasicData = struct {
|
||||
templateId: []const u8,
|
||||
markInstId: []const u8,
|
||||
pos: struct {
|
||||
x: f32,
|
||||
y: f32,
|
||||
z: f32,
|
||||
},
|
||||
};
|
||||
|
||||
pub const MapMarkDetailedData = struct {
|
||||
logicIdGlobal: ?u64 = null,
|
||||
teleportValidationId: ?[]const u8 = null,
|
||||
|
||||
pub const TeleportValidationData = struct {
|
||||
logicIdGlobal: u64,
|
||||
teleportValidationId: []const u8,
|
||||
};
|
||||
};
|
||||
|
||||
pub fn teleportValidationData(
|
||||
csmmd: *const ClientSingleMapMarkData,
|
||||
) ?MapMarkDetailedData.TeleportValidationData {
|
||||
const details = csmmd.detailedData orelse return null;
|
||||
|
||||
return .{
|
||||
.logicIdGlobal = details.logicIdGlobal orelse return null,
|
||||
.teleportValidationId = details.teleportValidationId orelse return null,
|
||||
};
|
||||
}
|
||||
10
gamesv/src/Assets/configs/TeleportValidationDataTable.zig
Normal file
10
gamesv/src/Assets/configs/TeleportValidationDataTable.zig
Normal file
@@ -0,0 +1,10 @@
|
||||
const std = @import("std");
|
||||
|
||||
teleportValidationDatas: std.json.ArrayHashMap(TeleportValidationData),
|
||||
|
||||
pub const TeleportValidationData = struct {
|
||||
id: []const u8,
|
||||
teleportReason: i32,
|
||||
sceneId: []const u8,
|
||||
position: struct { x: f32, y: f32, z: f32 },
|
||||
};
|
||||
@@ -107,17 +107,20 @@ pub fn process(
|
||||
error.Canceled => |e| return e,
|
||||
};
|
||||
|
||||
const player = fs.persistence.loadPlayer(io, gpa, assets, result.uid) catch |err| switch (err) {
|
||||
const player = fs.persistence.loadPlayer(io, gpa, assets, result.uid.view()) catch |err| switch (err) {
|
||||
error.Canceled => |e| return e,
|
||||
else => |e| {
|
||||
log.err("failed to load data for player with uid {d}: {t}, disconnecting", .{ result.uid, e });
|
||||
log.err(
|
||||
"failed to load data for player with uid {s}: {t}, disconnecting",
|
||||
.{ result.uid.view(), e },
|
||||
);
|
||||
return;
|
||||
},
|
||||
};
|
||||
|
||||
log.info(
|
||||
"client from '{f}' has successfully logged into account with uid: {d}",
|
||||
.{ stream.socket.address, result.uid },
|
||||
"client from '{f}' has successfully logged into account with uid: {s}",
|
||||
.{ stream.socket.address, result.uid.view() },
|
||||
);
|
||||
|
||||
world = logic.World.init(&session, assets, result.uid, player, gpa, io);
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
const std = @import("std");
|
||||
const pb = @import("proto").pb;
|
||||
const mem = @import("common").mem;
|
||||
const Session = @import("../Session.zig");
|
||||
const PlayerId = @import("../logic.zig").World.PlayerId;
|
||||
|
||||
const Io = std.Io;
|
||||
const Allocator = std.mem.Allocator;
|
||||
@@ -10,14 +12,30 @@ const log = std.log.scoped(.auth);
|
||||
pub const Error = error{LoginFailed} || Session.SendError || Allocator.Error || Io.Cancelable;
|
||||
|
||||
pub const Result = struct {
|
||||
uid: u64, // It's a string in SC_LOGIN tho
|
||||
uid: mem.LimitedString(PlayerId.max_length),
|
||||
|
||||
pub const FromUidSliceError = error{
|
||||
TooLongString,
|
||||
InvalidCharacters,
|
||||
};
|
||||
|
||||
pub fn fromUidSlice(slice: []const u8) FromUidSliceError!Result {
|
||||
const result: Result = .{ .uid = try .init(slice) };
|
||||
for (slice) |c| if (!std.ascii.isAlphanumeric(c)) {
|
||||
return error.InvalidCharacters;
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
pub fn processLoginRequest(io: Io, session: *Session, request: *const pb.CS_LOGIN) Error!Result {
|
||||
log.info("login request received: {any}", .{request});
|
||||
|
||||
const uid = std.fmt.parseInt(u64, request.uid, 10) catch
|
||||
const result = Result.fromUidSlice(request.uid) catch |err| {
|
||||
log.err("invalid UID received: {t}", .{err});
|
||||
return error.LoginFailed;
|
||||
};
|
||||
|
||||
try session.send(pb.SC_LOGIN{
|
||||
.uid = request.uid,
|
||||
@@ -25,5 +43,5 @@ pub fn processLoginRequest(io: Io, session: *Session, request: *const pb.CS_LOGI
|
||||
.server_time_zone = 3,
|
||||
});
|
||||
|
||||
return .{ .uid = uid };
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ const Assets = @import("../Assets.zig");
|
||||
const Io = std.Io;
|
||||
const Allocator = std.mem.Allocator;
|
||||
const Player = logic.Player;
|
||||
const PlayerId = logic.World.PlayerId;
|
||||
|
||||
const player_data_dir = "store/player/";
|
||||
const base_component_file = "base_data";
|
||||
@@ -19,6 +20,9 @@ const char_bag_teams_file = "teams";
|
||||
const char_bag_meta_file = "meta";
|
||||
const item_bag_path = "item_bag";
|
||||
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 = &.{
|
||||
"chr_0026_lastrite",
|
||||
@@ -35,10 +39,12 @@ const LoadPlayerError = error{
|
||||
const log = std.log.scoped(.persistence);
|
||||
|
||||
// Opens or creates data directory for the player with specified uid.
|
||||
pub fn openPlayerDataDir(io: Io, uid: u64) !Io.Dir {
|
||||
var dir_path_buf: [player_data_dir.len + 20]u8 = undefined;
|
||||
const dir_path = std.fmt.bufPrint(&dir_path_buf, player_data_dir ++ "{d}", .{uid}) catch
|
||||
unreachable; // Since we're printing a u64, it shouldn't exceed the buffer.
|
||||
pub fn openPlayerDataDir(io: Io, uid: []const u8) !Io.Dir {
|
||||
std.debug.assert(uid.len <= PlayerId.max_length);
|
||||
|
||||
var dir_path_buf: [player_data_dir.len + PlayerId.max_length]u8 = undefined;
|
||||
const dir_path = std.fmt.bufPrint(&dir_path_buf, player_data_dir ++ "{s}", .{uid}) catch
|
||||
unreachable;
|
||||
|
||||
const cwd: Io.Dir = .cwd();
|
||||
return cwd.openDir(io, dir_path, .{}) catch |open_err| switch (open_err) {
|
||||
@@ -53,7 +59,7 @@ pub fn openPlayerDataDir(io: Io, uid: u64) !Io.Dir {
|
||||
|
||||
// Loads player data. Creates components that do not exist.
|
||||
// Resets component to default if its data is corrupted.
|
||||
pub fn loadPlayer(io: Io, gpa: Allocator, assets: *const Assets, uid: u64) !Player {
|
||||
pub fn loadPlayer(io: Io, gpa: Allocator, assets: *const Assets, uid: []const u8) !Player {
|
||||
const data_dir = try openPlayerDataDir(io, uid);
|
||||
defer data_dir.close(io);
|
||||
|
||||
@@ -82,26 +88,31 @@ pub fn loadPlayer(io: Io, gpa: Allocator, assets: *const Assets, uid: u64) !Play
|
||||
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;
|
||||
}
|
||||
|
||||
fn loadBaseComponent(
|
||||
io: Io,
|
||||
data_dir: Io.Dir,
|
||||
uid: u64,
|
||||
uid: []const u8,
|
||||
) !Player.Base {
|
||||
return fs.loadStruct(Player.Base, io, data_dir, base_component_file) catch |err| switch (err) {
|
||||
inline error.FileNotFound, error.ChecksumMismatch, error.ReprSizeMismatch => |e| reset: {
|
||||
if (e == error.ChecksumMismatch) {
|
||||
log.err(
|
||||
"checksum mismatched for base_data of player {d}, resetting to defaults.",
|
||||
"checksum mismatched for base_data of player {s}, resetting to defaults.",
|
||||
.{uid},
|
||||
);
|
||||
}
|
||||
|
||||
if (e == error.ReprSizeMismatch) {
|
||||
log.err(
|
||||
"struct layout mismatched for base_data of player {d}, resetting to defaults.",
|
||||
"struct layout mismatched for base_data of player {s}, resetting to defaults.",
|
||||
.{uid},
|
||||
);
|
||||
}
|
||||
@@ -116,7 +127,7 @@ fn loadBaseComponent(
|
||||
};
|
||||
}
|
||||
|
||||
fn loadGameVarsComponent(io: Io, gpa: Allocator, data_dir: Io.Dir, uid: u64) !Player.GameVars {
|
||||
fn loadGameVarsComponent(io: Io, gpa: Allocator, data_dir: Io.Dir, uid: []const u8) !Player.GameVars {
|
||||
var game_vars: Player.GameVars = undefined;
|
||||
|
||||
game_vars.server_vars = try loadArray(
|
||||
@@ -146,7 +157,7 @@ fn loadGameVarsComponent(io: Io, gpa: Allocator, data_dir: Io.Dir, uid: u64) !Pl
|
||||
return game_vars;
|
||||
}
|
||||
|
||||
fn loadUnlockComponent(io: Io, gpa: Allocator, data_dir: Io.Dir, uid: u64) !Player.Unlock {
|
||||
fn loadUnlockComponent(io: Io, gpa: Allocator, data_dir: Io.Dir, uid: []const u8) !Player.Unlock {
|
||||
var unlock: Player.Unlock = undefined;
|
||||
|
||||
unlock.unlocked_systems = try loadArray(
|
||||
@@ -164,7 +175,7 @@ fn loadUnlockComponent(io: Io, gpa: Allocator, data_dir: Io.Dir, uid: u64) !Play
|
||||
return unlock;
|
||||
}
|
||||
|
||||
fn loadCharBagComponent(io: Io, gpa: Allocator, data_dir: Io.Dir, uid: u64) !Player.CharBag {
|
||||
fn loadCharBagComponent(io: Io, gpa: Allocator, data_dir: Io.Dir, uid: []const u8) !Player.CharBag {
|
||||
const char_bag_dir = data_dir.openDir(io, char_bag_path, .{}) catch |err| switch (err) {
|
||||
error.FileNotFound => return error.NeedsReset,
|
||||
error.Canceled => |e| return e,
|
||||
@@ -195,14 +206,14 @@ fn loadCharBagComponent(io: Io, gpa: Allocator, data_dir: Io.Dir, uid: u64) !Pla
|
||||
inline error.FileNotFound, error.ChecksumMismatch, error.ReprSizeMismatch => |e| reset: {
|
||||
if (e == error.ChecksumMismatch) {
|
||||
log.err(
|
||||
"checksum mismatched for char bag metadata of player {d}, resetting to defaults.",
|
||||
"checksum mismatched for char bag metadata of player {s}, resetting to defaults.",
|
||||
.{uid},
|
||||
);
|
||||
}
|
||||
|
||||
if (e == error.ReprSizeMismatch) {
|
||||
log.err(
|
||||
"struct layout mismatched for char bag metadata of player {d}, resetting to defaults.",
|
||||
"struct layout mismatched for char bag metadata of player {s}, resetting to defaults.",
|
||||
.{uid},
|
||||
);
|
||||
}
|
||||
@@ -398,19 +409,19 @@ pub fn saveCharBagComponent(
|
||||
}
|
||||
}
|
||||
|
||||
fn loadBitsetComponent(io: Io, data_dir: Io.Dir, uid: u64) !Player.Bitset {
|
||||
fn loadBitsetComponent(io: Io, data_dir: Io.Dir, uid: []const u8) !Player.Bitset {
|
||||
return fs.loadStruct(Player.Bitset, io, data_dir, bitset_file) catch |err| switch (err) {
|
||||
inline error.FileNotFound, error.ChecksumMismatch, error.ReprSizeMismatch => |e| {
|
||||
if (e == error.ChecksumMismatch) {
|
||||
log.err(
|
||||
"checksum mismatched for bitset of player {d}, resetting to defaults.",
|
||||
"checksum mismatched for bitset of player {s}, resetting to defaults.",
|
||||
.{uid},
|
||||
);
|
||||
}
|
||||
|
||||
if (e == error.ReprSizeMismatch) {
|
||||
log.err(
|
||||
"struct layout mismatched for bitset of player {d}, resetting to defaults.",
|
||||
"struct layout mismatched for bitset of player {s}, resetting to defaults.",
|
||||
.{uid},
|
||||
);
|
||||
}
|
||||
@@ -443,12 +454,81 @@ fn createDefaultBitsetComponent(io: Io, data_dir: Io.Dir, assets: *const Assets)
|
||||
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(
|
||||
comptime T: type,
|
||||
io: Io,
|
||||
gpa: Allocator,
|
||||
data_dir: Io.Dir,
|
||||
uid: u64,
|
||||
uid: []const u8,
|
||||
sub_path: []const u8,
|
||||
defaults: []const T,
|
||||
) ![]T {
|
||||
@@ -456,14 +536,14 @@ fn loadArray(
|
||||
inline error.FileNotFound, error.ChecksumMismatch, error.ReprSizeMismatch => |e| reset: {
|
||||
if (e == error.ChecksumMismatch) {
|
||||
log.err(
|
||||
"checksum mismatched for '{s}' of player {d}, resetting to defaults.",
|
||||
"checksum mismatched for '{s}' of player {s}, resetting to defaults.",
|
||||
.{ sub_path, uid },
|
||||
);
|
||||
}
|
||||
|
||||
if (e == error.ReprSizeMismatch) {
|
||||
log.err(
|
||||
"struct layout mismatched for '{s}' of player {d}, resetting to defaults.",
|
||||
"struct layout mismatched for '{s}' of player {s}, resetting to defaults.",
|
||||
.{ sub_path, uid },
|
||||
);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ pub const Unlock = @import("Player/Unlock.zig");
|
||||
pub const CharBag = @import("Player/CharBag.zig");
|
||||
pub const ItemBag = @import("Player/ItemBag.zig");
|
||||
pub const Bitset = @import("Player/Bitset.zig");
|
||||
pub const Scene = @import("Player/Scene.zig");
|
||||
|
||||
base: Base,
|
||||
game_vars: GameVars,
|
||||
@@ -17,6 +18,7 @@ unlock: Unlock,
|
||||
char_bag: CharBag,
|
||||
item_bag: ItemBag,
|
||||
bitset: Bitset,
|
||||
scene: Scene,
|
||||
|
||||
pub fn deinit(player: *Player, gpa: Allocator) void {
|
||||
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,
|
||||
};
|
||||
@@ -1,6 +1,7 @@
|
||||
// Describes player-local state of the world.
|
||||
const World = @This();
|
||||
const std = @import("std");
|
||||
const mem = @import("common").mem;
|
||||
const logic = @import("../logic.zig");
|
||||
const Session = @import("../Session.zig");
|
||||
const Assets = @import("../Assets.zig");
|
||||
@@ -8,7 +9,11 @@ const Assets = @import("../Assets.zig");
|
||||
const Io = std.Io;
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
pub const PlayerId = struct { uid: u64 };
|
||||
pub const PlayerId = struct {
|
||||
pub const max_length: usize = 16;
|
||||
|
||||
uid: mem.LimitedString(max_length),
|
||||
};
|
||||
|
||||
player_id: PlayerId,
|
||||
session: *Session, // TODO: should it be here this way? Do we need an abstraction?
|
||||
@@ -18,7 +23,7 @@ player: logic.Player,
|
||||
pub fn init(
|
||||
session: *Session,
|
||||
assets: *const Assets,
|
||||
uid: u64,
|
||||
uid: mem.LimitedString(PlayerId.max_length),
|
||||
player: logic.Player,
|
||||
gpa: Allocator,
|
||||
io: Io,
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
pub const Login = struct {};
|
||||
|
||||
pub const ChangeSceneBegin = struct {};
|
||||
|
||||
pub const CurrentSceneModified = struct {};
|
||||
|
||||
pub const CharBagTeamModified = struct {
|
||||
team_index: usize,
|
||||
modification: enum {
|
||||
|
||||
@@ -15,6 +15,7 @@ const namespaces = &.{
|
||||
@import("messaging/scene.zig"),
|
||||
@import("messaging/char_bag.zig"),
|
||||
@import("messaging/friend_chat.zig"),
|
||||
@import("messaging/map_mark.zig"),
|
||||
};
|
||||
|
||||
pub fn Request(comptime CSType: type) type {
|
||||
|
||||
56
gamesv/src/logic/messaging/map_mark.zig
Normal file
56
gamesv/src/logic/messaging/map_mark.zig
Normal file
@@ -0,0 +1,56 @@
|
||||
const std = @import("std");
|
||||
const pb = @import("proto").pb;
|
||||
const logic = @import("../../logic.zig");
|
||||
const Assets = @import("../../Assets.zig");
|
||||
|
||||
const Player = logic.Player;
|
||||
const messaging = logic.messaging;
|
||||
|
||||
pub fn onSceneSetTrackPoint(
|
||||
request: messaging.Request(pb.CS_SCENE_SET_TRACK_POINT),
|
||||
assets: *const Assets,
|
||||
scene: Player.Component(.scene),
|
||||
change_scene_tx: logic.event.Sender(.change_scene_begin),
|
||||
cur_scene_modified_tx: logic.event.Sender(.current_scene_modified),
|
||||
) !void {
|
||||
const log = std.log.scoped(.scene_set_track_point);
|
||||
|
||||
const track_point = request.message.track_point orelse return;
|
||||
const point_config = assets.map_mark_table.get(track_point.inst_id) orelse {
|
||||
log.debug("invalid point instance id: '{s}'", .{track_point.inst_id});
|
||||
return;
|
||||
};
|
||||
|
||||
const teleport_validation = point_config.teleportValidationData() orelse {
|
||||
// Not a teleport point.
|
||||
return;
|
||||
};
|
||||
|
||||
const validation_config = assets.teleport_validation_table.teleportValidationDatas.map.getPtr(teleport_validation.teleportValidationId) orelse {
|
||||
log.debug(
|
||||
"teleport validation config '{s}' doesn't exist",
|
||||
.{teleport_validation.teleportValidationId},
|
||||
);
|
||||
return;
|
||||
};
|
||||
|
||||
const level_config = assets.level_config_table.getPtr(validation_config.sceneId) orelse {
|
||||
log.debug("level with id '{s}' doesn't exist", .{validation_config.sceneId});
|
||||
return;
|
||||
};
|
||||
|
||||
scene.data.current.level_id = level_config.idNum;
|
||||
scene.data.current.position = .{
|
||||
validation_config.position.x,
|
||||
validation_config.position.y,
|
||||
validation_config.position.z,
|
||||
};
|
||||
|
||||
try cur_scene_modified_tx.send(.{});
|
||||
try change_scene_tx.send(.{});
|
||||
|
||||
log.info(
|
||||
"transitioning to scene '{s}', position: {any}",
|
||||
.{ validation_config.sceneId, scene.data.current.position },
|
||||
);
|
||||
}
|
||||
@@ -15,12 +15,12 @@ pub fn saveCharBagTeams(
|
||||
player_id: logic.World.PlayerId,
|
||||
io: Io,
|
||||
) !void {
|
||||
const data_dir = fs.persistence.openPlayerDataDir(io, player_id.uid) catch |err| switch (err) {
|
||||
const data_dir = fs.persistence.openPlayerDataDir(io, player_id.uid.view()) catch |err| switch (err) {
|
||||
error.Canceled => |e| return e,
|
||||
else => |e| {
|
||||
log.err(
|
||||
"failed to open data dir for player with uid {d}: {t}",
|
||||
.{ player_id.uid, e },
|
||||
"failed to open data dir for player with uid {s}: {t}",
|
||||
.{ player_id.uid.view(), e },
|
||||
);
|
||||
return;
|
||||
},
|
||||
@@ -36,3 +36,31 @@ pub fn saveCharBagTeams(
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
pub fn saveCurrentScene(
|
||||
_: logic.event.Receiver(.current_scene_modified),
|
||||
scene: Player.Component(.scene),
|
||||
player_id: logic.World.PlayerId,
|
||||
io: Io,
|
||||
) !void {
|
||||
const data_dir = fs.persistence.openPlayerDataDir(io, player_id.uid.view()) catch |err| switch (err) {
|
||||
error.Canceled => |e| return e,
|
||||
else => |e| {
|
||||
log.err(
|
||||
"failed to open data dir for player with uid {s}: {t}",
|
||||
.{ player_id.uid.view(), e },
|
||||
);
|
||||
return;
|
||||
},
|
||||
};
|
||||
|
||||
defer data_dir.close(io);
|
||||
|
||||
fs.persistence.saveSceneComponent(io, data_dir, scene.data) catch |err| switch (err) {
|
||||
error.Canceled => |e| return e,
|
||||
else => |e| {
|
||||
log.err("save failed: {t}", .{e});
|
||||
return;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -8,32 +8,37 @@ const Player = logic.Player;
|
||||
const ArrayList = std.ArrayList;
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
const default_level = "map02_lv001";
|
||||
|
||||
pub fn enterSceneOnLogin(
|
||||
rx: logic.event.Receiver(.login),
|
||||
tx: logic.event.Sender(.change_scene_begin),
|
||||
) !void {
|
||||
_ = rx;
|
||||
try tx.send(.{});
|
||||
}
|
||||
|
||||
pub fn beginChangingScene(
|
||||
rx: logic.event.Receiver(.change_scene_begin),
|
||||
session: *Session,
|
||||
assets: *const Assets,
|
||||
base_comp: Player.Component(.base),
|
||||
base: Player.Component(.base),
|
||||
scene: Player.Component(.scene),
|
||||
) !void {
|
||||
_ = rx;
|
||||
|
||||
const level_config = assets.level_config_table.getPtr(default_level).?;
|
||||
const position: pb.VECTOR = .{
|
||||
.X = level_config.playerInitPos.x,
|
||||
.Y = level_config.playerInitPos.y,
|
||||
.Z = level_config.playerInitPos.z,
|
||||
.X = scene.data.current.position[0],
|
||||
.Y = scene.data.current.position[1],
|
||||
.Z = scene.data.current.position[2],
|
||||
};
|
||||
|
||||
try session.send(pb.SC_CHANGE_SCENE_BEGIN_NOTIFY{
|
||||
.scene_num_id = level_config.idNum,
|
||||
.scene_num_id = scene.data.current.level_id,
|
||||
.position = position,
|
||||
.pass_through_data = .init,
|
||||
});
|
||||
|
||||
try session.send(pb.SC_ENTER_SCENE_NOTIFY{
|
||||
.role_id = base_comp.data.role_id,
|
||||
.scene_num_id = level_config.idNum,
|
||||
.role_id = base.data.role_id,
|
||||
.scene_num_id = scene.data.current.level_id,
|
||||
.position = position,
|
||||
.pass_through_data = .init,
|
||||
});
|
||||
@@ -57,7 +62,8 @@ pub fn syncSelfScene(
|
||||
rx: logic.event.Receiver(.sync_self_scene),
|
||||
session: *Session,
|
||||
arena: logic.Resource.Allocator(.arena),
|
||||
char_bag: logic.Player.Component(.char_bag),
|
||||
char_bag: Player.Component(.char_bag),
|
||||
scene: Player.Component(.scene),
|
||||
assets: *const Assets,
|
||||
) !void {
|
||||
const reason: pb.SELF_INFO_REASON_TYPE = switch (rx.payload.reason) {
|
||||
@@ -65,18 +71,17 @@ pub fn syncSelfScene(
|
||||
.team_modified => .SLR_CHANGE_TEAM,
|
||||
};
|
||||
|
||||
const level_config = assets.level_config_table.getPtr(default_level).?;
|
||||
const position: pb.VECTOR = .{
|
||||
.X = level_config.playerInitPos.x,
|
||||
.Y = level_config.playerInitPos.y,
|
||||
.Z = level_config.playerInitPos.z,
|
||||
.X = scene.data.current.position[0],
|
||||
.Y = scene.data.current.position[1],
|
||||
.Z = scene.data.current.position[2],
|
||||
};
|
||||
|
||||
const team_index = char_bag.data.meta.curr_team_index;
|
||||
const leader_index = char_bag.data.teams.items(.leader_index)[team_index];
|
||||
|
||||
var self_scene_info: pb.SC_SELF_SCENE_INFO = .{
|
||||
.scene_num_id = level_config.idNum,
|
||||
.scene_num_id = scene.data.current.level_id,
|
||||
.self_info_reason = @intFromEnum(reason),
|
||||
.teamInfo = .{
|
||||
.team_type = .CHAR_BAG_TEAM_TYPE_MAIN,
|
||||
@@ -106,7 +111,7 @@ pub fn syncSelfScene(
|
||||
.templateid = char_template_id,
|
||||
.position = position,
|
||||
.rotation = .{},
|
||||
.scene_num_id = level_config.idNum,
|
||||
.scene_num_id = scene.data.current.level_id,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user