Merge pull request #18 from ZeruLight/main

update achievement branch
This commit is contained in:
wish
2022-08-07 21:08:09 +10:00
committed by GitHub
664 changed files with 2136 additions and 2096 deletions

View File

@@ -1,10 +1,10 @@
name: Erupe
name: Build
on: [push]
jobs:
build:
runs-on: windows-latest
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
@@ -14,14 +14,32 @@ jobs:
with:
go-version: 1.18
- name: Build
run: cd Erupe && go build -v
- name: Build Linux-amd64
run: env GOOS=linux GOARCH=amd64 go build -v
- name: Upload artifacts
- name: Upload Linux-amd64 artifacts
uses: actions/upload-artifact@v3
with:
name: Erupe
name: Linux-amd64
path: |
./Erupe/erupe-ce.exe
./Erupe/config.json
./Erupe/www/
./erupe-ce
./config.json
./www/
./savedata/
./bin/
./RoadShopItems.csv
- name: Build Windows-amd64
run: env GOOS=windows GOARCH=amd64 go build -v
- name: Upload Windows-amd64 artifacts
uses: actions/upload-artifact@v3
with:
name: Windows-amd64
path: |
./erupe-ce.exe
./config.json
./www/
./savedata/
./bin/
./RoadShopItems.csv

13
.gitignore vendored
View File

@@ -1 +1,14 @@
.idea/
www/jp/
vendor/
bin/*.bin
bin/*.bak
bin/quests/*.bin
bin/questlists/*.bin
bin/scenarios/*.bin
bin/debug/*.bin
savedata/*/
*.exe
*.lnk
*.bat

14
Erupe/.gitignore vendored
View File

@@ -1,14 +0,0 @@
www/jp/
.idea/
vendor/
bin/*.bin
bin/*.bak
bin/quests/*.bin
bin/questlists/*.bin
bin/scenarios/*.bin
bin/debug/*.bin
savedata/
Erupe.exe
*.lnk
*.bat

View File

@@ -1 +0,0 @@
0 is no event, 1 is "Week 1 Timestamp (broken), 2 is "Week 2 Timestamp (broken), 3 is Diva Defense

Binary file not shown.

Binary file not shown.

View File

@@ -1,83 +0,0 @@
# Erupe
## WARNING
This project is in its infancy and has no reliable active developer, no documentation, and no support.
# General info
Currently allows a JP MHF client (with GameGuard removed) to:
* Login and register an account (registration is automatic if account doesn't exist)
* Create a character
* Get ingame to the main city
* See other players walk around
* Do quests
* Use chat*
# Installation
## Server
1. Clone the repo with `git clone https://github.com/Andoryuuta/Erupe.git`
2. Install PostgreSQL
3. Launch psql shell, `CREATE DATABASE erupe;`.
4. Setup database with golang-migrate:
Windows:
```
> go get -tags 'postgres' -u github.com/golang-migrate/migrate/v4/cmd/migrate/
> set POSTGRESQL_URL=postgres://postgres:password@localhost:5432/erupe?sslmode=disable
> cd erupe
> migrate -database %POSTGRESQL_URL% -path migrations up
```
Linux:
```
> go get -tags 'postgres' -u github.com/golang-migrate/migrate/v4/cmd/migrate/
> export POSTGRESQL_URL=postgres://postgres:password@localhost:5432/erupe?sslmode=disable
> cd erupe
> migrate -database $POSTGRESQL_URL -path migrations up
```
(Replacing `postgres:password` with your postgres username and password)
5. Edit the config.json
Namely:
* Update the database username and password
* Update the `host_ip` and `ip` fields (there are multiple) to your external IP if you are hosting for multiple clients.
6. Place quest/scenario binaries.
The quest and scenario binary files should be placed in `bin/quests/` and `bin/scenarios` respectively.
## Launcher
Erupe ships with a rudimentary custom launcher, so you don't need to obtain the original TW/JP files to simply get ingame. However, it does still support using the original files if you choose to. To set this up, place a copy of the original launcher html/js/css in `./www/tw/`, and `/www/jp/` for the TW and JP files respectively.
Then, modify the the `/launcher/js/launcher.js` file as such:
* Find the call to `startUpdateProcess();` in a case statement and replace it with `finishUpdateProcess();`. (This disables the file check and updating)
* (JP ONLY): replace all uses of "https://" with "http://" in the file.
Finally, edit the config.json and set `UseOriginalLauncherFiles` to `true` under the launcher settings.
# Usage
### Note: If you are switching to/from the custom launcher html, you will have to clear your IE cache @ `C:\Users\<user>\AppData\Local\Microsoft\Windows\INetCache`.
## Server
```
cd Erupe
go run .
```
## Client
Add to hosts:
```
127.0.0.1 mhfg.capcom.com.tw
127.0.0.1 mhf-n.capcom.com.tw
127.0.0.1 cog-members.mhf-z.jp
127.0.0.1 www.capcom-onlinegames.jp
127.0.0.1 srv-mhf.capcom-networks.jp
```
Run mhf.exe normally (with locale emulator or appropriate timezone).

View File

@@ -1,5 +0,0 @@
BEGIN;
CREATE SEQUENCE IF NOT EXISTS public.airou_id_seq;
END;

View File

@@ -1,46 +0,0 @@
package pascalstring
import (
"erupe-ce/common/byteframe"
"golang.org/x/text/encoding/japanese"
"golang.org/x/text/transform"
)
func Uint8(bf *byteframe.ByteFrame, x string, t bool) {
if t {
e := japanese.ShiftJIS.NewEncoder()
xt, _, err := transform.String(e, x)
if err != nil {
panic(err)
}
x = xt
}
bf.WriteUint8(uint8(len(x) + 1))
bf.WriteNullTerminatedBytes([]byte(x))
}
func Uint16(bf *byteframe.ByteFrame, x string, t bool) {
if t {
e := japanese.ShiftJIS.NewEncoder()
xt, _, err := transform.String(e, x)
if err != nil {
panic(err)
}
x = xt
}
bf.WriteUint16(uint16(len(x) + 1))
bf.WriteNullTerminatedBytes([]byte(x))
}
func Uint32(bf *byteframe.ByteFrame, x string, t bool) {
if t {
e := japanese.ShiftJIS.NewEncoder()
xt, _, err := transform.String(e, x)
if err != nil {
panic(err)
}
x = xt
}
bf.WriteUint32(uint32(len(x) + 1))
bf.WriteNullTerminatedBytes([]byte(x))
}

View File

@@ -1,26 +0,0 @@
BEGIN;
CREATE TABLE IF NOT EXISTS public.distribution
(
id serial NOT NULL PRIMARY KEY,
character_id int,
type int NOT NULL,
deadline timestamp without time zone,
event_name text NOT NULL DEFAULT 'GM Gift!',
description text NOT NULL DEFAULT '~C05You received a gift!',
times_acceptable int NOT NULL DEFAULT 1,
min_hr int NOT NULL DEFAULT 65535,
max_hr int NOT NULL DEFAULT 65535,
min_sr int NOT NULL DEFAULT 65535,
max_sr int NOT NULL DEFAULT 65535,
min_gr int NOT NULL DEFAULT 65535,
max_gr int NOT NULL DEFAULT 65535,
data bytea NOT NULL
);
CREATE TABLE IF NOT EXISTS public.distributions_accepted
(
distribution_id int,
character_id int
);
END;

View File

@@ -1,26 +0,0 @@
BEGIN;
ALTER TABLE IF EXISTS public.gook
DROP COLUMN IF EXISTS gook0status;
ALTER TABLE IF EXISTS public.gook
DROP COLUMN IF EXISTS gook1status;
ALTER TABLE IF EXISTS public.gook
DROP COLUMN IF EXISTS gook2status;
ALTER TABLE IF EXISTS public.gook
DROP COLUMN IF EXISTS gook3status;
ALTER TABLE IF EXISTS public.gook
DROP COLUMN IF EXISTS gook4status;
ALTER TABLE IF EXISTS public.gook
DROP COLUMN IF EXISTS gook5status;
ALTER TABLE IF EXISTS public.gook
DROP COLUMN IF EXISTS gook5;
UPDATE public.gook SET gook0=NULL, gook1=NULL, gook2=NULL, gook3=NULL, gook4=NULL;
END;

View File

@@ -1,56 +0,0 @@
BEGIN;
ALTER TABLE IF EXISTS public.guilds
ADD COLUMN IF NOT EXISTS pugi_name_1 varchar(12) DEFAULT '';
ALTER TABLE IF EXISTS public.guilds
ADD COLUMN IF NOT EXISTS pugi_name_2 varchar(12) DEFAULT '';
ALTER TABLE IF EXISTS public.guilds
ADD COLUMN IF NOT EXISTS pugi_name_3 varchar(12) DEFAULT '';
CREATE TABLE IF NOT EXISTS public.guild_alliances
(
id serial NOT NULL PRIMARY KEY,
name varchar(24) NOT NULL,
created_at timestamp without time zone NOT NULL DEFAULT now(),
parent_id int NOT NULL,
sub1_id int,
sub2_id int
);
CREATE TABLE IF NOT EXISTS public.guild_adventures
(
id serial NOT NULL PRIMARY KEY,
guild_id int NOT NULL,
destination int NOT NULL,
charge int NOT NULL DEFAULT 0,
depart int NOT NULL,
return int NOT NULL,
collected_by text NOT NULL DEFAULT ''
);
CREATE TABLE IF NOT EXISTS public.guild_meals
(
id serial NOT NULL PRIMARY KEY,
guild_id int NOT NULL,
meal_id int NOT NULL,
level int NOT NULL,
expires int NOT NULL
);
CREATE TABLE IF NOT EXISTS public.guild_hunts
(
id serial NOT NULL PRIMARY KEY,
guild_id int NOT NULL,
host_id int NOT NULL,
destination int NOT NULL,
level int NOT NULL,
return int NOT NULL,
acquired bool NOT NULL DEFAULT false,
claimed bool NOT NULL DEFAULT false,
hunters text NOT NULL DEFAULT '',
treasure text NOT NULL DEFAULT '',
hunt_data bytea NOT NULL,
cats_used text NOT NULL
);
END;

View File

@@ -1,6 +0,0 @@
BEGIN;
ALTER TABLE IF EXISTS public.characters
ADD COLUMN IF NOT EXISTS house bytea;
END;

View File

@@ -1,35 +0,0 @@
BEGIN;
CREATE TABLE IF NOT EXISTS public.normal_shop_items
(
shoptype integer,
shopid integer,
itemhash integer not null,
itemid integer,
points integer,
tradequantity integer,
rankreqlow integer,
rankreqhigh integer,
rankreqg integer,
storelevelreq integer,
maximumquantity integer,
boughtquantity integer,
roadfloorsrequired integer,
weeklyfataliskills integer,
enable_weeks character varying(8)
);
ALTER TABLE IF EXISTS public.normal_shop_items
ADD COLUMN IF NOT EXISTS enable_weeks character varying(8);
CREATE TABLE IF NOT EXISTS public.shop_item_state
(
char_id bigint REFERENCES characters (id),
itemhash int UNIQUE NOT NULL,
usedquantity int,
week int
);
ALTER TABLE IF EXISTS public.shop_item_state
ADD COLUMN IF NOT EXISTS week int;
END;

View File

@@ -1,9 +0,0 @@
BEGIN;
ALTER TABLE IF EXISTS public.characters
ADD COLUMN IF NOT EXISTS scenariodata bytea;
ALTER TABLE IF EXISTS public.characters
ADD COLUMN IF NOT EXISTS savefavoritequest bytea;
END;

View File

@@ -1,122 +0,0 @@
package channelserver
import (
"encoding/base64"
"fmt"
"erupe-ce/common/byteframe"
"erupe-ce/network/mhfpacket"
)
func handleMsgSysInsertUser(s *Session, p mhfpacket.MHFPacket) {}
func handleMsgSysDeleteUser(s *Session, p mhfpacket.MHFPacket) {}
func broadcastNewUser(s *Session) {
s.logger.Debug(fmt.Sprintf("Broadcasting new user: %s (%d)", s.Name, s.charID))
clientNotif := byteframe.NewByteFrame()
var temp mhfpacket.MHFPacket
for _, session := range s.server.sessions {
if session == s || !session.binariesDone {
continue
}
temp = &mhfpacket.MsgSysInsertUser{CharID: session.charID}
clientNotif.WriteUint16(uint16(temp.Opcode()))
temp.Build(clientNotif, s.clientContext)
for i := 0; i < 3; i++ {
temp = &mhfpacket.MsgSysNotifyUserBinary{
CharID: session.charID,
BinaryType: uint8(i + 1),
}
clientNotif.WriteUint16(uint16(temp.Opcode()))
temp.Build(clientNotif, s.clientContext)
}
}
s.QueueSend(clientNotif.Data())
serverNotif := byteframe.NewByteFrame()
temp = &mhfpacket.MsgSysInsertUser{CharID: s.charID}
serverNotif.WriteUint16(uint16(temp.Opcode()))
temp.Build(serverNotif, s.clientContext)
for i := 0; i < 3; i++ {
temp = &mhfpacket.MsgSysNotifyUserBinary{
CharID: s.charID,
BinaryType: uint8(i + 1),
}
serverNotif.WriteUint16(uint16(temp.Opcode()))
temp.Build(serverNotif, s.clientContext)
}
for _, session := range s.server.sessions {
if session == s || !session.binariesDone {
continue
}
session.QueueSend(serverNotif.Data())
}
}
func handleMsgSysSetUserBinary(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgSysSetUserBinary)
s.server.userBinaryPartsLock.Lock()
s.server.userBinaryParts[userBinaryPartID{charID: s.charID, index: pkt.BinaryType}] = pkt.RawDataPayload
s.server.userBinaryPartsLock.Unlock()
// Insert user once all binary parts exist
if !s.binariesDone {
for i := 0; i < 3; i++ {
_, exists := s.server.userBinaryParts[userBinaryPartID{charID: s.charID, index: uint8(i + 1)}]
if !exists {
return
}
}
s.binariesDone = true
broadcastNewUser(s)
return
}
msg := &mhfpacket.MsgSysNotifyUserBinary{
CharID: s.charID,
BinaryType: pkt.BinaryType,
}
s.server.BroadcastMHF(msg, s)
}
func handleMsgSysGetUserBinary(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgSysGetUserBinary)
// Try to get the data.
s.server.userBinaryPartsLock.RLock()
defer s.server.userBinaryPartsLock.RUnlock()
data, ok := s.server.userBinaryParts[userBinaryPartID{charID: pkt.CharID, index: pkt.BinaryType}]
resp := byteframe.NewByteFrame()
// If we can't get the real data, use a placeholder.
if !ok {
if pkt.BinaryType == 1 {
// Stub name response with character ID
resp.WriteBytes([]byte(fmt.Sprintf("CID%d", s.charID)))
resp.WriteUint8(0) // NULL terminator.
} else if pkt.BinaryType == 2 {
data, err := base64.StdEncoding.DecodeString("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBn8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAwAAAAAAAAAAAAAABAAAAAAAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==")
if err != nil {
panic(err)
}
resp.WriteBytes(data)
} else if pkt.BinaryType == 3 {
data, err := base64.StdEncoding.DecodeString("AQAAA2ea5P8ATgEA/wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBn8AAAAAAAAAAAABAKAMAAAAAAAAAAAAACgAAAAAAAAAAAABAsQOAAAAAAAAAAABA6UMAAAAAAAAAAABBKAMAAAAAAAAAAABBToNAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAgACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")
if err != nil {
panic(err)
}
resp.WriteBytes(data)
}
} else {
resp.WriteBytes(data)
}
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
}
func handleMsgSysNotifyUserBinary(s *Session, p mhfpacket.MHFPacket) {}
func handleMsgMhfGetBbsUserStatus(s *Session, p mhfpacket.MHFPacket) {}

View File

@@ -1,32 +0,0 @@
BEGIN;
DROP TABLE IF EXISTS public.sign_sessions;
CREATE TABLE IF NOT EXISTS public.sign_sessions
(
user_id int NOT NULL,
char_id int,
token varchar(16) NOT NULL,
server_id integer
);
DROP TABLE IF EXISTS public.servers;
CREATE TABLE IF NOT EXISTS public.servers
(
server_id int NOT NULL,
season int NOT NULL,
current_players int NOT NULL
);
ALTER TABLE IF EXISTS public.characters
ADD COLUMN IF NOT EXISTS deleted boolean NOT NULL DEFAULT false;
ALTER TABLE IF EXISTS public.characters
ADD COLUMN IF NOT EXISTS friends text NOT NULL DEFAULT '';
ALTER TABLE IF EXISTS public.characters
ADD COLUMN IF NOT EXISTS blocked text NOT NULL DEFAULT '';
ALTER TABLE IF EXISTS public.users
ADD COLUMN IF NOT EXISTS last_character int DEFAULT 0;
END;

View File

@@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2019 The Erupe Developers from Einherjar Team
Copyright (c) 2019 The Erupe Developers, The Erupe Developers from Einherjar Team, ZeruLight
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

Binary file not shown.

View File

@@ -1,7 +1,8 @@
# Erupe Community Edition
This is a community upload of a community project. The amount of people who worked on it is innumerous, and hard to keep track of. Credits to Andoryuuta, Fist's Team, the French Team, Mai's Team and many others. No matter the relations, these files will remain public and open source, free for all to use and modify.
A pastebin with various links, tips, and FAQ: https://pastebin.com/QqAwZSTC
[A pastebin with various links, tips, and FAQ](https://pastebin.com/QqAwZSTC)
An upload for the quest and scenario files exists here: https://github.com/xl3lackout/MHFZ-Quest-Files
(Over 300k+ files)
[An upload for the quest and scenario files exists here](https://github.com/xl3lackout/MHFZ-Quest-Files)
(Over 300k+ files)

View File

@@ -1,2 +0,0 @@
cd PUT ERUPE DIRECTORY HERE - BE SURE TO USE /d IF ITS ON A DRIVE OTHER THAN C
go run .

View File

@@ -0,0 +1,46 @@
package pascalstring
import (
"erupe-ce/common/byteframe"
"golang.org/x/text/encoding/japanese"
"golang.org/x/text/transform"
)
func Uint8(bf *byteframe.ByteFrame, x string, t bool) {
if t {
e := japanese.ShiftJIS.NewEncoder()
xt, _, err := transform.String(e, x)
if err != nil {
panic(err)
}
x = xt
}
bf.WriteUint8(uint8(len(x) + 1))
bf.WriteNullTerminatedBytes([]byte(x))
}
func Uint16(bf *byteframe.ByteFrame, x string, t bool) {
if t {
e := japanese.ShiftJIS.NewEncoder()
xt, _, err := transform.String(e, x)
if err != nil {
panic(err)
}
x = xt
}
bf.WriteUint16(uint16(len(x) + 1))
bf.WriteNullTerminatedBytes([]byte(x))
}
func Uint32(bf *byteframe.ByteFrame, x string, t bool) {
if t {
e := japanese.ShiftJIS.NewEncoder()
xt, _, err := transform.String(e, x)
if err != nil {
panic(err)
}
x = xt
}
bf.WriteUint32(uint32(len(x) + 1))
bf.WriteNullTerminatedBytes([]byte(x))
}

View File

@@ -106,7 +106,7 @@ func PaddedString(x string, size uint, t bool) []byte {
e := japanese.ShiftJIS.NewEncoder()
xt, _, err := transform.String(e, x)
if err != nil {
panic(err)
return make([]byte, size)
}
x = xt
}

View File

@@ -1,11 +1,14 @@
{
"host_ip": "127.0.0.1",
"bin_path": "bin",
"Host": "127.0.0.1",
"BinPath": "bin",
"DisableSoftCrash": false,
"devmode": true,
"devmodeoptions": {
"serverName" : "",
"hideLoginNotice": false,
"loginNotice": "<BODY><CENTER><SIZE_3><C_4>Welcome to Erupe SU9 (Patch 1)!<BR><BODY><LEFT><SIZE_2><C_5>Erupe is experimental software<C_7>, we are not liable for any<BR><BODY>issues caused by installing the software!<BR><BODY><BR><BODY><C_4>■Report bugs on Discord!<C_7><BR><BODY><BR><BODY><C_4>■Test everything!<C_7><BR><BODY><BR><BODY><C_4>■Don't talk to softlocking NPCs!<C_7><BR><BODY><BR><BODY><C_4>■Fork the code on GitHub!<C_7><BR><BODY><BR><BODY>Thank you to all of the contributors,<BR><BODY><BR><BODY>this wouldn't exist without you.",
"cleandb": false,
"maxlauncherhr": true,
"maxlauncherhr": false,
"LogInboundMessages": false,
"LogOutboundMessages": false,
"MaxHexdumpLength": 256,
@@ -14,6 +17,9 @@
"FestaEvent": 0,
"TournamentEvent": 0,
"MezFesEvent": true,
"MezFesAlt": false,
"DisableMailItems": true,
"DisableTokenCheck": false,
"SaveDumps": {
"Enabled": true,
"OutputDir": "savedata"
@@ -47,34 +53,34 @@
{
"name": "Newbie", "description": "", "ip": "", "type": 3, "recommended": 2, "allowedclientflags": 0,
"channels": [
{ "port": 54001, "MaxPlayers": 50, "Unk0": 319, "Unk1": 252, "Unk2": 248 },
{ "port": 54002, "MaxPlayers": 50, "Unk0": 319, "Unk1": 252, "Unk2": 248 }
{ "port": 54001, "MaxPlayers": 100 },
{ "port": 54002, "MaxPlayers": 100 }
]
}, {
"name": "Normal", "description": "", "ip": "", "type": 1, "recommended": 0, "allowedclientflags": 0,
"channels": [
{ "port": 54003, "MaxPlayers": 50, "Unk0": 319, "Unk1": 252, "Unk2": 248 },
{ "port": 54004, "MaxPlayers": 50, "Unk0": 319, "Unk1": 252, "Unk2": 248 }
{ "port": 54003, "MaxPlayers": 100 },
{ "port": 54004, "MaxPlayers": 100 }
]
}, {
"name": "Cities", "description": "", "ip": "", "type": 2, "recommended": 0, "allowedclientflags": 0,
"channels": [
{ "port": 54005, "MaxPlayers": 50, "Unk0": 319, "Unk1": 252, "Unk2": 248 }
{ "port": 54005, "MaxPlayers": 100 }
]
}, {
"name": "Tavern", "description": "", "ip": "", "type": 4, "recommended": 0, "allowedclientflags": 0,
"channels": [
{ "port": 54006, "MaxPlayers": 50, "Unk0": 319, "Unk1": 252, "Unk2": 248 }
{ "port": 54006, "MaxPlayers": 100 }
]
}, {
"name": "Return", "description": "", "ip": "", "type": 5, "recommended": 0, "allowedclientflags": 0,
"channels": [
{ "port": 54007, "MaxPlayers": 50, "Unk0": 319, "Unk1": 252, "Unk2": 248 }
{ "port": 54007, "MaxPlayers": 100 }
]
}, {
"name": "MezFes", "description": "", "ip": "", "type": 6, "recommended": 6, "allowedclientflags": 0,
"channels": [
{ "port": 54008, "MaxPlayers": 50, "Unk0": 319, "Unk1": 252, "Unk2": 248 }
{ "port": 54008, "MaxPlayers": 100 }
]
}
]

View File

@@ -9,9 +9,10 @@ import (
// Config holds the global server-wide config.
type Config struct {
HostIP string `mapstructure:"host_ip"`
BinPath string `mapstructure:"bin_path"`
DevMode bool
Host string `mapstructure:"Host"`
BinPath string `mapstructure:"BinPath"`
DisableSoftCrash bool // Disables the 'Press Return to exit' dialog allowing scripts to reboot the server automatically
DevMode bool
DevModeOptions DevModeOptions
Discord Discord
@@ -24,6 +25,8 @@ type Config struct {
// DevModeOptions holds various debug/temporary options for use while developing Erupe.
type DevModeOptions struct {
ServerName string // To get specific instance server about (Current Players/Event Week)
HideLoginNotice bool // Hide the Erupe notice on login
LoginNotice string // MHFML string of the login notice displayed
CleanDB bool // Automatically wipes the DB on server reset.
MaxLauncherHR bool // Sets the HR returned in the launcher to HR9 so that you can join non-beginner worlds.
FixedStageID bool // Causes all move_stage to use the ID sl1Ns200p0a0u0 to get you into all stages
@@ -34,6 +37,9 @@ type DevModeOptions struct {
FestaEvent int // Hunter's Festa event status
TournamentEvent int // VS Tournament event status
MezFesEvent bool // MezFes status
MezFesAlt bool // Swaps out Volpakkun for Tokotoko
DisableTokenCheck bool // Disables checking login token exists in the DB (security risk!)
DisableMailItems bool // Hack to prevent english versions of MHF from crashing
SaveDumps SaveDumpOptions
}
@@ -44,8 +50,8 @@ type SaveDumpOptions struct {
// Discord holds the discord integration config.
type Discord struct {
Enabled bool
BotToken string
Enabled bool
BotToken string
ServerID string
RealtimeChannelID string
DevRoles []string
@@ -80,11 +86,11 @@ type Entrance struct {
// EntranceServerInfo represents an entry in the serverlist.
type EntranceServerInfo struct {
IP string
Type uint8 // Server type. 0=?, 1=open, 2=cities, 3=newbie, 4=bar
Season uint8 // Server activity. 0 = green, 1 = orange, 2 = blue
IP string
Type uint8 // Server type. 0=?, 1=open, 2=cities, 3=newbie, 4=bar
Season uint8 // Server activity. 0 = green, 1 = orange, 2 = blue
Recommended uint8 // Something to do with server recommendation on 0, 3, and 5.
Name string // Server name, 66 byte null terminated Shift-JIS(JP) or Big5(TW).
Name string // Server name, 66 byte null terminated Shift-JIS(JP) or Big5(TW).
Description string // Server description
// 4096(PC, PS3/PS4)?, 8258(PC, PS3/PS4)?, 8192 == nothing?
// THIS ONLY EXISTS IF Binary8Header.type == "SV2", NOT "SVR"!
@@ -98,9 +104,6 @@ type EntranceChannelInfo struct {
Port uint16
MaxPlayers uint16
CurrentPlayers uint16
Unk0 uint16
Unk1 uint16
Unk2 uint16
}
// getOutboundIP4 gets the preferred outbound ip4 of this machine
@@ -138,8 +141,8 @@ func LoadConfig() (*Config, error) {
return nil, err
}
if c.HostIP == "" {
c.HostIP = getOutboundIP4().To4().String()
if c.Host == "" {
c.Host = getOutboundIP4().To4().String()
}
return c, nil

Binary file not shown.

View File

@@ -2,7 +2,7 @@ package main
import (
"fmt"
"math/rand"
"net"
"os"
"os/signal"
"syscall"
@@ -19,6 +19,8 @@ import (
"go.uber.org/zap"
)
var erupeConfig *config.Config
// Temporary DB auto clean on startup for quick development & testing.
func cleanDB(db *sqlx.DB) {
_ = db.MustExec("DELETE FROM guild_characters")
@@ -29,6 +31,7 @@ func cleanDB(db *sqlx.DB) {
}
func main() {
var err error
zapLogger, _ := zap.NewDevelopment()
defer zapLogger.Sync()
logger := zapLogger.Named("main")
@@ -36,7 +39,7 @@ func main() {
logger.Info("Starting Erupe")
// Load the configuration.
erupeConfig, err := config.LoadConfig()
erupeConfig, err = config.LoadConfig()
if err != nil {
preventClose(fmt.Sprintf("Failed to load config: %s", err.Error()))
}
@@ -45,6 +48,19 @@ func main() {
preventClose("Database password is blank")
}
if net.ParseIP(erupeConfig.Host) == nil {
ips, _ := net.LookupIP(erupeConfig.Host)
for _, ip := range ips {
if ip != nil {
erupeConfig.Host = ip.String()
break
}
}
if net.ParseIP(erupeConfig.Host) == nil {
preventClose("Invalid host address")
}
}
// Discord bot
var discordBot *discordbot.DiscordBot = nil
@@ -151,9 +167,6 @@ func main() {
ci := 0
count := 1
for _, ee := range erupeConfig.Entrance.Entries {
rand.Seed(time.Now().UnixNano())
// Randomly generate a season for the World
season := rand.Intn(3) + 1
for _, ce := range ee.Channels {
sid := (4096 + si*256) + (16 + ci)
c := *channelserver.NewServer(&channelserver.Config{
@@ -163,11 +176,17 @@ func main() {
DB: db,
DiscordBot: discordBot,
})
err = c.Start(int(ce.Port))
if ee.IP == "" {
c.IP = erupeConfig.Host
} else {
c.IP = ee.IP
}
c.Port = ce.Port
err = c.Start()
if err != nil {
preventClose(fmt.Sprintf("Failed to start channel server: %s", err.Error()))
} else {
channelQuery += fmt.Sprintf("INSERT INTO servers (server_id, season, current_players) VALUES (%d, %d, 0);", sid, season)
channelQuery += fmt.Sprintf("INSERT INTO servers (server_id, season, current_players) VALUES (%d, %d, 0);", sid, si%3)
channels = append(channels, &c)
logger.Info(fmt.Sprintf("Started channel server %d on port %d", count, ce.Port))
ci++
@@ -209,6 +228,9 @@ func wait() {
}
func preventClose(text string) {
if erupeConfig.DisableSoftCrash {
os.Exit(0)
}
fmt.Println("\nFailed to start Erupe:\n" + text)
go wait()
fmt.Println("\nPress Enter/Return to exit...")

View File

@@ -1,8 +0,0 @@
To bring up fresh database:
migrate.exe -database postgres://user:password@host:port/dbname?sslmode=disable -path /pathto/migrations up
To tear down database
migrate.exe -database postgres://user:password@host:port/dbname?sslmode=disable -path /pathto/migrations down
More info:
https://github.com/golang-migrate/migrate/releases/tag/v4.15.2

Binary file not shown.

View File

@@ -1,9 +1,9 @@
package binpacket
import (
"erupe-ce/common/byteframe"
"erupe-ce/common/stringsupport"
"erupe-ce/network"
"erupe-ce/common/byteframe"
)
type MsgBinMailNotify struct {

View File

@@ -1,8 +1,8 @@
package binpacket
import (
"erupe-ce/network"
"erupe-ce/common/byteframe"
"erupe-ce/network"
)
// MsgBinTargeted is a format used for some broadcast types

View File

@@ -87,4 +87,4 @@ func (c *CryptPacketHeader) Encode() ([]byte, error) {
}
return buf.Bytes(), nil
}
}

Some files were not shown because too many files have changed in this diff Show More