jpcsupplies / Economy_mod

Basic Economy System for Space Engineers
13 stars 12 forks source link

Script needs to be able to read/write the bank balance file #2

Closed jpcsupplies closed 9 years ago

jpcsupplies commented 9 years ago

The script should at least be able to read and write to a bank balance file, at present all my attempts to do so have failed. Most file operation methods appear to be blocked by keen except for: Write: MyAPIGateway.Utilities.WriteFileInLocalStorage("bank.txt", [data structure])); Paths: MyAPIGateway.Utilities.ShowMessage("path", togame); MyAPIGateway.Session.CurrentPath Path.GetFileNameWithoutExtension(MyAPIGateway.Session.CurrentPath); string.Format("bank{0}.txt",Path.GetFileNameWithoutExtension(MyAPIGateway.Session.CurrentPath));

I've just redesigned my pseudo code here - all the data is handled by other arrays, so reading and writing is now a simpler process; since we just need the raw data now. Proposed file logic - Pseudo Code (loading):

open bank.txt for reading read entire file into variable close file

{ (Using data) this is an example this part of code already exists and is not part of this TODO feed data into array1, splitting by \n (each record) when reading or writing array1 read each element into array 2, splitting each array2 element by "," only one record at a time can exist in array2, so check data; increment and load next element repeat until desired data is found; or all records have been examined.

Add or edit record as needed. Write back to file variable (recreate \n and ",") (and write data to disk) }

Pseudo Code (writing): having previously read data into array1 write it back to file variable. (file=file+reassemble all the "." and \n (or +=) ) etc open bank.txt for writing write file variable to disk close file

midspace commented 9 years ago

Keen prevent reading and writing of files outside of the game's filesystem. I'm guessing these conditions are imposed by Valve and Steam, otherwise it would be too easy for a mod to be released that can damage people's computers.

By using WriteFileInLocalStorage, you have to remember that all files are accessible by other saved games. If the file is to be only for one save game, then it must contain the game name: Path.GetFileNameWithoutExtension(MyAPIGateway.Session.CurrentPath)

If the file is to be used by any game, then you name it anything, but you will have to manage your file access to prevent file locks in case two dedicated servers are running at the same time.

Saving of complex detail should use the Xml serializer (it's the only serializer available under the API), in conjunction with struct for your data.

Config = MyAPIGateway.Utilities.SerializeFromXML<ServerConfigurationStruct>(xmlText);

jpcsupplies commented 9 years ago

Bank balances are probably safe enough to allow any DS to access, that allows players to mine in one world, sell it and build in the other, although trade markets (when we get that far) should probably be tied to a given save; to make the transition to elite style (station tied) trading not require a total rewrite, although the prospect of a central (federal?) market which spans both worlds has a certain appeal too

jpcsupplies commented 9 years ago

Do you think you could knock up a very basic sub, all it needs to do is read the entire contents of the "bank.txt" file into an integer to be passed back, and vice versa? Basically what your motd does but doesnt get displayed. Have a quick glance at how the /bal command processes the data, pretty much does all the work to the data, i just need a way to GET the data in there.

midspace commented 9 years ago

Sorry, i wont be able to look at code as i am down with the flu. In a few days when i can concentrate on a screen.

jpcsupplies commented 9 years ago

That's fine, no hurry; I can pretty much simulate having read a file to work on the arrays and bug test where I am at now - although the downside there is data persistence; if i change arrays the moment another section reads the load class it reverts.. i really need to figure out a way to allow the contents of the array to survive between calls to my command section; no such thing as persistent globals as far as I can see in c#, and public classes have quirks I am still trying to understand.

midspace commented 9 years ago

Static field. public static List<BalanceData> PlayerBalances = new List<BalanceData>();

jpcsupplies commented 9 years ago

ive tried that, i can read it out but i cant see how to write changes back as they only seem to exist in the current sub, moment the sub ends it seems to throw out the changes.. ive got to test some more to figure out its exact behaviour.. to my thinking the =new part means its cloning the version from the other class, not simply accessing it.. but c# has some weird ways of terming things to what i am used to. Annoyingly many examples online access public classes direct without the =new, (and visual basic has no problems working like that either) but that throws debug errors in c#, about not existing in current context even if you reference it = eg string playerdata = load.balancedata; (do stuff) load.balancedata = playerdata; code snippet examples say this should work if all are public's, in practice you get doesnt exist context debug errors, if you use playerdata = new load.balancedata it works but any changes seem to get lost somewhere. is there a way to reverse the process and keep the changes? or manipulate data like in a global under VB,

eg new load.balancedata = player data;

On the other hand in theory if i just dump the changes as they happen to the bank file they are always kept as the bank file refreshes the array each time a command hits it rending the entire issue moot.

My other option is to code it all like a basic program, wrap the entire script in a loop so it remains in the current sub, and move all my handling in there somewhere; that way I am always working with the "live" data, but i suspect space engineers will treat it like a rogue code in an infinite loop since its basically a deadlocked thread as far as it knows.

jpcsupplies commented 9 years ago

If you pull up last nights changes in git, you will see a big block of commented out code in "public class bank" which wasted several hours and didnt appear to persist - in my attempt to use constructors

this is a major noob question but is there perhaps a way to access defined variables under "public class economy script" from within the subs or bools and make changes ?

Going out on a limb here, i assume that would remain persistent as it wraps the entire show, and everything runs under it... but i expect its considered bad programming style.

midspace commented 9 years ago

I think you are over complicaing something. When the following is loaded, you load up your config from file into memory. public class ChatCommandLogic : Sandbox.Common.MySessionComponentBase

When it is unloaded, you save it out again.

All other access will be through the static instance.

See the ServerCfg varible and the static above it, which willload the entire class into static memory. Because it is static, there is only ever one instance of it. https://github.com/midspace/Space-Engineers-Admin-script-mod/blob/master/midspace%20admin%20helper/Data/Scripts/midspace.adminscripts/ChatCommandLogic.cs

jpcsupplies commented 9 years ago

Ok thanks, ill look into that; can you suggest any c# docs there that may help me wrap my head around it? I am still noob enough in c# a lot of this is still voodoo - ive pretty much figured out arrays which I used a lot in other languages; so im all happy there, I even used a C# version of a for loop (admittedly i should have used a while loop;) hell of a learning curve.

When you are feeling well, Are you still ok to knock up a really basic load and save doesnt need fancy paths or anyhing, just needs to be able to dump a string to a file and vice versa using whatever is left that keen lets you use to access files. I've pretty much grasped splits and arrays i just need something to use them on.

jpcsupplies commented 9 years ago

Really struggling here; going over all the rare modapi docs I can find; but looks like nobody has really tried to write anything useful beyond the whitelist and the example file script.

Are these likely to work, steam guide here http://steamcommunity.com/sharedfiles/filedetails/?id=315625486 lists these in whitelist System.IO.Stream System.IO.TextWriter System.IO.TextReade

checking msdn references, takes me eventually to these examples -

writing https://msdn.microsoft.com/en-us/library/db5x7c0d%28v=vs.110%29.aspx

reading https://msdn.microsoft.com/en-us/library/6ka1wd3w%28v=vs.110%29.aspx

Trouble is i cannot seem to grasp how everything fires everything in C#; VB and C# are meant to be related in visual studio, but the examples have no similarity to anything i was taught in regard to VB program structure. Looks like MS left in some backward compatibility to VB5 and 6, but studio is basically C#. So the VB to C# examples on msdn look nothing like traditional VB, so I cant even convert something I know in VB to C# as the MSDN examples are VB'flavoured C# not traditional VB.

even the VB example section of the links above are using totally alien to me ways of reading/writing, and I used to make VB database engines!.. i feel like the village idiot now, and i aced my software development course back in the day LOL

Even if the above save/load examples should work, I cant see a way to implement them - since i cant work out how i would even fire it off... in vb i would make a module that returned the contents of the file, or the result of my search, in C#.. nothing makes sense! different levels of subs are not allowed to use certain logics, its weird. Especially the subs in subs in subs.. seems so sloppy

If I was trained in C# its probably makes perfect sense, but I am pre-.net vb which appears useless here :/ Would ordering you a pizza help? ROFL

jpcsupplies commented 9 years ago

To quote my steam guide dev comment - Argh really struggling with file operations part on this mod, C#, and by extension keen ModAPi has little resemblence to visualbasic 5 professional logical structure here.. even VB visual studio is coded nothing like pre-dot net VB anymore; so the VB to C# conversion examples dont help either. I am at a loss. Anyone want to help here.. can offer a free pizza... Basically with my current understanding of C#, i need something along the lines of this type of logic. load() being a sub or function or class or type that triggers code to load the contents in full of file bank.txt in the string bankdata. [code] string bankdata; bankdata= load("bank.txt"); // here is the type of thing i need here string[] lines = bankdata.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None); etc [/code]

jpcsupplies commented 9 years ago

and on the flip side: [code] //we have done all the work we need.. reconstruct the raw file structure //convert array elements to seperate by "," into string, and end with a newline between each record and write all elements to string "bankdata" .. assuming we did this to bankdata already - save("bank.txt") = bankdata; // here is the type of thing i need here etc [/code]

same save() and load() could be used to read to and from the other files like the price list etc

jpcsupplies commented 9 years ago

or to cut out the middle man simply: string[] lines = load("bank.txt).Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None); and vice versa

midspace commented 9 years ago

An explanation on the 'client side'.

The Mod API code runs all client and servers simultaneously. There isn't a specific module for servers or for clients.

To make this work, you actually have to write your own logic to check if the mod is running on a server or a client. And in the case of a Host (listen server), it is running BOTH! Otherwise, you would end up with each player creating a and loading a balance file on their own computer.

ie... am I a server? -- then read the bank records. -- set up listen hooks for commands from clients.

am I a client? -- set up listen hooks for commands from server. -- set up chat hooks for instructions from user.

The flow: -- user enters a chat command "/bal". -- client examines the command for what the user wants, and either responds directly (if it already has what it needs), or asks the server for detail. -- client sends special message instruction to server. -- server receives message instruction. -- server disseminates message instruction. -- server runs the Balance Message for the user specified. -- server sends Balance Response instruction to client. -- client receives message instruction. -- client disseminates message instruction. -- client displays balance on screen to user.

What I've written just covers the loading, reading, and writing of the file. There isn't any server/client comms to separate this portion of the code.

jpcsupplies commented 9 years ago

Ahh ok, so DS can work, but needs a bit more voodoo; this commit you just kept it simple so I have the right modules to call for getting stuff to work; and testing; and we can add the DS stuff to the modules later without impacting the main script file..

Am i understanding this correctly?

midspace commented 9 years ago

Absolutely. I'm just trying to keep the focus right, without forgetting the rest of technical debt.

SaltPepp commented 9 years ago

I'm still getting my head around XML as a config data store. I've only used it once for a ordering system program I created a few months ago to store program settings. I've always used the traditional read and write in my projects but going from the restrictions of the API, I'm forced to get used to XML.

jpcsupplies commented 9 years ago

Traditional read write is still theoretically possible, albeit in an arcane form, i beleve thats how midspaces motd works but for what we are trying to do xml make sense, it removes the need for extra split/deliminating processing overhead in our code - and it is what keen uses for everything. Not sure the performance difference, but it removes a lot of array bounds issues which in mods can still crash the main game. If keen uses it, i expect they have it pretty lean and mean anyway, its how their saves work. They save pretty quick.

midspace commented 9 years ago

It's called Serializing and Deserializing. It's fairly easy to set up by mapping directly to your classes which hold your data. As long as you are using Basic datatypes, and not doing anything fancy. And relatively fast compared to reading and converting data manually. Keen only allow Serializing and Deserializing to Xml in the API. Otherwise with the full .Net codebase we could be going straight to Byte arrays, or other forms like JSON.

With Serializing to Xml, we have a fair amount of flexibility, as the Deserializing process can automatically detect changes to your data class, and fill in the gaps.

SaltPepp commented 9 years ago

I guess the fill in the gaps feature is handy

jpcsupplies commented 9 years ago

Now that i've figured out the C# voodoo that translates back to what I called functions in my less decrepit younger years of VB 5 and 6, ive implemented a basically functional pay command - SaltPepp give it a look, and you will see why it makes sense to use it. No crazy for do while loop structures jsut some look.here.and.get.(that).. very sexy in its simplicity.

midspace - if it is ok with you, I am thinking of adding SaltPepp in to the contributor list.. although he can probably do the push/pull request thing, i am not yet familiar with it.. Only reason I held of till now was I wanted to try the pull request thing, and I was worried how we would go with three people pushing to master, what might break.. Toby seems to have a decent grasp of things here so he probably wont nuke our entire codebase by accident. Although if he could do a test pull request first to, for example the sample bank file; so I can see what happens that would be an interesting exercise.

midspace commented 9 years ago

Just add him as a "Collaborator". As I am no longer the owner, I don't have access.

  1. On the right, click "Settings".
  2. On the top left a menu, click "Collaborators".
  3. Confirm your password.
  4. Enter the name "SaltPepp".
  5. Wait a moment for it to confirm the name in the GitHub system then click on the matching user.
  6. "Hit "Add Collaborator".
jpcsupplies commented 9 years ago

I am liking the way we interact with our database more and more, even if we totally threw out the xml stuff -- so long as whatever we did use formatted it into our array for the function call, the main economy.cs file could remain exactly the same as it is now.. all the file code can stay in the bank scripts out of the way..