Code:
GUI <==> Client Shell <==> Client Engine <==> Internet <==> Server
| ^
\-> 3D World -/
GUI talks to the Client Shell via a "text-based" messaging interface, plus a secondary "3d world" interface.
GUI <==> Client Shell
Observers for when something in the player-state has changed.
Command-Requests for when the user tells the GUI to do something. (from "Get my AA" to "tell john he sucks".
3d world interface that renders the game-world and allows for hit-testing. The GUI provides the 3d world with a surface of some kind to render on.
Command-requests return a Future (see
wikipedia). The GUI can request to get a message when a future is evaluated.
Observers are just requests to get a message when a value is changed. This is useful for things like HP, Stats, or other displayed items.
Client Shell talks to the Client Engine. It needs to determine if the GUI is talking nonsense, parse the commands and requests into low-level code communication with the Engine, and send messages to the GUI when things it asked for have been changed. The Client Shell can maintain a cached state of the player's stats, or just forward all requests to the server: that is an implementation detail.
Client Engine talks over the internet to the Server. Here is where the opcode and networking stuff comes in.
---
This is all architecture details. But it would cut the messy GUI code away from the opcode, and allow you to code up a crappy-GUI that gets replaced after the project is working, and a GUI that is pretty independant of the game-rules.
---
Now, really blue-sky for game features:
Server-defined currencies. (with trade restrictions)
Server-defined item flags. (Lore, etc)
Server-defined item properties.
Server-defined character attributes.
Server-defined "can equip" rules.
Server-defined "can trade to player X" rules.
Server-defined "can trade to NPC X" rules.
Server-defined equipment slots.
Server-defined "can-put-in-bag" rules.
NPC/game-event Interaction dialogs:
Lists of options
Lists of purchases (arbitrary currency)
Server-defined commands, grouped by server-defined groups. (ie, dzadd, etc)
Pet(s) control dialogs (server-defined list of commands you can give)
That might get too general, and require too much client-server chatter. But much of that doesn't change that rapidly, and can be cached (the fact that right-clicking on an NPC opens a "talk", "pickpocket" or "examine" dialog would have to be told to the client once with the right kind of caching system.)
The Client-Engine should ideally cache some of the information (if the server says it is cacheable).
Maybe the Server would be allowed to send Scripts to the Client-Engine? Then when the user clicks on a dialog, the client could be more responsive, and not have to wait for the server to figure out what should happen. So long as the script isn't trusted (ie, it changes UI-state, not game-state) and the engine relies on the server to confirm the action was legal, it would be safe from cheating.
...
The goal is to be able to have a custom defined set of stats and skills, determined by the particular server. Given that you don't have a hard set of rules for the game, this also means you don't lock youself into a particular set of gameplay.
The server might have to modify the GUI, or the GUI might have to be flexible, to allow for some UI tweaks. But one could instead take the "dialog" approach: the server says "there is a SKILLS button. Clicking on it opens the SKILLs dialog. The SKILLs dialog is a LIST of [ SKILL_CONTROL["SKILL::CLIMB"]...SKILL_CONTROL["SKILL::PARRY"] ] and one BUTTON (CLOSE). SKILL_CONTROL[SKILL_NAME] is a pair [ATTRIBUTE_DISPLAY[SKILL_NAME], SKILL_TWIDDLE_CONTROL]. A SKILL_TWIDDLE_CONTROL is a toggle over 3 options ["CONCENTRATE", "IGNORE", "ATROPHY"].
It won't be pretty, but that is enough information to create a skills dialog with some interactive parts.
Toss version-GUIDs next to each of those, so when the server updates the list of skills, the client doens't display the old one, and when the server doesn't change it, the client doesn't have to rerequest the list of skills from the server.
Start with a basic layout engine. Add in the ability to override a default widget layout by name and version-GUID with a custom one (ie, the GUI would first ask the local CustomGUI-DLLs "do you have a control for SKILL_CONTROL["SKILL_NAME"] version GUID{1234-adfa-baad-f00d1234}? If the CustomGUI-DLL said "yes, with GUID{...}", it would check if it already has that GUID custom control in it's GUI cache (and use the cached one), or use the CustomGUI-DLLs version otherwise. Otherwise it would query the server "so, what exactly is a SKILL_CONTROL[]?".
But that is going too deep. To start with, the GUI would have to be kept in sync with the server, and the server would only tell the GUI what it expects to hear. Faster prototype. Of course, you could deal with this by having a Custom-GUI-DLL with all of the server dialogs pre-loaded in it. Not relying on this this allows you to tweak the gameplay on the server-end without having to update the client manually. It also means that logging into a server with very different character stats works without a problem. A keen server would write a custom-GUI-DLL to make their character stat display look prettier, and different servers could steal each other's custom controls...
You could even be paranoid, and run the Custon-GUI-DLL in a seperate process and/or in a sandbox, so they can't poke into the game memory.
I want someone to be able to create an AA system, a use-based skill system, a buy-abilities-from-an-NPC system, a level-up-and-spend-stat-points system, a raid/group management system, or a build-items-from-raw-materials system all on the same client without having to rewrite it.
Yes, this is blue sky. You did ask.
...
What else...
The spell/effect particle engine should be able to get data from the GUI, the Client Shell, and from the Server (indirectly, via the Client Shell). It probably needs to be pretty integrated with the 3d engine if you want effects like "the sword glows" or "a bolt of fire shoots out from your hand and heads towards the target", and not just random nimbus's around characters.
The client should send "I am here, I am here, I am here" packets to the server. In addition, it should sent a trap-door (CRC32) of "the justification of my last 12 seconds of movement and my location at this time" every 5 seconds, and keep track of a complete justification for the last 2 minutes. The server can ask for the actual justification of movement whenever it wants
after the fact, which can be checked against the sent CRCs, for internal consistency, and against movement packets that actually arrived at the server.
If the player is move-hacking, it will be hard to generate a justification of movement that lines up with the CRCs, the location packets sent to the server, and the rules of the game. Clients who regularly disconnect when requested for justification packets get flagged as potential cheaters. Clients who give bad justifications are flagged. Clients who seem to move faster than the game thinks is possible are sent requests, as well as clients randomly.
This doesn't prevent movement cheating, but it does make it catchable.
In effect, the client is trusted with determining it's location, but it must also provide
justification for it's movement when requested.
If justification is expensive to verify, one could even farm it off to another client (pick two random clients, they are unlikely to be both cheating in exactly the same way), store up the details and check it when server load is lower, or just drop it. Heck, one could ignore the justification sent, and just ask out of paranoia.
...
That's it for now. Food!