Skip to content
This repository has been archived by the owner on Feb 27, 2023. It is now read-only.

Commit

Permalink
Update to version v0.0.4
Browse files Browse the repository at this point in the history
Merge pull request #4 from KingRainbow44/development
  • Loading branch information
KingRainbow44 authored Apr 15, 2022
2 parents fa02493 + 8e2af17 commit 929a102
Show file tree
Hide file tree
Showing 26 changed files with 922 additions and 66 deletions.
14 changes: 13 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,16 @@ node_modules/
tsconfig.tsbuildinfo

# pkg Builds
build/
build/

# Running in this directory
certs/
logs/
plugins/
configs/
packets/
protocol/
rawPackets/
unknown/
versions/
config.json
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ An open-source server software for a certain anime gaem.

You can find the Open-Shen community [here](https://discord.gg/sJ7VatCYvZ)!

### Note: Open-Shen is still in development. Don't expect a ton of features. (_cough_ skids _cough_)
We provide the **underlying codebase** for a server, **not** the _data needed_ to run it.

# Features
- [ ] Game login
- [x] Game login
- [ ] Multiple version support
- [ ] Version cross-play
- [ ] Server commands
Expand All @@ -25,4 +28,4 @@ You can find the Open-Shen community [here](https://discord.gg/sJ7VatCYvZ)!
how to contribute.

### Disclaimer
*Note: Open Shen is not affiliated with HoYoVerse or Cognosphere.*
*Note: Open Shen is not affiliated with HoYoVerse or Cognosphere, if they wish to take this repository down, please contact me.*
14 changes: 11 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "open-shen",
"description": "An open-source server software for a certain anime game.",
"version": "0.0.3",
"version": "0.0.4",

"main": "src/index.ts",
"bin": "src/index.js",
Expand Down Expand Up @@ -31,11 +31,19 @@
"assets": [
"resources/default-configs/*.json",
"resources/static/*.ejs",
"resources/**"
"resources/**",

"node_modules/**/*"
],
"scripts": [
"src/packets/*.js",
"src/packets/union/*.js"
],
"outputPath": "build",
"targets": [
"node16-windows-x64"
"node16-windows-x64",
"node16-linux-x64",
"node16-linux-arm64"
]
}
}
47 changes: 47 additions & 0 deletions src/commands/support.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright © 2022 Open-Shen Team. All rights reserved.
*
* Project licensed under the MIT License: https://www.mit.edu/~amini/LICENSE.md
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
* OR OTHER DEALINGS IN THE SOFTWARE.
*
* All portions of this software are available for public use, provided that
* credit is given to the original author(s).
*/

import Command from "../objects/command";
import Player from "../player/player";
import {base, config, mode} from "../index";
import {existsSync} from "fs";
import {execSync} from "child_process";
import {formatDate} from "../utils/utilities";

export default class SupportCommand extends Command {
constructor() {
super("support", "Logs useful support information to the console.", "/support");
}

async execute(args: string[], player?: Player): Promise<void> {
// Collect the data.
const data: string = `
Running in mode: ${mode == "precompile" ? "development" : "release"}
Running: ${existsSync(`${base}/.git`) ? `from source code on Git (build: ${execSync("git describe --tags --always --dirty", {encoding: "utf-8"}).trim()})` : "from a packaged executable"}
Using client version: ${config.server.clientVersion}
Running server on port: ${config.server.udpPort}
Config version: ${config.version}
Debug status: ${config.debug.enableDebug ? `enabled (level ${config.debug.debugLevel})` : "disabled"}
Specified data provider: ${config.data.dataProvider}
Data dump from ${formatDate(Date.now())}
`;

console.info("Paste the following data into the support channel: ", "```" + data + "```");
return Promise.resolve();
}
}
6 changes: 5 additions & 1 deletion src/handlers/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ import {info} from "../utils/logger";
import Player from "../player/player";
import Command from "../objects/command";

const commands: object = {};
import SupportCommand from "../commands/support";

const commands: object = {
support: new SupportCommand()
};

const stdin = process.openStdin();
stdin.addListener('data', data => handleCommand(data.toString().trim()));
Expand Down
8 changes: 5 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
/* Run mode. none = normal; precompile = from source */
export const mode: string = process.argv[2] || "none";
/* The current working directory. */
export const working: string = mode == "precompile" ? process.env["WORKING_DIRECTORY"] : process.cwd();
export const working: string = mode == "precompile" ? (process.env["WORKING_DIRECTORY"] || process.cwd()) : process.cwd();
/* The application files directory. */
export const base: string = `${__dirname}/..`;

Expand All @@ -32,10 +32,11 @@ process.on('uncaughtException', (error: any) => {
/* Dynamic imports. */
import {copyFileSync, existsSync} from "fs";
import {createStructure, updateConfig} from "./utils/updater";
import {ServerConstants} from "./utils/constants";
import {Color, ServerConstants} from "./utils/constants";

/* Override 'console' methods. */
import "./utils/logger";
import * as logger from "./utils/logger";
logger.info(Color.DEFAULT(), "Open Shen is starting...");

/* Declare server config. */
import {Config} from "./utils/interfaces";
Expand All @@ -57,5 +58,6 @@ export const configs: ConfigLoader = new ConfigLoader();
/* Start handlers. */
import "./handlers/udp";
import "./handlers/http";
import "./handlers/command";
/* Create server instance. */
import "./server";
6 changes: 3 additions & 3 deletions src/objects/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@
* credit is given to the original author(s).
*/

/**
* The base class for Bridge's commands.
*/
import Player from "../player/player";
import {info} from "../utils/logger";

/**
* The base class for Open Shen's commands.
*/
abstract class Command {
label: string;
description: string;
Expand Down
2 changes: 1 addition & 1 deletion src/objects/configs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,6 @@ export default class ConfigLoader {
gachaConfig: GachaConfig;

constructor() {
this.gachaConfig = <GachaConfig>readConfig("gacha");
this.gachaConfig = <GachaConfig> readConfig("gacha");
}
}
4 changes: 2 additions & 2 deletions src/objects/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export default interface DataProvider {
}

const registeredProviders: object = {
sqlite3: `${base}/src/objects/providers/sqlite3`
sqlite3: require("./providers/sqlite3")
};

/**
Expand All @@ -53,7 +53,7 @@ export function createProviderInstance(): DataProvider {

let dataProvider: DataProvider;
try {
let provider: any = require(registeredProviders[providerName]).default;
let provider: any = registeredProviders[providerName].default;
dataProvider = new provider(providerCredentials);
} catch (error: any) {
console.error(`Failed to create data provider instance.`, error);
Expand Down
2 changes: 1 addition & 1 deletion src/packets/SceneInitFinishReq.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export default async function (data, player: Player): Promise<void> {
player.sendPacket("AvatarEquipChangeNotify", jsonToObject("AvatarEquipChangeNotify2"));
player.sendPacket("HostPlayerNotify", world.getWorldHost());
player.sendPacket("ScenePlayerInfoNotify", world.toScenePlayerInfo());
player.sendPacket("PlayerEnterSceneInfoNotify", player.network.enterSceneNotification(3495));
player.sendPacket("PlayerEnterSceneInfoNotify", player.network.enterSceneInfoNotification(3495));
player.sendPacket("SyncTeamEntityNotify", {sceneId: 3}); // Temporarily hardcoded.
player.sendPacket("SyncScenePlayTeamEntityNotify", {sceneId: 3}); // Temporarily hardcoded.
player.sendPacket("ScenePlayBattleInfoListNotify");
Expand Down
44 changes: 42 additions & 2 deletions src/packets/UnionCmdNotify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,47 @@
*/

import Player from "../player/Player";
import {UnionCmdNotify} from "../utils/protocol";
import {Color} from "../utils/constants";
import * as protocol from "../utils/packets";
import * as logger from "../utils/logger";
import * as utils from "../utils/utilities";

export default async function (data, player: Player): Promise<void> {
// TODO: Handle packet.
import {config} from "../index";
import {server} from "../server";

export default async function (data: UnionCmdNotify, player: Player): Promise<void> {
for(const cmd of data.cmdList) {
const messageId: number = cmd.messageId;
const body: Buffer = cmd.body;

const data: object = await protocol.packetToObject(body, messageId);
await handleUnionCmd(messageId, data, player);
} return Promise.resolve();
}

/**
* Invokes the appropriate handler for the given message ID.
* @param cmdId The message ID.
* @param cmdData The data associated with the message.
*/
async function handleUnionCmd(cmdId: number, cmdData: object, player: Player): Promise<void> {
const framework: string = protocol.getFrameworkById(cmdId);
try {
const handler = require(`./union/${framework}`);
const result: any = await handler.default(cmdData, player);

if(config.debug.logPackets) {
logger.logToFile(JSON.stringify(cmdData), `incoming_${framework}`, true);
logger.logToFile(`[UDP] Accepted ${framework} at ${utils.formatDate(Date.now())}`, `inbound_packets`, true);
}

return result;
} catch (error: any) {
logger.debug(Color.CYAN(false), `Unable to handle union command ${cmdId} (${framework})`);
if(config.debug.debugLevel > 1 && !server.unhandledPackets[cmdId]) {
console.warn("Unhandled union command:", error);
server.unhandledPackets.push(cmdId);
}
}
}
23 changes: 23 additions & 0 deletions src/packets/union/AbilityInvocationsNotify.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright © 2022 Open-Shen Team. All rights reserved.
*
* Project licensed under the MIT License: https://www.mit.edu/~amini/LICENSE.md
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
* OR OTHER DEALINGS IN THE SOFTWARE.
*
* All portions of this software are available for public use, provided that
* credit is given to the original author(s).
*/

import Player from "../../player/player";

export default async function (data: object, player: Player) {

}
67 changes: 67 additions & 0 deletions src/packets/union/CombatInvocationsNotify.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright © 2022 Open-Shen Team. All rights reserved.
*
* Project licensed under the MIT License: https://www.mit.edu/~amini/LICENSE.md
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
* OR OTHER DEALINGS IN THE SOFTWARE.
*
* All portions of this software are available for public use, provided that
* credit is given to the original author(s).
*/

import Player from "../../player/player";
import World from "../../world/world";
import ServerEntity from "../../world/entity";
import {CombatInvocationsNotify, EntityMoveInfo} from "../../utils/protocol";
import {InvocationArguments} from "../../utils/constants";
import * as protocol from "../../utils/packets";

export default async function (data: CombatInvocationsNotify, player: Player) {
for(const invoke of data.invokeList) {
const type: number = invoke.argumentType;
const forwardTo: number = invoke.forwardType;
const data: Buffer = invoke.combatData;
await handleInvocation({
player: player,
type: type,
forwardTo: forwardTo,
data: data
});
}
}

async function handleInvocation(object: InvocationObject) {
const {data, player, type} = object;
const world: World = player.world;

switch(type) {
default:
console.log(`Unknown invocation type: ${type}`);
break;

case InvocationArguments.ENTITY_MOVE:
const decoded: EntityMoveInfo = await protocol.packetToObject(data, "EntityMoveInfo");

const entityId: number = decoded.entityId;
const entity: ServerEntity = world.entityManager.getEntityById(entityId);
if(entity) entity.move(decoded.motionInfo); // Move the specified entity.
break;
}

return Promise.resolve();
}

/* Makes data easier. */
interface InvocationObject {
data: Buffer;
forwardTo: number;
type: number;
player: Player;
}
Loading

0 comments on commit 929a102

Please sign in to comment.