mirror of
https://github.com/OpenFusionProject/OpenFusion.git
synced 2026-01-01 15:41:03 +00:00
Compare commits
9 Commits
patchmap
...
f9e61a61b3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f9e61a61b3 | ||
| d3bef95a7f | |||
|
|
650f947451 | ||
|
|
613a4c58a3 | ||
|
|
177565dc55 | ||
|
|
b12aecad63 | ||
|
|
5bf0c8f3ea | ||
|
|
2ddc956c9b | ||
|
|
4f0ae027a5 |
1
.dockerignore
Normal file
1
.dockerignore
Normal file
@@ -0,0 +1 @@
|
|||||||
|
version.h
|
||||||
26
.vscode/launch.json
vendored
Normal file
26
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Debug (Linux)",
|
||||||
|
"type": "cppdbg",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "${workspaceFolder}/bin/fusion",
|
||||||
|
"cwd": "${workspaceFolder}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Debug (Windows)",
|
||||||
|
"type": "cppvsdbg",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "${workspaceFolder}/bin/Debug/winfusion.exe",
|
||||||
|
"cwd": "${workspaceFolder}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Release (Windows)",
|
||||||
|
"type": "cppvsdbg",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "${workspaceFolder}/bin/Release/winfusion.exe",
|
||||||
|
"cwd": "${workspaceFolder}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -44,7 +44,7 @@ add_executable(openfusion ${SOURCES})
|
|||||||
set_target_properties(openfusion PROPERTIES OUTPUT_NAME ${BIN_NAME})
|
set_target_properties(openfusion PROPERTIES OUTPUT_NAME ${BIN_NAME})
|
||||||
|
|
||||||
# find sqlite3 and use it
|
# find sqlite3 and use it
|
||||||
find_package(sqlite3 REQUIRED)
|
find_package(SQLite3 REQUIRED)
|
||||||
target_include_directories(openfusion PRIVATE ${SQLite3_INCLUDE_DIRS})
|
target_include_directories(openfusion PRIVATE ${SQLite3_INCLUDE_DIRS})
|
||||||
target_link_libraries(openfusion PRIVATE ${SQLite3_LIBRARIES})
|
target_link_libraries(openfusion PRIVATE ${SQLite3_LIBRARIES})
|
||||||
|
|
||||||
@@ -56,5 +56,5 @@ set_property(TARGET openfusion PROPERTY VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_S
|
|||||||
# It's not something you should do, but it's there if you need it...
|
# It's not something you should do, but it's there if you need it...
|
||||||
if (NOT CMAKE_GENERATOR MATCHES "Visual Studio" AND NOT CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" AND NOT CMAKE_GENERATOR MATCHES "MinGW Makefiles")
|
if (NOT CMAKE_GENERATOR MATCHES "Visual Studio" AND NOT CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" AND NOT CMAKE_GENERATOR MATCHES "MinGW Makefiles")
|
||||||
find_package(Threads REQUIRED)
|
find_package(Threads REQUIRED)
|
||||||
target_link_libraries(openfusion pthread)
|
target_link_libraries(openfusion PRIVATE pthread)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
21
Dockerfile
Normal file
21
Dockerfile
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
FROM debian:latest
|
||||||
|
|
||||||
|
WORKDIR /usr/src/app
|
||||||
|
|
||||||
|
RUN apt-get -y update && apt-get install -y \
|
||||||
|
git \
|
||||||
|
clang \
|
||||||
|
make \
|
||||||
|
libsqlite3-dev
|
||||||
|
|
||||||
|
COPY . ./
|
||||||
|
|
||||||
|
RUN make -j8
|
||||||
|
|
||||||
|
# tabledata should be copied from the host;
|
||||||
|
# clone it there before building the container
|
||||||
|
#RUN git submodule update --init --recursive
|
||||||
|
|
||||||
|
CMD ["./bin/fusion"]
|
||||||
|
|
||||||
|
LABEL Name=openfusion Version=0.0.1
|
||||||
12
config.ini
12
config.ini
@@ -1,8 +1,3 @@
|
|||||||
# name of the client build the server is targetting.
|
|
||||||
# used for determining which patches to apply.
|
|
||||||
# default is beta-20111013 for Academy, beta-20100104 otherwise.
|
|
||||||
#buildname=beta-20100104
|
|
||||||
|
|
||||||
# verbosity level
|
# verbosity level
|
||||||
# 0 = mostly silence
|
# 0 = mostly silence
|
||||||
# 1 = debug prints and unknown packets
|
# 1 = debug prints and unknown packets
|
||||||
@@ -51,6 +46,11 @@ motd=Welcome to OpenFusion!
|
|||||||
# location of the patch folder
|
# location of the patch folder
|
||||||
#patchdir=tdata/patch/
|
#patchdir=tdata/patch/
|
||||||
|
|
||||||
|
# Space-separated list of patch folders in patchdir to load from.
|
||||||
|
# If you uncomment this, note that Academy builds *must* contain 1013,
|
||||||
|
# and pre-Academy builds must *not* contain it.
|
||||||
|
#enabledpatches=1013
|
||||||
|
|
||||||
# xdt json filename
|
# xdt json filename
|
||||||
#xdtdata=xdt.json
|
#xdtdata=xdt.json
|
||||||
# NPC json filename
|
# NPC json filename
|
||||||
@@ -61,8 +61,6 @@ motd=Welcome to OpenFusion!
|
|||||||
#pathdata=paths.json
|
#pathdata=paths.json
|
||||||
# drop json filename
|
# drop json filename
|
||||||
#dropdata=drops.json
|
#dropdata=drops.json
|
||||||
# patchmap json filename
|
|
||||||
#patchmapdata=patchmap.json
|
|
||||||
# gruntwork output filename (this is what you submit)
|
# gruntwork output filename (this is what you submit)
|
||||||
#gruntwork=gruntwork.json
|
#gruntwork=gruntwork.json
|
||||||
# location of the database
|
# location of the database
|
||||||
|
|||||||
12
docker-compose.yml
Normal file
12
docker-compose.yml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
version: '3.4'
|
||||||
|
|
||||||
|
services:
|
||||||
|
openfusion:
|
||||||
|
image: openfusion
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: ./Dockerfile
|
||||||
|
ports:
|
||||||
|
- "23000:23000"
|
||||||
|
- "23001:23001"
|
||||||
|
- "8003:8003"
|
||||||
@@ -358,23 +358,19 @@ static void npcRotateCommand(std::string full, std::vector<std::string>& args, C
|
|||||||
int angle = (plr->angle + 180) % 360;
|
int angle = (plr->angle + 180) % 360;
|
||||||
NPCManager::updateNPCPosition(npc->appearanceData.iNPC_ID, npc->x, npc->y, npc->z, npc->instanceID, angle);
|
NPCManager::updateNPCPosition(npc->appearanceData.iNPC_ID, npc->x, npc->y, npc->z, npc->instanceID, angle);
|
||||||
|
|
||||||
// if it's a gruntwork NPC, rotate in-place
|
bool isGruntworkNpc = true;
|
||||||
if (TableData::RunningMobs.find(npc->appearanceData.iNPC_ID) != TableData::RunningMobs.end()) {
|
|
||||||
NPCManager::updateNPCPosition(npc->appearanceData.iNPC_ID, npc->x, npc->y, npc->z, npc->instanceID, angle);
|
|
||||||
|
|
||||||
Chat::sendServerMessage(sock, "[NPCR] Successfully set angle to " + std::to_string(angle) + " for gruntwork NPC "
|
// add a rotation entry to the gruntwork file, unless it's already a gruntwork NPC
|
||||||
+ std::to_string(npc->appearanceData.iNPC_ID));
|
if (TableData::RunningMobs.find(npc->appearanceData.iNPC_ID) == TableData::RunningMobs.end()) {
|
||||||
} else {
|
|
||||||
TableData::RunningNPCRotations[npc->appearanceData.iNPC_ID] = angle;
|
TableData::RunningNPCRotations[npc->appearanceData.iNPC_ID] = angle;
|
||||||
|
isGruntworkNpc = false;
|
||||||
Chat::sendServerMessage(sock, "[NPCR] Successfully set angle to " + std::to_string(angle) + " for NPC "
|
|
||||||
+ std::to_string(npc->appearanceData.iNPC_ID));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// update rotation clientside
|
Chat::sendServerMessage(sock, "[NPCR] Successfully set angle to " + std::to_string(angle) +
|
||||||
INITSTRUCT(sP_FE2CL_NPC_ENTER, pkt);
|
" for " + (isGruntworkNpc ? "gruntwork " : "") + "NPC " + std::to_string(npc->appearanceData.iNPC_ID));
|
||||||
pkt.NPCAppearanceData = npc->appearanceData;
|
|
||||||
sock->sendPacket(pkt, P_FE2CL_NPC_ENTER);
|
// update rotation clientside by refreshing the player's chunks (same as the /refresh command)
|
||||||
|
PlayerManager::updatePlayerPositionForWarp(sock, plr->x, plr->y, plr->z, plr->instanceID);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void refreshCommand(std::string full, std::vector<std::string>& args, CNSocket* sock) {
|
static void refreshCommand(std::string full, std::vector<std::string>& args, CNSocket* sock) {
|
||||||
|
|||||||
@@ -86,7 +86,10 @@ void PlayerManager::updatePlayerPosition(CNSocket* sock, int X, int Y, int Z, ui
|
|||||||
plr->x = X;
|
plr->x = X;
|
||||||
plr->y = Y;
|
plr->y = Y;
|
||||||
plr->z = Z;
|
plr->z = Z;
|
||||||
plr->instanceID = I;
|
if (plr->instanceID != I) {
|
||||||
|
plr->instanceID = I;
|
||||||
|
plr->recallInstance = INSTANCE_OVERWORLD;
|
||||||
|
}
|
||||||
if (oldChunk == newChunk)
|
if (oldChunk == newChunk)
|
||||||
return; // didn't change chunks
|
return; // didn't change chunks
|
||||||
Chunking::updateEntityChunk({sock}, oldChunk, newChunk);
|
Chunking::updateEntityChunk({sock}, oldChunk, newChunk);
|
||||||
@@ -132,24 +135,6 @@ void PlayerManager::sendPlayerTo(CNSocket* sock, int X, int Y, int Z, uint64_t I
|
|||||||
sock->sendPacket(resp, P_FE2CL_REP_PC_WARP_USE_NPC_SUCC);
|
sock->sendPacket(resp, P_FE2CL_REP_PC_WARP_USE_NPC_SUCC);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (I != INSTANCE_OVERWORLD) {
|
|
||||||
INITSTRUCT(sP_FE2CL_INSTANCE_MAP_INFO, pkt);
|
|
||||||
pkt.iInstanceMapNum = (int32_t)MAPNUM(I); // lower 32 bits are mapnum
|
|
||||||
if (I != fromInstance // do not retransmit MAP_INFO on recall
|
|
||||||
&& Racing::EPData.find(pkt.iInstanceMapNum) != Racing::EPData.end()) {
|
|
||||||
EPInfo* ep = &Racing::EPData[pkt.iInstanceMapNum];
|
|
||||||
pkt.iEP_ID = ep->EPID;
|
|
||||||
pkt.iMapCoordX_Min = ep->zoneX * 51200;
|
|
||||||
pkt.iMapCoordX_Max = (ep->zoneX + 1) * 51200;
|
|
||||||
pkt.iMapCoordY_Min = ep->zoneY * 51200;
|
|
||||||
pkt.iMapCoordY_Max = (ep->zoneY + 1) * 51200;
|
|
||||||
pkt.iMapCoordZ_Min = INT32_MIN;
|
|
||||||
pkt.iMapCoordZ_Max = INT32_MAX;
|
|
||||||
}
|
|
||||||
|
|
||||||
sock->sendPacket(pkt, P_FE2CL_INSTANCE_MAP_INFO);
|
|
||||||
}
|
|
||||||
|
|
||||||
INITSTRUCT(sP_FE2CL_REP_PC_GOTO_SUCC, pkt2);
|
INITSTRUCT(sP_FE2CL_REP_PC_GOTO_SUCC, pkt2);
|
||||||
pkt2.iX = X;
|
pkt2.iX = X;
|
||||||
pkt2.iY = Y;
|
pkt2.iY = Y;
|
||||||
@@ -376,6 +361,24 @@ static void loadPlayer(CNSocket* sock, CNPacketData* data) {
|
|||||||
updatePlayerPosition(sock, plr->x, plr->y, plr->z, plr->instanceID, plr->angle);
|
updatePlayerPosition(sock, plr->x, plr->y, plr->z, plr->instanceID, plr->angle);
|
||||||
|
|
||||||
sock->sendPacket(response, P_FE2CL_REP_PC_LOADING_COMPLETE_SUCC);
|
sock->sendPacket(response, P_FE2CL_REP_PC_LOADING_COMPLETE_SUCC);
|
||||||
|
|
||||||
|
if (plr->instanceID != INSTANCE_OVERWORLD) {
|
||||||
|
INITSTRUCT(sP_FE2CL_INSTANCE_MAP_INFO, pkt);
|
||||||
|
pkt.iInstanceMapNum = (int32_t)MAPNUM(plr->instanceID); // lower 32 bits are mapnum
|
||||||
|
if (pkt.iInstanceMapNum != plr->recallInstance // do not retransmit MAP_INFO on recall
|
||||||
|
&& Racing::EPData.find(pkt.iInstanceMapNum) != Racing::EPData.end()) {
|
||||||
|
EPInfo* ep = &Racing::EPData[pkt.iInstanceMapNum];
|
||||||
|
pkt.iEP_ID = ep->EPID;
|
||||||
|
pkt.iMapCoordX_Min = ep->zoneX * 51200;
|
||||||
|
pkt.iMapCoordX_Max = (ep->zoneX + 1) * 51200;
|
||||||
|
pkt.iMapCoordY_Min = ep->zoneY * 51200;
|
||||||
|
pkt.iMapCoordY_Max = (ep->zoneY + 1) * 51200;
|
||||||
|
pkt.iMapCoordZ_Min = INT32_MIN;
|
||||||
|
pkt.iMapCoordZ_Max = INT32_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
sock->sendPacket(pkt, P_FE2CL_INSTANCE_MAP_INFO);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void heartbeatPlayer(CNSocket* sock, CNPacketData* data) {
|
static void heartbeatPlayer(CNSocket* sock, CNPacketData* data) {
|
||||||
@@ -579,7 +582,7 @@ static void setFirstUseFlag(CNSocket* sock, CNPacketData* data) {
|
|||||||
std::cout << "[WARN] Client submitted invalid first use flag number?!" << std::endl;
|
std::cout << "[WARN] Client submitted invalid first use flag number?!" << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flag->iFlagCode <= 64)
|
if (flag->iFlagCode <= 64)
|
||||||
plr->iFirstUseFlag[0] |= (1ULL << (flag->iFlagCode - 1));
|
plr->iFirstUseFlag[0] |= (1ULL << (flag->iFlagCode - 1));
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -1086,33 +1086,6 @@ static void patchJSON(json* base, json* patch) {
|
|||||||
|
|
||||||
void TableData::init() {
|
void TableData::init() {
|
||||||
int32_t nextId = INT32_MAX; // next dynamic ID to hand out
|
int32_t nextId = INT32_MAX; // next dynamic ID to hand out
|
||||||
json patchmap;
|
|
||||||
|
|
||||||
// load patch map
|
|
||||||
{
|
|
||||||
std::fstream fstream;
|
|
||||||
fstream.open(settings::TDATADIR + "/" + settings::PATCHMAPJSON);
|
|
||||||
|
|
||||||
if (fstream.fail()) {
|
|
||||||
std::cerr << "[FATAL] Critical tdata file missing: " << settings::PATCHMAPJSON << std::endl;
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fstream.peek() == std::ifstream::traits_type::eof()) {
|
|
||||||
std::cerr << "[FATAL] Critical tdata file is empty: " << settings::PATCHMAPJSON << std::endl;
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
fstream >> patchmap;
|
|
||||||
fstream.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ensure that there is a patch list for the current build
|
|
||||||
if (patchmap["patchmap"].find(settings::BUILDNAME) == patchmap["patchmap"].end()) {
|
|
||||||
std::cerr << "[FATAL] Build name " << settings::BUILDNAME << " not found in " <<
|
|
||||||
settings::PATCHMAPJSON << std::endl;
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// base JSON tables
|
// base JSON tables
|
||||||
json xdt, paths, drops, eggs, npcs, mobs, gruntwork;
|
json xdt, paths, drops, eggs, npcs, mobs, gruntwork;
|
||||||
@@ -1161,13 +1134,15 @@ void TableData::init() {
|
|||||||
fstream >> *table.first;
|
fstream >> *table.first;
|
||||||
}
|
}
|
||||||
|
|
||||||
// patching: load each patch directory specified in patchmap.json
|
// patching: load each patch directory specified in the config file
|
||||||
|
|
||||||
|
// split config field into individual patch entries
|
||||||
|
std::stringstream ss(settings::ENABLEDPATCHES);
|
||||||
|
std::istream_iterator<std::string> begin(ss);
|
||||||
|
std::istream_iterator<std::string> end;
|
||||||
|
|
||||||
// fetch list of patches that need to be applied for the current build
|
|
||||||
json patch;
|
json patch;
|
||||||
json patchlist = patchmap["patchmap"][settings::BUILDNAME];
|
for (auto it = begin; it != end; it++) {
|
||||||
|
|
||||||
for (auto it = patchlist.begin(); it != patchlist.end(); it++) {
|
|
||||||
// this is the theoretical path of a corresponding patch for this file
|
// this is the theoretical path of a corresponding patch for this file
|
||||||
std::string patchModuleName = *it;
|
std::string patchModuleName = *it;
|
||||||
std::string patchFile = settings::PATCHDIR + patchModuleName + "/" + table.second;
|
std::string patchFile = settings::PATCHDIR + patchModuleName + "/" + table.second;
|
||||||
|
|||||||
@@ -47,13 +47,12 @@ std::string settings::GRUNTWORKJSON = "gruntwork.json";
|
|||||||
std::string settings::MOTDSTRING = "Welcome to OpenFusion!";
|
std::string settings::MOTDSTRING = "Welcome to OpenFusion!";
|
||||||
std::string settings::DROPSJSON = "drops.json";
|
std::string settings::DROPSJSON = "drops.json";
|
||||||
std::string settings::PATHJSON = "paths.json";
|
std::string settings::PATHJSON = "paths.json";
|
||||||
std::string settings::PATCHMAPJSON = "patchmap.json";
|
|
||||||
#ifdef ACADEMY
|
#ifdef ACADEMY
|
||||||
std::string settings::XDTJSON = "xdt1013.json";
|
std::string settings::XDTJSON = "xdt1013.json";
|
||||||
std::string settings::BUILDNAME = "beta-20111013";
|
std::string settings::ENABLEDPATCHES = "1013";
|
||||||
#else
|
#else
|
||||||
std::string settings::XDTJSON = "xdt.json";
|
std::string settings::XDTJSON = "xdt.json";
|
||||||
std::string settings::BUILDNAME = "beta-20100104";
|
std::string settings::ENABLEDPATCHES = "";
|
||||||
#endif // ACADEMY
|
#endif // ACADEMY
|
||||||
|
|
||||||
int settings::ACCLEVEL = 1;
|
int settings::ACCLEVEL = 1;
|
||||||
@@ -79,7 +78,6 @@ void settings::init() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
BUILDNAME = reader.Get("", "buildname", BUILDNAME);
|
|
||||||
VERBOSITY = reader.GetInteger("", "verbosity", VERBOSITY);
|
VERBOSITY = reader.GetInteger("", "verbosity", VERBOSITY);
|
||||||
SANDBOX = reader.GetBoolean("", "sandbox", SANDBOX);
|
SANDBOX = reader.GetBoolean("", "sandbox", SANDBOX);
|
||||||
LOGINPORT = reader.GetInteger("login", "port", LOGINPORT);
|
LOGINPORT = reader.GetInteger("login", "port", LOGINPORT);
|
||||||
@@ -107,7 +105,7 @@ void settings::init() {
|
|||||||
DBPATH = reader.Get("shard", "dbpath", DBPATH);
|
DBPATH = reader.Get("shard", "dbpath", DBPATH);
|
||||||
TDATADIR = reader.Get("shard", "tdatadir", TDATADIR);
|
TDATADIR = reader.Get("shard", "tdatadir", TDATADIR);
|
||||||
PATCHDIR = reader.Get("shard", "patchdir", PATCHDIR);
|
PATCHDIR = reader.Get("shard", "patchdir", PATCHDIR);
|
||||||
PATCHMAPJSON = reader.Get("shard", "patchmapdata", PATCHMAPJSON);
|
ENABLEDPATCHES = reader.Get("shard", "enabledpatches", ENABLEDPATCHES);
|
||||||
ACCLEVEL = reader.GetInteger("shard", "accountlevel", ACCLEVEL);
|
ACCLEVEL = reader.GetInteger("shard", "accountlevel", ACCLEVEL);
|
||||||
EVENTMODE = reader.GetInteger("shard", "eventmode", EVENTMODE);
|
EVENTMODE = reader.GetInteger("shard", "eventmode", EVENTMODE);
|
||||||
DISABLEFIRSTUSEFLAG = reader.GetBoolean("shard", "disablefirstuseflag", DISABLEFIRSTUSEFLAG);
|
DISABLEFIRSTUSEFLAG = reader.GetBoolean("shard", "disablefirstuseflag", DISABLEFIRSTUSEFLAG);
|
||||||
|
|||||||
@@ -29,8 +29,7 @@ namespace settings {
|
|||||||
extern std::string GRUNTWORKJSON;
|
extern std::string GRUNTWORKJSON;
|
||||||
extern std::string DBPATH;
|
extern std::string DBPATH;
|
||||||
extern std::string PATCHDIR;
|
extern std::string PATCHDIR;
|
||||||
extern std::string PATCHMAPJSON;
|
extern std::string ENABLEDPATCHES;
|
||||||
extern std::string BUILDNAME;
|
|
||||||
extern std::string TDATADIR;
|
extern std::string TDATADIR;
|
||||||
extern int EVENTMODE;
|
extern int EVENTMODE;
|
||||||
extern bool MONITORENABLED;
|
extern bool MONITORENABLED;
|
||||||
|
|||||||
Reference in New Issue
Block a user