Home » Stars! Clones, Extensions, Modding » Stars! Nova - Development » Orders
Orders |
Wed, 06 July 2011 23:03 |
|
Aeglos | | | Messages: 142
Registered: May 2011 Location: Chile | |
|
The great Id refactoring is practically done, and the Intel file is well underway to being properly structured.
So, let's talk Orders now; Let's clear some ideas for it's future restructuring, if any.
Right now, the Orders file is nothing more than an updated State; it sends the state read from the intel plus any changes the client made. I was under the impresion that the idea was to change this to send some kind of order commands that the server would process, instead of merging each client's state to it's master copies and then process fleets, stars, etc.
Right now the server keeps a record of each client's valid state for the start of each turn. Due to this, It's easier for the server to check for errors and cheats than before, but it's not flawless. Checking fleet positions for example; it can be done but it would be awkward to loop all fleets and compare their coords for each player when reading their turns. We would need to do this for stars also, and for almost all of their fields, else a client can silently modify some data from objects and it would be merged into the server's master copies.
Ideally the client would send only commands like "add waypoint to fleet #xx", "remove item from star #xx's queue" or "activate mass driver on star #xx". There should be a dinstinct and finite number of commands a client can send... in fact, the amount of commands for Stars seems to be very small. I can think of this command "types":
- Add/remove waypoint
- Merge/split manually
- Modify cargo manually
- Add/remove item from production queue
- Mark/Unmark a star for leftover resources only
- Activate Mass Driver (could be waypointed since starbases are fleets)
- Change research target
- Change research budget
- Add/edit/remove a design (edit could be a remove-add combo).
- Add/edit/remove a battleplan
- Change a relation
And that seems to be it... I can't think of anything else. So the list is pretty small to be passing the whole state down to the server.
This could easily be achieved with a bunch of concrete order implementations that inherit a base Order class.
Thoughts?
[Updated on: Wed, 06 July 2011 23:17] Report message to a moderator
|
|
| | | |
Re: Orders |
Thu, 07 July 2011 06:31 |
|
Aeglos | | | Messages: 142
Registered: May 2011 Location: Chile | |
|
The problem with that approach is that the client shouldn't modify it's state at all; it should just tell the server to modify it instead, otherwise it would force a lot of checking server-side for valid values since those changes are not under the server's control.
For the split/merge it would need to check not only the amount of ships and cargo, but also the cargo composition, else the client could magically change colonists into ironium. It would have to check each ship and it's components lest they changed, their individual damage amounts, etc, and see if it all matched the previous fleet values.
The other option of the server just cherry picking which variables to update fails for cases like split/merge where almost all of the values need to be updated.
For the production queues something similar happens, it would have to check each production item's data individually. Consider this; a client which has an item at 50% production edits his orders so that it's at 70%. The server has to check each item to see if the progress has changed, and only allow for decreases in progress, in case someone for example, removed that 50% item by mistake and then added it again, reseting it to 0%; it's a valid order that the server has to accept, so it would need to check all items for special cases like that where some changes are allowed and others not.
It just feels easier to send to the server "merge fleet Y & Z" or "add item to X stars queue", where the checks would be far less. Merging/Splitting would need only to check for same owners and same position (not even nessesary for split) since the server is sure the fleet data has not been tampered with. Production queues would only need to check for component/design availability and star capability. Waypoint modifications would only need to check owners, and if deleting, that the waypoint exists already. (Since editing is simply a remove-add combo).
Report message to a moderator
|
|
| | |
Re: Orders |
Thu, 07 July 2011 07:49 |
|
Musmuris | | | Messages: 96
Registered: June 2011 | |
|
Aeglos wrote on Thu, 07 July 2011 07:02 |
What I understood is that for merging, for example, the client merges the fleets, and sends it's state with the fleets already merged. So the server checks if it's valid and updates it's own copies. But to do so, it needs to first find the two fleets that were merged, and double check that everything is still the same; designs, components, cargo amounts, damage amounts.
|
Well to find the fleets it can use ship IDs as a ship can only ever be in one fleet. Once it's done that it just has to check what cargo is in the new fleets and make sure that the totals are the same as previously, and that each fleet can carry what it now has. Damage ammouns, designs and components CANNOT be changed by the client so it doesn't check those, it just ignores them, throws them away in fact, and keeps what it already has from what it sent to the client.
I.e. it takes the ships from the previous turns, puts them into new the fleet objects, adjusts the cargo and fuel etc.
[edit to remove last edits]
[Updated on: Thu, 07 July 2011 07:59] Report message to a moderator
|
|
| |
Re: Orders |
Thu, 07 July 2011 08:02 |
|
Musmuris | | | Messages: 96
Registered: June 2011 | |
|
Aeglos wrote on Thu, 07 July 2011 07:55 | But there is a flaw there...
If the client sends the fleet already merged and the server uses that as it's data source, then it needs to validate every single field, as the client could have modified those.
|
My point is that the server NEVER READS those fields. Yes - it essentially creates 2 new fleets and moves the ships from it's own data store across. So yes the server is re-doing the client merge. Yes, this harder than just processing a merge order, however it actually may be easier than producing that merge order in the first place.
Just to re-interate, I'm mainly suggesting this as the easiest way from where [i think] we are.
Leave that to one side for now and let's explore the other option how are we proposing to track orders as the client makes them, and how does the UI show the last known state + orders?
[Updated on: Thu, 07 July 2011 08:03] Report message to a moderator
|
|
|
Re: Orders |
Thu, 07 July 2011 08:17 |
|
Aeglos | | | Messages: 142
Registered: May 2011 Location: Chile | |
|
Alrighty then.
I was thinking of adding a collection to ClientState which holds Order objects. We simply add/remove them there when needed.
Order would be a common interface or base class, and there would be concrete implementations; WaypointOrder, ProductionOrder, MergeOrder, RenameOrder, etc. Or separated by a Type variable.
Showing state+orders is the trickier part. I can think of two things right now.
Parse the orders after the state, which would be similar to what the server should do. They could use a common order parser, or do it on a per case basis on the client.
Or, hold two state copies on the client, the initial and an updated one, and for each change we both update the state and issue and order. The client sends only orders down to the server, and discards it's changed state each turn in favor for the one on the intel. This feels terribly redundant, but could be easier than the first approach.
The key thing that i'm holding on to is the principle that we shouldn't trust anything that comes form the client; we should expect it to lie, cheat and malverse it's state and orders every time, that's why I'm mostly against sending state to the server. But, as always, I'll go with the majority vote, if for whatever reason implementing orders turns out to be unfeasible.
Report message to a moderator
|
|
|
Re: Orders |
Thu, 07 July 2011 09:32 |
|
Musmuris | | | Messages: 96
Registered: June 2011 | |
|
Currently the whole UI is driven from the client side state and changing that would be a PITA. Having 2 states is an option, and then we'd have to modify the code everywhere to add orders.
Of course there may be orders that change previous orders, e.g. you re-split a merged fleet, or you delete all a fleets way points and re-add a load more. And then do the same again. No problems really of course as you can just grow the list of orders indefinately as each one must make sense if you play them back in the same order.
Another option would be produce orders from the old and new states. I.e. the client would just udpate a new state and then on submit it would work out the orders needed to transform one to the other. However in this case the server would need to verify it all anyway so the client may as well send all it's state over and have the server work out the orders.
In fact that's a better way to think of what I'm suggesting. The Server doesn't just take the state the client sends as the The Truth. It looks at the OLD state it sent and the ORDERS state it gets back and essentially generates what orders were made, checks they are valid, and applies them to the OLD state to produce a NEW state for the next turn. (It probably never actually produces a List<Order> as it were, but that's logically what it's doing). Does that now make more sense of what I was suggesting?
Aeglos wrote on Thu, 07 July 2011 08:17 |
The key thing that i'm holding on to is the principle that we shouldn't trust anything that comes form the client; we should expect it to lie, cheat and malverse it's state and orders every time
|
Absolutely agree - we have to assume the client is going to cheat as someone will, which is why I think of the server working out the orders on the fly and checking them,
Aeglos |
But, as always, I'll go with the majority vote, if for whatever reason implementing orders turns out to be unfeasible.
|
Likewise I'm happy to be persuaded either way, or go along with any decision made. There is some level of pragmatism in what I'm suggesting given where we are in the code base. If we were going from scratch then it may be a different discussion
Report message to a moderator
|
|
| | | |
Re: Orders |
Thu, 07 July 2011 19:53 |
|
evild00d | | | Messages: 14
Registered: July 2009 Location: Norway | |
|
This is an important architectural decision so getting it "wrong" just means that changing it later will cause a lot of pain. I don't like pain I just want stuff to work (like it's that easy)
That said, I'm very much in favor of the proposed command/order solution, but I'm not saying that this is necessarily THE RIGHT WAY(tm).
In this particular case (client-server communication, validation, etc.) storing and passing around state and trying to validate it will likely make things difficult to maintain in the long run. The client- and server-side at some point need to know the state, but conveying a change as a command allows us to capture the player's intent.
With commands (orders if you wish), one of the benefits on the client side would be that undo/redo support would be easy to implement (just one/two stacks of commands and code to reverse commands). On the server side it would make testing, debugging and validation easier. The entire sequence of commands (or resulting events) made during a game could be stored and used as a basis for auditing, running it through external analysis tools, replays, retroactively checking for potential cheats used in a game if a cheat/hack/exploit is published some time after the game completed.
Implementing commands and some kind of "event sourcing" (http://martinfowler.com/eaaDev/EventSourcing.html if you will) is a story for another time
Report message to a moderator
|
|
| | | | | | | | | |
Goto Forum:
Current Time: Tue May 07 22:48:38 EDT 2024
|