This project exists to preserve and archive an early version of the game (v28 of global)
A DLL which will auto hook the functions to make a localhost and window mode can be found here
General:
- Simulated latency with jitter (set in config) to make dev environment simulate a real world connections when within network
Login server:
- Login user
- Auto-register (optional feature to automatically create accounts on first login attempt)
- Show EULA on first login
- Pin
- Display world ribbons
- Display world messages
- Display world status (e.g. overpopulated)
- World selection
- Channel selection
- Create character
- Delete character
- Delete character informs world servers
- Migrate to channel server
- Show worlds, channels, world status etc from information sent from world server
- Prevent players from accessing dead channel
- Server resets login status upon restart for dangling users
World server:
- Keep track of player count
- Send information to login server
- Send IP, port to channel for change channel requests
- Forward player connects to channels
- Forward player leaves game to channels
- Broadcast buddy events
- Broadcast party events
- Broadcast guild events
- Forward whisphers
- Allow gm command to actiavate exp/drop changes accross all channels
- Allow gm commands to update information displayed at login
- Propagate character deletion to channels
- Party sync when channel or world server are restarted
- Guild sync when channel or world server are restarted
Cashshop server:
- List items
- Allow purchases via different currencies
Channel server:
- GM commands
- Players can see each other
- Player can change channel
- Players can see other movement
- Player chat
- player use portal
- Player allocate skill points
- Player stats
- Player use skills
- Player skill logic (haste etc)
- Player inventory (needs a re-write)
- Player use item (scrolls, potions etc
- Player use cash item (super megaphones, etc)
- Player drop item(s)
- Player pets
- NPC visible
- NPC movement
- NPC basic chat
- NPC shops
- NPC stylist
- NPC storage
- Load scripts from folder (incl. hot loading)
- Map instancing
- Mob visible
- Mob movement
- Mob attack
- Mob skills that cause stat changes or summon other mobs (not on death)
- Mob death
- Mob respawn
- Mob spawns mob(s) on death
- Mob drops
- Mob boss HP bar
- Minigames
- Whisphers
- Find / Map in buddy window
- Buddy list
- Buddy chat
- Party creation
- Party invite
- Party accept/reject
- Party expel
- Party chat
- Party HP bar
- Guild creation/disband
- Guild invite
- Guild join/leave
- Guild emblem
- Guild chat
- Guild points update
- Guild rank titles change
- Guild rank update
- Guild notice update
- Guild expel
- Guild member online notice
- Kerning PQ
- Ludi PQ
- Balrog boat invasion
- Deleted character removes from guild
- Deleted character removes from party
- Trade
- Communication Window
- Quests
- Reactors
- Server resets login status upon restart for dangling characters
Metrics:
- Channel population
- Server thread count (OS and Go)
- Server memory usage (heap and stack)
- Monster kill rate
- Ongoing trades
- Ongoing minigames
- Ongoing npc script interactions
- Number of parties
See screenshots section for an example Grafana dashboard
- Profile the channel server and do the following:
- Reduce branches in frequent paths
- Determine which pieces of data if any provide any benefit in being converted SOAs
- Implement AES crypt (ontop of the shanda) and determine how to enable it in the client
- Move player save database operations into relevant systems
- Player inventory needs a re-write
- Investigate party reject invite packet from client (it looks like garbage)
- Sunnyboy for providing a list of idbs for which this project would not have started
- The following projects were used to help reverse packet structures that were not clearly shown in the idb
- NX file format (see acknowledgements at link)
All instances are run through the main executable by passing a type and an optional config file.
Valhalla.exe -type login -config config_login.toml
Valhalla -type login -config config_login.toml
Each server type can be configured either via its corresponding config_<type>.toml
file or through environment variables.
For containerized setups, the TOML files used are the ones inside the docker
directory.
Environment variable names follow the same structure as the TOML keys, but with prefixes added.
For example, in TOML:
[login]
clientListenAddress = "0.0.0.0"
clientListenPort = "8484"
The equivalent environment variables would be:
VALHALLA_LOGIN_CLIENTLISTENADDRESS=0.0.0.0
VALHALLA_LOGIN_CLIENTLISTENPORT=8484
The login server supports an optional auto-registration feature that automatically creates new accounts when users attempt to login with credentials that don't exist in the database. This is useful for development environments or private servers where you want to allow easy access without manual account creation.
To enable auto-registration, set autoRegister = true
in your config_login.toml
:
[login]
autoRegister = true
Or via environment variable:
VALHALLA_LOGIN_AUTOREGISTER=true
When enabled:
- Users attempting to login with non-existent credentials will have accounts automatically created
- New accounts are created with default values: gender=0, dob=1111111, eula=1, adminLevel=0, PIN="1111"
- The password provided during the first login attempt is hashed and stored
- The default PIN is "1111" and can be changed by the user later if
withPin = true
Note: For production environments, it's recommended to keep this disabled (autoRegister = false
) for security reasons.
NPCs are scripted in javscript powered by goja
Taken from here
- #b - Blue text.
- #c[itemid]# - Shows how many [itemid] the player has in their inventory.
- #d - Purple text.
- #e - Bold text.
- #f[imagelocation]# - Shows an image inside the .wz files.
- #g - Green text.
- #h # - Shows the name of the player.
- #i[itemid]# - Shows a picture of the item.
- #k - Black text.
- #l - Selection close.
- #m[mapid]# - Shows the name of the map.
- #n - Normal text (removes bold).
- #o[mobid]# - Shows the name of the mob.
- #p[npcid]# - Shows the name of the NPC.
- #q[skillid]# - Shows the name of the skill.
- #r - Red text.
- #s[skillid]# - Shows the image of the skill.
- #t[itemid]# - Shows the name of the item.
- #v[itemid]# - Shows a picture of the item.
- #x - Returns "0%" (need more information on this).
- #z[itemid]# - Shows the name of the item.
- #B[%]# - Shows a 'progress' bar.
- #F[imagelocation]# - Shows an image inside the .wz files.
- #L[number]# Selection open.
- \r\n - Moves down a line.
- \r - Return Carriage
- \n - New Line
- \t - Tab (4 spaces)
- \b - Backwards
This repository now includes Kubernetes manifests that mirror docker-compose services.
Prerequisites:
- A Kubernetes cluster (minikube, kind, K3s, or cloud)
- kubectl configured to point to the cluster
- A container registry or a way to load local images into your cluster
Build and load the image:
- Build the image from the Dockerfile:
docker build -t valhalla:latest -f Dockerfile .
- If using kind:
kind load docker-image valhalla:latest
- If using minikube:
minikube image load valhalla:latest
- Otherwise, push
valhalla:latest
to a registry your cluster can pull from and update the image in your helm values.
Deploy:
helm install valhalla ./helm
Service discovery changes (compared to docker-compose):
- K8s services use hyphens. Configs inside the pods are adjusted accordingly:
- login-server, world-server, db
All ports are via ClusterIP, and can be exposed via Ingress-Nginx.
You will need to use the ingress-nginx
deployment to expose your service.
The following values should be used to deploy the helm chart:
tcp:
8484: valhalla/login-server:8484
8600: valhalla/cashShop-server:8600
8685: valhalla/channel-server-1:8685
8684: valhalla/channel-server-2:8684
8683: valhalla/channel-server-3:8683
... etc
You will need to add all the channels you intend on having, and the port decreases by 1 for each additional channel
- Deploy Ingress-Nginx via Helm
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm install -n ingress-nginx ingress-nginx ingress-nginx/ingress-nginx --create-namespace -f values.yaml
- Update Maplestory client to use ingress-nginx external IP
kubectl get svc -n ingress-nginx
- Update Valhalla config to use ingress-nginx external IP
channel.clientConnectionAddress: "<loadbalancer-ip"
- Upgrade/Restart Helm chart
helm upgrade -n valhalla valhalla ./helm -f values.yaml