- better respond time - import BuffInfoConfig.json - implemented custom mode for challenge mode to sellect older MoC/PF/AS
354 lines
15 KiB
Zig
354 lines
15 KiB
Zig
const std = @import("std");
|
|
const protocol = @import("protocol");
|
|
const Session = @import("../session.zig");
|
|
const Packet = @import("../Packet.zig");
|
|
const Config = @import("../services/config.zig");
|
|
const Res_config = @import("../services/res_config.zig");
|
|
const Item = @import("../services/item.zig");
|
|
const UidGenerator = Item.UidGenerator();
|
|
const ArrayList = std.ArrayList;
|
|
const Allocator = std.mem.Allocator;
|
|
|
|
pub const SceneManager = struct {
|
|
allocator: Allocator,
|
|
|
|
pub fn init(allocator: Allocator) SceneManager {
|
|
return SceneManager{ .allocator = allocator };
|
|
}
|
|
|
|
fn addAvatarEntities(
|
|
scene_group: *protocol.SceneEntityGroupInfo,
|
|
avatar_configs: []const Config.Avatar,
|
|
tele_pos: protocol.Vector,
|
|
tele_rot: protocol.Vector,
|
|
uid: u32,
|
|
) !void {
|
|
for (avatar_configs) |avatarConf| {
|
|
try scene_group.entity_list.append(.{
|
|
.inst_id = 1,
|
|
.entity_id = @intCast(avatarConf.id + 100000),
|
|
.entity = .{ .actor = .{
|
|
.base_avatar_id = avatarConf.id,
|
|
.avatar_type = .AVATAR_FORMAL_TYPE,
|
|
.uid = uid,
|
|
.map_layer = 0,
|
|
} },
|
|
.motion = .{ .pos = tele_pos, .rot = tele_rot },
|
|
});
|
|
}
|
|
}
|
|
fn addPropEntities(
|
|
allocator: Allocator,
|
|
group_map: *std.AutoHashMap(u32, protocol.SceneEntityGroupInfo),
|
|
prop_configs: []const Res_config.Props,
|
|
generator: *UidGenerator,
|
|
) !void {
|
|
for (prop_configs) |propConf| {
|
|
var scene_group = try getOrCreateGroup(group_map, propConf.groupId, allocator);
|
|
var prop_info = protocol.ScenePropInfo.init(allocator);
|
|
prop_info.prop_id = propConf.propId;
|
|
prop_info.prop_state = propConf.propState;
|
|
try scene_group.entity_list.append(.{
|
|
.entity = .{ .prop = prop_info },
|
|
.group_id = scene_group.group_id,
|
|
.inst_id = propConf.instId,
|
|
.entity_id = 1000 + generator.nextId(),
|
|
.motion = .{
|
|
.pos = .{ .x = propConf.pos.x, .y = propConf.pos.y, .z = propConf.pos.z },
|
|
.rot = .{ .x = propConf.rot.x, .y = propConf.rot.y, .z = propConf.rot.z },
|
|
},
|
|
});
|
|
}
|
|
}
|
|
fn addMonsterEntities(
|
|
allocator: Allocator,
|
|
group_map: *std.AutoHashMap(u32, protocol.SceneEntityGroupInfo),
|
|
monster_configs: []const Res_config.Monsters,
|
|
generator: *UidGenerator,
|
|
) !void {
|
|
for (monster_configs) |monsConf| {
|
|
var scene_group = try getOrCreateGroup(group_map, monsConf.groupId, allocator);
|
|
var monster_info = protocol.SceneNpcMonsterInfo.init(allocator);
|
|
monster_info.monster_id = monsConf.monsterId;
|
|
monster_info.event_id = monsConf.eventId;
|
|
monster_info.world_level = 6;
|
|
try scene_group.entity_list.append(.{
|
|
.entity = .{ .npc_monster = monster_info },
|
|
.group_id = scene_group.group_id,
|
|
.inst_id = monsConf.instId,
|
|
.entity_id = if ((monsConf.monsterId / 1000) % 10 == 3) monster_info.monster_id else generator.nextId(),
|
|
.motion = .{
|
|
.pos = .{ .x = monsConf.pos.x, .y = monsConf.pos.y, .z = monsConf.pos.z },
|
|
.rot = .{ .x = monsConf.rot.x, .y = monsConf.rot.y, .z = monsConf.rot.z },
|
|
},
|
|
});
|
|
}
|
|
}
|
|
pub fn createScene(
|
|
self: *SceneManager,
|
|
plane_id: u32,
|
|
floor_id: u32,
|
|
entry_id: u32,
|
|
teleport_id: u32,
|
|
) !protocol.SceneInfo {
|
|
const config = try Config.loadGameConfig(self.allocator, "config.json");
|
|
const res_config = global_game_config_cache.res_config;
|
|
var generator = Item.UidGenerator().init();
|
|
|
|
var scene_info = protocol.SceneInfo.init(self.allocator);
|
|
scene_info.game_mode_type = 1;
|
|
scene_info.plane_id = plane_id;
|
|
scene_info.floor_id = floor_id;
|
|
scene_info.entry_id = entry_id;
|
|
scene_info.leader_entity_id = config.avatar_config.items[0].id + 100000;
|
|
scene_info.world_id = 501;
|
|
scene_info.client_pos_version = 1;
|
|
|
|
var group_map = std.AutoHashMap(u32, protocol.SceneEntityGroupInfo).init(self.allocator);
|
|
defer group_map.deinit();
|
|
|
|
for (res_config.scene_config.items) |sceneConf| {
|
|
for (sceneConf.teleports.items) |teleConf| {
|
|
if (teleConf.teleportId == teleport_id) {
|
|
var scene_group = protocol.SceneEntityGroupInfo.init(self.allocator);
|
|
scene_group.state = 1;
|
|
const proto_tele_pos = protocol.Vector{
|
|
.x = teleConf.pos.x,
|
|
.y = teleConf.pos.y,
|
|
.z = teleConf.pos.z,
|
|
};
|
|
const proto_tele_rot = protocol.Vector{
|
|
.x = teleConf.rot.x,
|
|
.y = teleConf.rot.y,
|
|
.z = teleConf.rot.z,
|
|
};
|
|
|
|
try addAvatarEntities(&scene_group, config.avatar_config.items, proto_tele_pos, proto_tele_rot, 0);
|
|
try scene_info.entity_group_list.append(scene_group);
|
|
break;
|
|
}
|
|
}
|
|
if (scene_info.plane_id != 10000 and scene_info.plane_id != 10202 and sceneConf.planeID == scene_info.plane_id) {
|
|
try addPropEntities(self.allocator, &group_map, sceneConf.props.items, &generator);
|
|
try addMonsterEntities(self.allocator, &group_map, sceneConf.monsters.items, &generator);
|
|
}
|
|
}
|
|
|
|
var iter = group_map.iterator();
|
|
while (iter.next()) |entry| {
|
|
try scene_info.entity_group_list.append(entry.value_ptr.*);
|
|
try scene_info.entity_list.appendSlice(entry.value_ptr.entity_list.items);
|
|
try scene_info.DJBIBIJMEBH.append(entry.value_ptr.group_id);
|
|
try scene_info.custom_data_list.append(protocol.CustomSaveData{
|
|
.group_id = entry.value_ptr.group_id,
|
|
});
|
|
try scene_info.group_state_list.append(protocol.SceneGroupState{
|
|
.group_id = entry.value_ptr.group_id,
|
|
.state = 0,
|
|
.is_default = true,
|
|
});
|
|
}
|
|
const ranges = [_][2]usize{
|
|
.{ 0, 101 },
|
|
.{ 10000, 10051 },
|
|
.{ 20000, 20001 },
|
|
.{ 30000, 30020 },
|
|
};
|
|
for (ranges) |range| {
|
|
for (range[0]..range[1]) |i| {
|
|
try scene_info.lighten_section_list.append(@intCast(i));
|
|
}
|
|
}
|
|
return scene_info;
|
|
}
|
|
fn getOrCreateGroup(group_map: *std.AutoHashMap(u32, protocol.SceneEntityGroupInfo), group_id: u32, allocator: Allocator) !*protocol.SceneEntityGroupInfo {
|
|
if (group_map.getPtr(group_id)) |existing_group| {
|
|
return existing_group;
|
|
}
|
|
var new_group = protocol.SceneEntityGroupInfo.init(allocator);
|
|
new_group.state = 1;
|
|
new_group.group_id = group_id;
|
|
try group_map.put(group_id, new_group);
|
|
return group_map.getPtr(group_id).?;
|
|
}
|
|
};
|
|
|
|
pub const ChallengeSceneManager = struct {
|
|
allocator: Allocator,
|
|
|
|
pub fn init(allocator: Allocator) ChallengeSceneManager {
|
|
return ChallengeSceneManager{ .allocator = allocator };
|
|
}
|
|
pub fn createScene(
|
|
self: *ChallengeSceneManager,
|
|
avatar_list: ArrayList(u32),
|
|
plane_id: u32,
|
|
floor_id: u32,
|
|
entry_id: u32,
|
|
world_id: u32,
|
|
monster_id: u32,
|
|
event_id: u32,
|
|
group_id: u32,
|
|
maze_group_id: u32,
|
|
) !protocol.SceneInfo {
|
|
const res_config = global_game_config_cache.res_config;
|
|
var generator = Item.UidGenerator().init();
|
|
|
|
var scene_info = protocol.SceneInfo.init(self.allocator);
|
|
scene_info.game_mode_type = 4;
|
|
scene_info.plane_id = plane_id;
|
|
scene_info.floor_id = floor_id;
|
|
scene_info.entry_id = entry_id;
|
|
scene_info.leader_entity_id = avatar_list.items[0];
|
|
scene_info.world_id = world_id;
|
|
try scene_info.group_state_list.append(protocol.SceneGroupState{
|
|
.group_id = maze_group_id,
|
|
.is_default = true,
|
|
});
|
|
{ // Character Group
|
|
var scene_group = protocol.SceneEntityGroupInfo.init(self.allocator);
|
|
scene_group.state = 1;
|
|
scene_group.group_id = 0;
|
|
for (avatar_list.items) |avatar_base_id| {
|
|
try scene_group.entity_list.append(.{
|
|
.inst_id = 1,
|
|
.entity_id = @intCast(avatar_base_id + 100000),
|
|
.entity = .{
|
|
.actor = .{
|
|
.base_avatar_id = avatar_base_id,
|
|
.avatar_type = .AVATAR_FORMAL_TYPE,
|
|
.uid = 1,
|
|
.map_layer = 0,
|
|
},
|
|
},
|
|
.motion = .{ .pos = .{}, .rot = .{} },
|
|
});
|
|
}
|
|
try scene_info.entity_group_list.append(scene_group);
|
|
}
|
|
for (res_config.scene_config.items) |sceneConf| {
|
|
if (sceneConf.planeID == scene_info.plane_id) {
|
|
for (sceneConf.monsters.items) |monsConf| {
|
|
if (monsConf.groupId == group_id) {
|
|
var scene_group = protocol.SceneEntityGroupInfo.init(self.allocator);
|
|
scene_group.state = 1;
|
|
scene_group.group_id = group_id;
|
|
|
|
var monster_info = protocol.SceneNpcMonsterInfo.init(self.allocator);
|
|
monster_info.monster_id = monster_id;
|
|
monster_info.event_id = event_id;
|
|
monster_info.world_level = 6;
|
|
|
|
try scene_group.entity_list.append(.{
|
|
.entity = .{ .npc_monster = monster_info },
|
|
.group_id = group_id,
|
|
.inst_id = monsConf.instId,
|
|
.entity_id = generator.nextId(),
|
|
.motion = .{
|
|
.pos = .{ .x = monsConf.pos.x, .y = monsConf.pos.y, .z = monsConf.pos.z },
|
|
.rot = .{ .x = monsConf.rot.x, .y = monsConf.rot.y, .z = monsConf.rot.z },
|
|
},
|
|
});
|
|
try scene_info.entity_group_list.append(scene_group);
|
|
break;
|
|
}
|
|
}
|
|
for (sceneConf.props.items) |propConf| {
|
|
var scene_group = protocol.SceneEntityGroupInfo.init(self.allocator);
|
|
scene_group.state = 1;
|
|
scene_group.group_id = group_id;
|
|
|
|
var prop_info = protocol.ScenePropInfo.init(self.allocator);
|
|
prop_info.prop_id = propConf.propId;
|
|
prop_info.prop_state = propConf.propState;
|
|
|
|
try scene_group.entity_list.append(.{
|
|
.entity = .{ .prop = prop_info },
|
|
.group_id = group_id,
|
|
.inst_id = propConf.instId,
|
|
.entity_id = generator.nextId(),
|
|
.motion = .{
|
|
.pos = .{ .x = propConf.pos.x, .y = propConf.pos.y, .z = propConf.pos.z },
|
|
.rot = .{ .x = propConf.rot.x, .y = propConf.rot.y, .z = propConf.rot.z },
|
|
},
|
|
});
|
|
try scene_info.entity_group_list.append(scene_group);
|
|
}
|
|
}
|
|
}
|
|
return scene_info;
|
|
}
|
|
};
|
|
pub const MazeMapManager = struct {
|
|
allocator: Allocator,
|
|
pub fn init(allocator: Allocator) MazeMapManager {
|
|
return MazeMapManager{ .allocator = allocator };
|
|
}
|
|
pub fn setMazeMapData(
|
|
self: *MazeMapManager,
|
|
map_info: *protocol.SceneMapInfo,
|
|
floor_id: u32,
|
|
) !void {
|
|
const map_entrance_config = global_game_config_cache.map_entrance_config;
|
|
|
|
const res_config = global_game_config_cache.res_config;
|
|
var plane_ids = ArrayList(u32).init(self.allocator);
|
|
defer plane_ids.deinit();
|
|
for (map_entrance_config.map_entrance_config.items) |entrConf| {
|
|
if (entrConf.floor_id == floor_id) {
|
|
try plane_ids.append(entrConf.plane_id);
|
|
}
|
|
}
|
|
map_info.maze_group_list = ArrayList(protocol.MazeGroup).init(self.allocator);
|
|
map_info.maze_prop_list = ArrayList(protocol.MazePropState).init(self.allocator);
|
|
for (res_config.scene_config.items) |sceneConf| {
|
|
for (plane_ids.items) |plane_id| {
|
|
if (sceneConf.planeID == plane_id) {
|
|
for (sceneConf.props.items) |propConf| {
|
|
try map_info.maze_group_list.append(protocol.MazeGroup{
|
|
.NOBKEONAKLE = ArrayList(u32).init(self.allocator),
|
|
.group_id = propConf.groupId,
|
|
});
|
|
try map_info.maze_prop_list.append(protocol.MazePropState{
|
|
.group_id = propConf.groupId,
|
|
.config_id = propConf.instId,
|
|
.state = propConf.propState,
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
pub const GameConfigCache = struct {
|
|
allocator: Allocator,
|
|
res_config: Res_config.SceneConfig,
|
|
map_entrance_config: Config.MapEntranceConfig,
|
|
stage_config: Config.StageConfig,
|
|
|
|
pub fn init(allocator: Allocator) !GameConfigCache {
|
|
const res_cfg = try Res_config.anchorLoader(allocator, "resources/res.json");
|
|
const map_entr_cfg = try Config.loadMapEntranceConfig(allocator, "resources/MapEntrance.json");
|
|
const stage_cfg = try Config.loadStageConfig(allocator, "resources/StageConfig.json");
|
|
|
|
return GameConfigCache{
|
|
.allocator = allocator,
|
|
.res_config = res_cfg,
|
|
.map_entrance_config = map_entr_cfg,
|
|
.stage_config = stage_cfg,
|
|
};
|
|
}
|
|
pub fn deinit(_: *GameConfigCache) void {}
|
|
};
|
|
|
|
pub var global_game_config_cache: GameConfigCache = undefined;
|
|
pub var global_main_allocator: Allocator = undefined;
|
|
|
|
pub fn initGameGlobals(main_allocator: Allocator) !void {
|
|
global_main_allocator = main_allocator;
|
|
global_game_config_cache = try GameConfigCache.init(main_allocator);
|
|
}
|
|
|
|
pub fn deinitGameGlobals() void {
|
|
global_game_config_cache.deinit();
|
|
}
|