2 Commits

Author SHA1 Message Date
3cfecd9644 Refuse to run if the specified build name isn't in the patch map 2023-06-26 06:48:12 +02:00
6537e38987 Replace enabledpatches config option with patchmap.json
This should make it a lot easier to manage patch directories when we add
support for each known client build.
2023-06-26 05:42:57 +02:00
13 changed files with 74 additions and 110 deletions

View File

@@ -1 +0,0 @@
version.h

View File

@@ -53,7 +53,7 @@ jobs:
- name: Upload build artifact
uses: actions/upload-artifact@v2
with:
name: 'ubuntu22_04-bin-x64-${{ env.SHORT_SHA }}'
name: 'ubuntu20_04-bin-x64-${{ env.SHORT_SHA }}'
path: bin
windows-build:
@@ -112,7 +112,7 @@ jobs:
copy-artifacts:
if: github.event_name != 'pull_request' && github.ref == 'refs/heads/master'
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
needs: [windows-build, ubuntu-build]
env:
BOT_SSH_KEY: ${{ secrets.BOT_SSH_KEY }}

26
.vscode/launch.json vendored
View File

@@ -1,26 +0,0 @@
{
"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}"
}
]
}

View File

@@ -44,7 +44,7 @@ add_executable(openfusion ${SOURCES})
set_target_properties(openfusion PROPERTIES OUTPUT_NAME ${BIN_NAME})
# find sqlite3 and use it
find_package(SQLite3 REQUIRED)
find_package(sqlite3 REQUIRED)
target_include_directories(openfusion PRIVATE ${SQLite3_INCLUDE_DIRS})
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...
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)
target_link_libraries(openfusion PRIVATE pthread)
target_link_libraries(openfusion pthread)
endif()

View File

@@ -1,21 +0,0 @@
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

View File

@@ -13,13 +13,13 @@ OpenFusion is a reverse-engineered server for FusionFall. It primarily targets v
### Getting Started
#### Method A: Installer (Easiest)
1. Download the client installer by clicking [here](https://github.com/OpenFusionProject/OpenFusion/releases/download/1.5/OpenFusionClient-1.5-Installer.exe) - choose to run the file.
1. Download the client installer by clicking [here](https://github.com/OpenFusionProject/OpenFusion/releases/download/1.4/OpenFusionClient-1.4-Installer.exe) - choose to run the file.
2. After a few moments, the client should open: you will be given a choice between two public servers by default. Select the one you wish to play and click connect.
3. To create an account, simply enter the details you wish to use at the login screen then click Log In. Do *not* click register, as this will just lead to a blank screen.
4. Make a new character, and enjoy the game! Your progress will be saved automatically, and you can resume playing by entering the login details you used in step 3.
#### Method B: Standalone .zip file
1. Download the client from [here](https://github.com/OpenFusionProject/OpenFusion/releases/download/1.5/OpenFusionClient-1.5.zip).
1. Download the client from [here](https://github.com/OpenFusionProject/OpenFusion/releases/download/1.4/OpenFusionClient-1.4.zip).
2. Extract it to a folder of your choice. Note: if you are upgrading from an older version, it is preferable to start with a fresh folder rather than overwriting a previous install.
3. Run OpenFusionClient.exe - you will be given a choice between two public servers by default. Select the one you wish to play and click connect.
4. To create an account, simply enter the details you wish to use at the login screen then click Log In. Do *not* click register, as this will just lead to a blank screen.
@@ -29,7 +29,7 @@ Instructions for getting the client to run on Linux through Wine can be found [h
### Hosting a server
1. Grab `OpenFusionServer-1.5-original.zip` or `OpenFusionServer-1.5-academy.zip` from [here](https://github.com/OpenFusionProject/OpenFusion/releases/tag/1.5).
1. Grab `OpenFusionServer-1.4-original.zip` or `OpenFusionServer-1.4-academy.zip` from [here](https://github.com/OpenFusionProject/OpenFusion/releases/tag/1.4).
2. Extract it to a folder of your choice, then run `winfusion.exe` (Windows) or `fusion` (Linux) to start the server.
3. Add a new server to the client's list:
1. For Description, enter anything you want. This is what will show up in the server list.

View File

@@ -1,3 +1,8 @@
# 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
# 0 = mostly silence
# 1 = debug prints and unknown packets
@@ -46,11 +51,6 @@ motd=Welcome to OpenFusion!
# location of the patch folder
#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
#xdtdata=xdt.json
# NPC json filename
@@ -61,6 +61,8 @@ motd=Welcome to OpenFusion!
#pathdata=paths.json
# drop json filename
#dropdata=drops.json
# patchmap json filename
#patchmapdata=patchmap.json
# gruntwork output filename (this is what you submit)
#gruntwork=gruntwork.json
# location of the database

View File

@@ -1,12 +0,0 @@
version: '3.4'
services:
openfusion:
image: openfusion
build:
context: .
dockerfile: ./Dockerfile
ports:
- "23000:23000"
- "23001:23001"
- "8003:8003"

View File

@@ -69,41 +69,31 @@ static void setValuePlayer(CNSocket* sock, CNPacketData* data) {
// Handle serverside value-changes
switch (setData->iSetValueType) {
case CN_GM_SET_VALUE_TYPE__HP:
response.iSetValue = plr->HP = setData->iSetValue;
case 1:
plr->HP = setData->iSetValue;
break;
case CN_GM_SET_VALUE_TYPE__WEAPON_BATTERY :
case 2:
plr->batteryW = setData->iSetValue;
// caps
if (plr->batteryW > 9999)
plr->batteryW = 9999;
response.iSetValue = plr->batteryW;
break;
case CN_GM_SET_VALUE_TYPE__NANO_BATTERY:
case 3:
plr->batteryN = setData->iSetValue;
// caps
if (plr->batteryN > 9999)
plr->batteryN = 9999;
response.iSetValue = plr->batteryN;
break;
case CN_GM_SET_VALUE_TYPE__FUSION_MATTER:
case 4:
Missions::updateFusionMatter(sock, setData->iSetValue - plr->fusionmatter);
response.iSetValue = plr->fusionmatter;
break;
case CN_GM_SET_VALUE_TYPE__CANDY:
response.iSetValue = plr->money = setData->iSetValue;
break;
case CN_GM_SET_VALUE_TYPE__SPEED:
case CN_GM_SET_VALUE_TYPE__JUMP:
response.iSetValue = setData->iSetValue;
case 5:
plr->money = setData->iSetValue;
break;
}
response.iPC_ID = setData->iPC_ID;
response.iSetValue = setData->iSetValue;
response.iSetValueType = setData->iSetValueType;
sock->sendPacket(response, P_FE2CL_GM_REP_PC_SET_VALUE);

View File

@@ -358,19 +358,23 @@ static void npcRotateCommand(std::string full, std::vector<std::string>& args, C
int angle = (plr->angle + 180) % 360;
NPCManager::updateNPCPosition(npc->appearanceData.iNPC_ID, npc->x, npc->y, npc->z, npc->instanceID, angle);
bool isGruntworkNpc = true;
// if it's a gruntwork NPC, rotate in-place
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);
// add a rotation entry to the gruntwork file, unless it's already a gruntwork NPC
if (TableData::RunningMobs.find(npc->appearanceData.iNPC_ID) == TableData::RunningMobs.end()) {
Chat::sendServerMessage(sock, "[NPCR] Successfully set angle to " + std::to_string(angle) + " for gruntwork NPC "
+ std::to_string(npc->appearanceData.iNPC_ID));
} else {
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));
}
Chat::sendServerMessage(sock, "[NPCR] Successfully set angle to " + std::to_string(angle) +
" for " + (isGruntworkNpc ? "gruntwork " : "") + "NPC " + std::to_string(npc->appearanceData.iNPC_ID));
// 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);
// update rotation clientside
INITSTRUCT(sP_FE2CL_NPC_ENTER, pkt);
pkt.NPCAppearanceData = npc->appearanceData;
sock->sendPacket(pkt, P_FE2CL_NPC_ENTER);
}
static void refreshCommand(std::string full, std::vector<std::string>& args, CNSocket* sock) {

View File

@@ -1086,6 +1086,33 @@ static void patchJSON(json* base, json* patch) {
void TableData::init() {
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
json xdt, paths, drops, eggs, npcs, mobs, gruntwork;
@@ -1134,15 +1161,13 @@ void TableData::init() {
fstream >> *table.first;
}
// 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;
// patching: load each patch directory specified in patchmap.json
// fetch list of patches that need to be applied for the current build
json patch;
for (auto it = begin; it != end; it++) {
json patchlist = patchmap["patchmap"][settings::BUILDNAME];
for (auto it = patchlist.begin(); it != patchlist.end(); it++) {
// this is the theoretical path of a corresponding patch for this file
std::string patchModuleName = *it;
std::string patchFile = settings::PATCHDIR + patchModuleName + "/" + table.second;

View File

@@ -47,12 +47,13 @@ std::string settings::GRUNTWORKJSON = "gruntwork.json";
std::string settings::MOTDSTRING = "Welcome to OpenFusion!";
std::string settings::DROPSJSON = "drops.json";
std::string settings::PATHJSON = "paths.json";
std::string settings::PATCHMAPJSON = "patchmap.json";
#ifdef ACADEMY
std::string settings::XDTJSON = "xdt1013.json";
std::string settings::ENABLEDPATCHES = "1013";
std::string settings::BUILDNAME = "beta-20111013";
#else
std::string settings::XDTJSON = "xdt.json";
std::string settings::ENABLEDPATCHES = "";
std::string settings::BUILDNAME = "beta-20100104";
#endif // ACADEMY
int settings::ACCLEVEL = 1;
@@ -78,6 +79,7 @@ void settings::init() {
return;
}
BUILDNAME = reader.Get("", "buildname", BUILDNAME);
VERBOSITY = reader.GetInteger("", "verbosity", VERBOSITY);
SANDBOX = reader.GetBoolean("", "sandbox", SANDBOX);
LOGINPORT = reader.GetInteger("login", "port", LOGINPORT);
@@ -105,7 +107,7 @@ void settings::init() {
DBPATH = reader.Get("shard", "dbpath", DBPATH);
TDATADIR = reader.Get("shard", "tdatadir", TDATADIR);
PATCHDIR = reader.Get("shard", "patchdir", PATCHDIR);
ENABLEDPATCHES = reader.Get("shard", "enabledpatches", ENABLEDPATCHES);
PATCHMAPJSON = reader.Get("shard", "patchmapdata", PATCHMAPJSON);
ACCLEVEL = reader.GetInteger("shard", "accountlevel", ACCLEVEL);
EVENTMODE = reader.GetInteger("shard", "eventmode", EVENTMODE);
DISABLEFIRSTUSEFLAG = reader.GetBoolean("shard", "disablefirstuseflag", DISABLEFIRSTUSEFLAG);

View File

@@ -29,7 +29,8 @@ namespace settings {
extern std::string GRUNTWORKJSON;
extern std::string DBPATH;
extern std::string PATCHDIR;
extern std::string ENABLEDPATCHES;
extern std::string PATCHMAPJSON;
extern std::string BUILDNAME;
extern std::string TDATADIR;
extern int EVENTMODE;
extern bool MONITORENABLED;