Commit Graph

131 Commits

Author SHA1 Message Date
Aaron Kimbrell
e2d6c4124b feat(chat): answer the client's minimum chat mode requests
Before private (7), team (8) and local team (10) chat the client asks
the chat server for the minimum chat mode of the channel
(LWOChatComponent::RequestMinimumChatMode; it answers every other
channel itself) and hands the answer to its chat UI. DLU never
answered. Live answered chat mode 0 with the requested channel (74 of
74 team answers in the captures: 53 05 00 39 00 00 00 00 00 08).

The chat server now answers with the lowest chat mode among who reads
the channel (the sender and their online teammates, or the sender and
the recipient), using the GM level as the chat mode as DLU does
everywhere else; the private answer also echoes the recipient's name
and GM level (0 when offline). Inferred: the minimum for GMs (no live
GM sample) and the answer when the recipient is offline.

Check: type in team chat and whisper another player: the messages send
as before and the chat box shows no error; do the same with a GM in
the team.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 03:50:02 -05:00
Aaron Kimbrell
109a936798 feat: live updates move every server onto a new build without a restart
With new binaries in place, master moves everything onto them while the
server keeps running (the dashboard's Live update, /liveupdate or SIGUSR2 to
master):

- database migrations of the new build first; a failure stops there
- UGC finishes the jobs it is running (queued rows stay pending), auth
  restarts, chat hands its teams to master for the next chat server; master
  starts the new processes and retries ones that don't come back
- once the new chat server is up (CHAT_SERVER_READY) every world connects at
  once and sends its players again (LoginSessionNotify resync, no login logged)
- every world instance is replaced with an instance migration: public worlds
  and private ones (same password) at once, properties after the old instance
  saved and froze the property (MIGRATE_PREPARE: no building, claiming or
  saving there any more), activity zones and character select once their
  players left or after a wait; empty instances just stop, zones in
  prestart_worlds get a new one first
- the dashboard restarts last and picks the status up again

Players land where they stood (position carried in CarriedPlayerState, also on
properties and Moon Base). Draining instances get no new players
(InstanceMigration::AcceptsNewPlayers) and show as "Moving players" in the
world list. The order lives in LiveUpdateMachine.h without master state and is
unit tested; master's glue is LiveUpdateCoordinator. Master itself is not
replaced. Message IDs are appended only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:31:23 -05:00
Aaron Kimbrell
d43cdef104 feat(mail): notify online recipients of new mail on any world
Mail sent to someone who is not in the sender's world (system mail with
no address, and all player-to-player mail) now reaches them: the world
sends a MailNotify (Chat::MAIL, unused until now) to the chat server,
which passes it to the world the receiver is in, and that world sends
the client its unread count with a NewMail NotificationResponse.
Receivers in the same world are told directly. Player-to-player mail
did not notify the receiver at all before.

Replaces the TODO in Mail::SendMail.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:31:04 -05:00
Aaron Kimbrell
5a9a3e380b refactor: master packets as structs
Every MASTER service packet is now an LUBitStream struct (docs/PacketArchitecture.md,
PR 14) and the master server's switch is a dispatch map (PacketDispatcher), as are the
master handlers of the world, chat and dashboard servers.

- dNet/MasterPackets.h: RequestZoneTransfer, RequestZoneTransferResponse, ServerInfo,
  RequestSessionKey, SetSessionKey, SessionKeyResponse, NewSessionAlert, PlayerAdded /
  PlayerRemoved, CreatePrivateZone, RequestPrivateZone (passwords still cut to 50
  characters when read), WorldReady, WorldReadyInfo (WORLD_READY to the dashboard),
  PrepZone, Shutdown, ShutdownResponse, WorldShutDown (SHUTDOWN_RESPONSE to the
  dashboard), ShutdownUniverse, AffirmTransferRequest/Response, RequestServerList,
  ServerListResponse, DashboardShutdown, ConfigReload, InstanceShutdown. The Send*
  functions are gone; MasterPackets::SendToMaster(msg) and SendTo(sysAddr, msg) send a
  struct.
- The dashboard and instance migration structs (PlayerAction, DataChanged, Dashboard
  messages, MessageCapture, InstanceMigration) are LUBitStreams of the MASTER service now
  and moved to dNet/master/, included by MasterPackets.h. Their payloads are unchanged;
  master forwards them by re-serializing the struct instead of copying raw bytes.
- InstanceManager, ZoneInstanceManager, MigrationCoordinator, dServer (server info, zone
  transfer response), auth (SET_SESSION_KEY), the world (session keys, player added and
  removed, world ready, shutdown response, affirmations, prep zone, shutdown universe) and
  the dashboard (server list, instance shutdown, config reload, announcements, player
  actions, message capture) send and read structs.
- The login stamps are a `stamps` field of RequestZoneTransfer and
  RequestZoneTransferResponse (read leniently as before: a message without them reads as
  empty); master adds its stamps in the REQUEST_ZONE_TRANSFER handler and when it answers,
  as it did.
- InstanceManager::GetInstanceBySysAddr takes a const address.

Verified: tests/dGameTests/dNetTests/Legacy/MasterPacketsLegacy.h is a verbatim copy of
the old writers and readers; MasterPacketsTests requires identical bytes for a grid of
inputs, checks the old readers read what the structs write, round trips and truncation,
hand written golden packets, that zone transfers without stamps still read, that the dashboard/migration structs write what
"header + Serialize" wrote, and that the dispatcher drops truncated packets. No wire
bytes changed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:30:50 -05:00
Aaron Kimbrell
796fd1b941 refactor: chat packets as structs
Every packet of the chat service is now an LUBitStream struct in dNet/ChatPackets.h
(docs/PacketArchitecture.md, PR 13), and nothing in the chat server or the chat side of
the world server reads or writes a packet by hand any more.

- World <-> chat: LoginSessionNotify, UnexpectedDisconnect, GMLevelUpdate, GMMute,
  Announcement (GM announce), CreateTeam, TeamUpdate (TEAM_GET_STATUS to worlds),
  AchievementNotify, ShowAllRequest, FindPlayerRequest.
- Client -> world -> chat (friends, ignore list, teams, general and private chat):
  GetFriendsList, AddFriendRequest, AddFriendResponse, RemoveFriend, GetIgnoreList,
  AddIgnore, RemoveIgnore, GeneralChatMessage, PrivateChatMessage, TeamInvite,
  TeamInviteResponse, TeamLeave, TeamKick, TeamSetLeader, TeamSetLoot, TeamGetStatus.
  The 77 bytes the handlers skipped are named fields now (the sender block the client
  fills in); the 4 unused bytes after the player ID are kept as `unknown`.
- What the client receives. Chat service (ChatPackets::Client): GeneralChatMessage
  (replaces SendChatMessage; SendSystemMessage stays as a helper built on it),
  PrivateChatMessage. Client service (ClientPackets, as structs go in the file of the
  ServiceType in their header): SendCannedText (replaces SendMessageFail), GetFriendsListResponse, AddFriendRequest,
  AddFriendResponse, RemoveFriendResponse, UpdateFriendNotify, WhoResponse,
  ShowAllResponse, Get/Add/RemoveIgnoreResponse, TeamInvite, TeamInviteInitialResponse,
  and the team game messages chat writes (TeamInviteConfirm, TeamGetStatusResponse,
  TeamSetLeader, TeamAddPlayer, TeamRemovePlayer, TeamSetOffWorldFlag) as TeamGameMsg
  structs, since chat doesn't link dGame's NetGameMsg.
- WORLD_ROUTE_PACKET is ChatPackets::WorldRoutePacket (its own file, dNet/WorldRoutePacket.h,
  since it carries packets of other services): the target and the inner packet.
  ChatPacketHandler::SendRouted replaces the per-function route headers and
  SendRoutedMsg.

Dispatch: dNet/PacketDispatcher.h is a dispatch map from packet ID to (struct, handler
function); packets that fail to Deserialize are logged and dropped. The chat server's
switch and the world's HandlePacketChat switch are now maps. The handlers take the
structs; their logic is unchanged. World code sends to chat with ChatServerLink::Send
(dGame) instead of writing to Game::chatServer by hand. eChatChannel,
eChatMessageResponseCode and eAddIgnoreResponse moved to dCommon/dEnums so the structs
can use them.

Verified: tests/dGameTests/dNetTests/Legacy/ChatPacketsLegacy.h is a verbatim copy of
the old senders and readers; ChatPacketsTests (25 tests) sends a grid of inputs through
both and requires identical bits, bytes and destination, checks the old readers read
what the structs write, round trips every struct, checks truncated packets are refused,
and has hand written golden packets for general chat, canned text, GM mute and a routed
team game message. Breaking one field width (UpdateFriendNotify) and the TeamAddPlayer
zone flag made the tests fail. No wire bytes changed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:30:50 -05:00
Aaron Kimbrell
e213a7aeff feat: web dashboard and playground work
The NexusDashboard-parity dashboard (dDashboardServer) and everything built on it on the experimental branch:
accounts, characters, properties and moderation tools, permissions shared with in-game slash commands, economy
reports, World 3D and property 3D views with client scenery, scheduled events (features, vanity changes, live
events, announcements, restarts), vanity files and events, the CDClient browser, the message inspector with saved
captures, chat filter tools, community challenges, live ops, the AI moderator helper, and the server-side changes
they need.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:30:43 -05:00
David Markowitz
6f3a8d502f feat: logging structure improvements (#2037)
* feat: logging structure improvements

tested that logs are sorted by the folder argument and that the directories are created recursively.
tested that crash dumps follow the same exact name (+Crash_...name..._pid.log) so you can match the crash dump to the corresponding log file much easier

* Potential fix for pull request finding 'Use parsed cloneID when constructing the log folder'

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* const

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-09-26 21:35:58 -05:00
David Markowitz
a1891955e2 fix: leave team when fully logged out (#2007)
* feat: spawner weights

* remove ref

* default weights to 1

* fix: remove team member if they've logged out

tested that if i logout, after 20 seconds the team member is removed.
2026-06-20 02:50:49 -07:00
David Markowitz
a156a8fcba fix: security vulnerabilities (#1980)
* fix: security vulnerabilities

Tested that all functions related to the touched files work

will test sqlite on a CI build

* fix failing test

* ai feedback

* add buffer size checking

* use c_str

* dont log session key

* Try this for a mac definition

* be quiet apple
2026-06-07 20:59:11 -07:00
David Markowitz
5410acffaa fix: chat server crash (#1931)
* fix: chat server crash

* Update dChatServer/ChatServer.cpp

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-16 13:48:57 -08:00
David Markowitz
ca60787055 fix: ffa -> shared loot for activities (#1925) 2025-10-26 01:01:21 -07:00
David Markowitz
4a577f233d fix: hardcore mode fixes (#1883)
fixes hardcore modes uscore drops
adds config option for excluded item drops

f

feat: Add logging for config options on load and reload

feat: Add logging for config options on load and reload
2025-09-21 20:12:50 -05:00
David Markowitz
6389876c6e feat: convert character ids to 64 bits (#1878)
* feat: convert character ids to 64 bits

remove all usages of the PERSISTENT bit with regards to storing of playerIDs on the server.  the bit does not exist and was a phantom in the first place.
Tested that a full playthrough of ag, ns and gf was still doable.  slash commands work, ugc works, friends works, ignore list works, properties work and have names, teaming works.
migrating an old mysql database works . need to test an old sqlite database

* fix sqlite migration

* remove nd specific column migration
2025-09-19 01:12:23 -05:00
David Markowitz
f6c13d9ee6 Replace Quaternion with glm math (#1868) 2025-09-06 19:18:03 -07:00
jadebenn
3364884126 Consolidate serviceID enums into one enum (#1855)
* merge ServerType and ServiceID enums

* rename eConnectionType to ServiceType in preparation for enum unification

* unify ServiceID and ServiceType enums

* shrink ServiceType to an 8-bit integer

* fix linux compilation error and update gamemsg test

* return to uint16_t

* Update dNet/AuthPackets.cpp

Use cast instead of padding

Co-authored-by: David Markowitz <39972741+EmosewaMC@users.noreply.github.com>

* Add default case to MasterServer.cpp

* move ref back to type

* Another formatting fix

* Fix comment to be more accurate

---------

Co-authored-by: jadebenn <9892985+jadebenn@users.noreply.github.com>
Co-authored-by: David Markowitz <39972741+EmosewaMC@users.noreply.github.com>
2025-08-20 20:26:48 -07:00
Aaron Kimbrell
61921cfb62 feat: refactor web server to be generic and add websockets framework (#1786)
* Break out changes into a smaller subset

* NL@EOF

* fix windows bs
add player ws updates
add websocket docs

* tested everything to make sure it works

* Address Feedback
2025-05-14 22:38:38 -05:00
David Markowitz
0e551429d3 chore: move all teams logic to its own namespace to consolidate logic (#1777)
* Add invite initial response msg

re-do team leave logic to send more accurate messages

Players are still able to leave the team with the same results as before, however now the correct messages are sent to team chats (no fixes for local teams).

* chore: move team logic to separate container

Makes it easier to follow team logic when you're not bouncing between 3 classes in 3 files.  Consolidates all team logic to 1 namespace in TeamContainer.  No logic changes were done, only renaming and fixing errors from the moving. TeamData should be replaced with unique_ptrs at some point so the Shutdown method can be removed from TeamContainer.
2025-05-05 09:04:43 -05:00
David Markowitz
55d409eb82 Add invite initial response msg (#1775)
re-do team leave logic to send more accurate messages

Players are still able to leave the team with the same results as before, however now the correct messages are sent to team chats (no fixes for local teams).
2025-04-23 01:56:38 -07:00
David Markowitz
65f3c33ca5 chore: use client enum packet type instead (#1776)
Same values, different namespace and not duplicated
2025-04-23 01:55:52 -07:00
David Markowitz
6f94043b33 feat: broadcast achievements in chat as in live (#1771)
* feat: broadcast achievements in chat as in live

Tested that everyone on the receiving players' friends list receives the announcement as it went out in live.  Only works for achievements that have an entry in the MissionEmail table.  This may have been sent out to everyone in your zone as well however we don't really have a way to verify this aside from questioning why the client checks for the receiver being in the ignore list.  This is the only hint to me that this may have been broadcast to more than friends but again, no proof.

* Add initial response msg and sending

* Revert "Add initial response msg and sending"

This reverts commit fb942e4692.
2025-04-19 07:36:53 -05:00
Aaron Kimbrell
566791e647 chore: limit API to only listen on localhost (#1740) 2025-01-25 20:47:12 -06:00
Gie "Max" Vanommeslaeghe
dc602a94eb Merge pull request #1715 from DarkflameUniverse/webapiv2
feat: Chat Web API (now with no threading)
2025-01-17 22:38:15 +01:00
Aaron Kimbre
3faf9eea45 fix invalid players from showing up in api response 2025-01-15 15:50:30 -06:00
Aaron Kimbre
9542216650 comments and tweaks 2025-01-15 14:59:30 -06:00
Aaron Kimbre
5b8fe2cba0 refactor again 2025-01-15 13:48:49 -06:00
David Markowitz
8abc545bd1 fix: use generated bcrypt password for internal master connections (#1720)
* add password hashing for master server

* use define
2025-01-10 01:45:20 -08:00
David Markowitz
136133dde2 fix: friends (#1726)
* fix

* Update ChatPacketHandler.cpp
2025-01-08 22:44:55 -06:00
David Markowitz
23551d4ed8 fix: friends not updating and using incorrect world (#1724)
* fix: friends not updating and using incorrect world

* use better reset logic

* actual fix for real
2025-01-06 20:25:51 -06:00
Aaron Kimbre
72ae55981b fix here too 2025-01-06 13:55:43 -06:00
Aaron Kimbre
88376c233c cleanup and make the web routes cleaner 2025-01-06 01:23:29 -06:00
Aaron Kimbre
f3b4143698 fix typo 2025-01-05 18:31:53 -06:00
Aaron Kimbre
7a99e8ee6b don't unecessairly convert to string 2025-01-03 09:27:48 -06:00
Aaron Kimbre
210bc48149 return 204 when no data 2025-01-02 23:11:06 -06:00
David Markowitz
e757086465 include optimization 2025-01-02 20:28:03 -08:00
David Markowitz
e9ee3e21cf Update PlayerContainer.h 2025-01-02 20:24:53 -08:00
David Markowitz
631980af3a add json stuff 2025-01-02 20:14:07 -08:00
David Markowitz
6e66c5c362 works 2025-01-02 18:42:50 -08:00
Aaron Kimbre
7aaa69e42d lol, fix it 2025-01-02 20:19:23 -06:00
Aaron Kimbre
181bb0ce14 Address some fo the feedback 2025-01-02 20:09:44 -06:00
Aaron Kimbrell
2b325165aa Update dChatServer/ChatWebAPI.h
Co-authored-by: David Markowitz <39972741+EmosewaMC@users.noreply.github.com>
2025-01-02 20:03:59 -06:00
Aaron Kimbrell
94d53fa77c Update dChatServer/ChatWebAPI.cpp
Co-authored-by: David Markowitz <39972741+EmosewaMC@users.noreply.github.com>
2025-01-02 20:03:44 -06:00
Aaron Kimbrell
846ba894a4 Update dChatServer/PlayerContainer.cpp
Co-authored-by: David Markowitz <39972741+EmosewaMC@users.noreply.github.com>
2025-01-02 20:03:16 -06:00
Aaron Kimbre
fd1ce75380 whitespace 2025-01-02 17:06:08 -06:00
Aaron Kimbre
3578076eca even more cleanup, and make the tryparse work properly 2025-01-02 17:04:07 -06:00
Aaron Kimbre
7d06d012b5 formatting and more cleanup 2025-01-02 16:48:31 -06:00
Aaron Kimbre
126701b5fe Make startup cleaner and don't listen by default 2025-01-02 16:35:27 -06:00
Aaron Kimbre
2d08ec641c cleanup and fixes 2025-01-02 16:28:34 -06:00
Aaron Kimbrell
9387a8e3d1 Merge branch 'main' into webapiv2 2025-01-02 16:13:17 -06:00
Aaron Kimbre
e86f4e011b redo it with mongoose
add all previous POC api endpoints
2025-01-02 16:11:45 -06:00
Aaron Kimbre
070bec697c Alllll the groundwork 2025-01-02 00:45:53 -06:00