Converting to "the cloud"


  • Notification Spam Recipient

    I am not a coder by profession, I only do it as a hobby, so I wouldn't be surprised if you came across a few WTFs just by reading this.

    What I have is the following:
    A turn-based campaign system for Warhammer (a tabletop game) written in C#. When you login and it is your turn, you do your actions. If it is not your turn, you see the state of things. Everything is stored in XML (was easier than to setup a db). At the moment there is no concept of concurrent logins, because the original idea was to host the program on a server with remote desktop access, and when you connect to the server (and nobody else is logged in), you can open the program and login. The reason it works this way is because it is all I have experience with

    What I want to do:
    Make it proper multiplayer, i.e. you login with a client, and it connects to a server. My "quickfix" idea is to host all of the XML files "in the cloud", and when you login, it loads these files instead of locally hosted files (Think Dropbox). My ideal solution would actually be some type of MVC, and if I had the time I would do that, but it would involve a lot of rewriting which I find a bit daunting at the moment.

    My question is what would be the best approach, without completely redesigning the whole thing. I am willing to use a db if this is the best recommendation. I hope I am making sense...



  • @Vault_Dweller said:

    XML

    😧

    @Vault_Dweller said:

    redesigning the whole thing

    👍

    @Vault_Dweller said:

    db

    👍


  • FoxDev

    what @Keith said, but times two.


  • Grade A Premium Asshole

    @Vault_Dweller said:

    Make it proper multiplayer

    @Vault_Dweller said:

    My "quickfix" idea is to host all of the XML files "in the cloud", and when you login, it loads these files instead of locally hosted files

    These two ideas are simply incompatible. The risk of collisions would be massively high. I realize you are (hopefully) not designing this for high concurrency and that it would just be something for you and your friends, but the latency in the transaction the way you describe it would be massively high. XML files have no concept of locks or semaphores (to my knowledge). The chances of two people making a change at the exact same time will get pretty high and then you have to have a way to handle that.

    As you are currently doing it, this is handled in logic. I suppose it could be done with your methods, but it would be difficult and fraught with frustration...to put it mildly.

    Also, by exposing the XML as you are proposing, what would keep a person from just altering the XML in a text editor and making themselves win? Once again, I realize this is just for friends, but I have friends who would do shit like that.

    Pick up a Ruby on Rails book. Let a framework handle all the db transactions and schema for you to cut the cost of entry on knowledge down to something that is achievable for the hobbyist. Then go forth, create your idea and have fun. If you get "the bug", then you can go back and learn about all the stuff that is happening behind the scenes in the framework.



  • Have a look at SQLite—a DB is basically just a file, which is easy enough to get started with, but it'll probably perform better than XML once you have a lot of data, or a lot of people trying to access it at the same time.

    I've used one set of .NET bindings for SQLite from PowerShell (but should also work from C#): I think it was this one, but I'll need to double check...



  • You aren't a coder, so I think a lot of what people are saying, while totally valid, isn't going to help you actually solve your problem, which is basically hack together something that works in the smallest time possible.

    I think setting up a simple secondary webapp should be pretty plausible for you, you have a file format that works for you, and ripping it out to start again with a database while solving a lot of problems, solves problems you dont (currently) have, and you can avoid it, at least for now.

    If you were to create a simple website that provides just a 2 field entry, one a text field to provide the name of the submitter and one a file chooser (the latter I believe is still a standard control on all microsoft web technologies) and then submits, uploading your XML file of the game state from that user. Some basic validation would be beneficial, but depends on how your files work (if you can identify reliably whose move is next, only allow uploads with that corresponding name) On upload, store the file in a known location, ideally a folder with all the other uploads. I recommend numbering them and naming them, e.g. "1 - Vault_Dweller.xml", "2 - Algorythmics.xml" So you can track just with the file names which is the latest and who did what when. Allow users to download all files so you can trace back any errors to their source and pick up from the last good upload if necessary.

    What I am providing is what springs to my mind as the simplest to implement solution to your problem. This is worlds, miles, 3 year full-time degree courses and several years of work experience in the industry away from the correct solution for a product released to customers. But I'm pretty sure you aren't looking for that.


  • Notification Spam Recipient

    Thanks, this is exactly what I was looking for. It is a turn-based game, so the chance of 2 people altering the XML is 0. I actually do a fair bit of SQL Server development at my work, so databases aren't foreign to me. It was just some laziness at the time which made me go with XML. I will probably convert the project to something proper on the long run, but for now I just need something that works, so that we can start proper testing



  • Note the SQLite cannot handle more than 1 concurrent user (reader or writer). This includes threads, and is by design.


  • Discourse touched me in a no-no place

    @riking said:

    Note the SQLite cannot handle more than 1 concurrent user (reader or writer). This includes threads, and is by design.

    It handles concurrent readers fine (provided you build it with the right options). It's concurrent writers that it doesn't do.



  • @dkf said:

    provided you build it with the right options

    Mhm.



  • IME, it can also handle multiple processes trying to write to a db at once (by blocking one of the processes).



  • If you are going to do something like what @algorythmics proposed then I would recommend adding something to your client to poll for "is there a new file". Mostly to help with the testing you were talking about, as very small armies is probably how people should start testing a Warhammer thingy which leads to short turns (at least compared to proper games of it).


  • Discourse touched me in a no-no place

    @tar said:

    IME, it can also handle multiple processes trying to write to a db at once (by blocking one of the processes).

    If you count that as “handle” then yes, it handles as many writers as you can practically put on the machine. 😃



  • @dkf said:

    count that as “handle” then yes

    I considered quotation marks around "handle". :<lol>D

    In the context of someone who doesn't really want to faff with a 'proper' database, it's going to do the 'right thing' (i.e. not corrupt your data) in most use cases, I would expect...

    Also it's probably easier to migrate to a proper db later...


  • Notification Spam Recipient

    Thanks, I will consider this. Just to be clear, this is for a campaign system, i.e. battles that initiate on the system are still resolved on the tabletop, and the result is given the to program afterwards.


  • Notification Spam Recipient

    Ok, so, this is one of those cases that make you go "WTH was I thinking?". In hindsight, I should have known the only long-term solution is to use a db.

    So, at the moment I am thinking of doing the following:

    • Host the database centrally (I will most likely use SQL Server Express)
    • The application will run on a client machine that connects to the centrally-hosted db.

    Before I start with the conversion process, however, my questions are as follows:

    • What is the best approach for clients to connect to the database over the internet? At the moment the only thing I can think of is using a VPN. Any better ideas? This is a pet project, so I am not looking at any paid hosting options for now, except if they are dirt cheap.
    • Will it be possible to manage the db structure in git? If so, how?
    • Is there a better way to do this than what I am proposing? Before answering, keep in mind that, again, this is a pet project, and this is the first time in about a year and a half I have time to work on it again

    If anyone is interested, the project is on github (finally).



  • @Vault_Dweller You don't let the clients connect directly to the db. You should create an API through e.g. REST which maps the actions of your clients to the commands executed on the db.


  • Banned

    @Vault_Dweller said in Converting to "the cloud":

    What is the best approach for clients to connect to the database over the internet? At the moment the only thing I can think of is using a VPN. Any better ideas? This is a pet project, so I am not looking at any paid hosting options for now, except if they are dirt cheap.

    noip.com or some similar service. My bro had a CS server a few years ago and it worked rather good.

    @Rhywden said in Converting to "the cloud":

    You don't let the clients connect directly to the db. You should create an API through e.g. REST which maps the actions of your clients to the commands executed on the db.

    +1. Though it might be overkill if you personally know all potential users and data at stake isn't very important.



  • @Vault_Dweller actually, you can let the users connect directly to a db. it's just not recommended because of IT security.

    But it can be worth the risk if you don't have important data there, to avoid writing a web service over it. you should do backups of it anyway


  • Discourse touched me in a no-no place

    @fbmac said in Converting to "the cloud":

    it's just not recommended because of IT security.

    It's also not recommended because it makes all the applications actually dependent on the DB schema; updates to anything will end up giving lots of developers stomach ulcers.



  • @dkf I heard this before, and it's bullshit. If you put a middleman like a rest web service, almost any change in the schema will end being repeated in the web service and affecting the client in the same way.

    It only made things worse every fucking time I see this sort of bullshit applied.




  • Discourse touched me in a no-no place

    @fbmac said in Converting to "the cloud":

    almost any change in the schema will end being repeated in the web service

    That depends what the change is.



  • @Vault_Dweller said in Converting to "the cloudbutt":

    What I want to do:
    Make it proper multiplayer, i.e. you login with a client, and it connects to a server. My "quickfix" idea is to host all of the XML files "in the cloudbutt", and when you login, it loads these files instead of locally hosted files (Think Dropbox). My ideal solution would actually be some type of MVC, and if I had the time I would do that, but it would involve a lot of rewriting which I find a bit daunting at the moment.

    FTFY.

    I think the other replies have steered you in the right direction, though. The server manages the data somehow (DB, XML file, whatever) and presents the players with forms that let them submit their moves when it is their turn and are rejected if, due to caching or malice, they are submitted when it is not their turn. Only the server actually modifies the data after verifying that the submission is valid.

    If you expect players to sometimes play in real time, you might also put in something that polls the server for updates periodically when it is not their turn, so they will know when it is their turn.



  • This post is deleted!


  • @fbmac said in Converting to "the cloud":

    @dkf I heard this before, and it's bullshit. If you put a middleman like a rest web service, almost any change in the schema will end being repeated in the web service and affecting the client in the same way.

    It only made things worse every fucking time I see this sort of bullshit applied.

    How about, if the web service doesn't have the entire scheme internalized?

    I am now working on my first web service, and its main purpose is that it should display something like 100 obligatory properties of geographical objects. So my design is now, that the web service simply takes any result row from select * (on a view rather than a table if necessary) and encodes it as a GeoJSON object. The only intelligence it needs to have this way, is to extract an id and the location. For the rest it can use introspection pass on all other columns unprocessed.



  • @Grunnen said in Converting to "the cloud":

    How about, if the web service doesn't have the entire scheme internalized?

    you may hit one of the rare cases when your webservice really does some abstraction and make sense.

    but 90% of times I see people doing it or any type of layer is just a silly repeat of the previous layer and actually increase the cost of maintenance

    that's the whole abstraction vs indirection thing zed shaw explained in his rant I have posted earlier



  • @fbmac however if your ws just has a few less attributes than the db it's still not worth it.


  • Banned

    @fbmac said in Converting to "the cloud":

    @dkf I heard this before, and it's bullshit. If you put a middleman like a rest web service, almost any change in the schema will end being repeated in the web service and affecting the client in the same way.

    To be fair, I actually don't know shit about backend programming, but if you put this middleman in your process, you should be able to modify DB schema without modifying API and the client. Like, you can handle both the newest version and some very old one on the same server, operating on the same data. With direct DB access, it would be pretty much impossible.


  • :belt_onion:

    @dkf said in Converting to "the cloud":

    @fbmac said in Converting to "the cloud":

    almost any change in the schema will end being repeated in the web service

    That depends what the change is.

    And on how well designed the API is. If it's a logical API, you needn't change the API endpoints at all (unless you're adding something, which is a 🐄 point because you're adding code anyways)



  • @fbmac before I read it, is it intelligent and useful? I only ask because Zed Shaw is... infamous around here for his opinions.



  • @Arantor I liked that post when I read it, but it was a long time ago. It's good in my memory.


  • Grade A Premium Asshole

    @Arantor said in Converting to "the cloud":

    @fbmac before I read it, is it intelligent and useful? I only ask because Zed Shaw is... infamous around here for his opinions.

    Yeah...he has always reminded me of someone. Can't quite name who....


  • Grade A Premium Asshole

    @fbmac said in Converting to "the cloud":

    It's good in my memory.

    Ex-girlfriends are similar in that respect. But of you dig deep enough, you can remember how cunty they are.



  • @Arantor
    I skimmed it and from what I've seen, the answers are no and no.

    Also, why is he talking about Java's abstract keyword when he clearly has no idea how it's used?

    But, when you implement an “abstract” Java class you must implement the same number of functions including the abstract functions just to get it work.

    Err, no, I must implement all the methods that are marked as abstract. If that's the same as the number of methods in the abstract class, the person who created it should have created a Java interface instead.

    Java just gave a keyword to something you could already do in C++ simply by defining a virtual function in a class in its .h / .hpp file and not defining it in the class's .cpp file.

    Edit: Also, how long ago was this article written? He's linking to Sun's site, which has been defunct for the better part of a decade. Not to mention it references the version of EJB pre-2005.


  • Notification Spam Recipient

    I see your points about the API, and it is something I will put on my long-term to-do list. However, I'm not worried about it for now, as security is not an issue (it will be hosted on my own PC with only the 1 db), and I am the only developer.


  • Discourse touched me in a no-no place

    @powerlord said in Converting to "the cloud":

    Java just gave a keyword to something you could already do in C++ simply by defining a virtual function in a class in its .h / .hpp file and not defining it in the class's .cpp file.

    Strictly, it's a pure virtual method.


  • Banned

    @powerlord said in Converting to "the cloud":

    Java just gave a keyword to something you could already do in C++ simply by defining a virtual function in a class in its .h / .hpp file and not defining it in the class's .cpp filewith = 0 at the end.

    FTFY. Virtual method without definition isn't the same as pure virtual method.


  • Banned

    @powerlord said in Converting to "the cloud":

    Edit: Also, how long ago was this article written? He's linking to Sun's site, which has been defunct for the better part of a decade. Not to mention it references the version of EJB pre-2005.

    Earliest reference I can find is Internet Archive entry from November 17, 2006. So it's at least this old. The date that Google puts next to the article is November 2, 2004, but I'm not sure how credible this date is.


  • Discourse touched me in a no-no place

    @Gąska said in Converting to "the cloud":

    Virtual method without definition isn't the same as pure virtual method.

    Link failures are not (necessarily) errors. But sometimes they ought to be anyway. ;)


  • kills Dumbledore

    @Polygeekery said in Converting to "the cloud":

    But of you dig deep enough, you can remember how cunty they are

    if an ex girlfriend isn't cunty, you need the Guacamole thread


  • Banned

    @dkf said in Converting to "the cloud":

    Link failures are not (necessarily) errors.

    I never said they are. Also, lack of definition doesn't always lead to link failures.



  • @Gąska I probably should mention I only rarely use C++.


  • Banned

    @powerlord in your defence, the syntax for pure virtual functions in C++ is batshit insane.


  • Discourse touched me in a no-no place

    @Gąska said in Converting to "the cloud":

    the syntax for pure virtual functions in C++ is batshit insane

    It reminds me of the crazy crap in Modula 3.


  • ♿ (Parody)

    @Gąska said in Converting to "the cloud":

    @powerlord in your defence, the syntax for pure virtual functions in C++ is batshit insane.

    How so?


  • Banned

    @boomzilla in your opinion, to an untrained eye, what would look more like a pure virtual method: virtual void something() which is being assigned the value of zero, or pure virtual void something()? Also, can I assign to a method anything else besides zero? Why?


  • ♿ (Parody)

    @Gąska I agree that putting pure in there would be clearer. OTOH, the = 0 makes sense, too, since you're putting that into the vtable. I dunno, doesn't rise to my standard for batshit insane I guess.



  • @Gąska said in Converting to "the cloud":

    @boomzilla in your opinion, to an untrained eye, what would look more like a pure virtual method: virtual void something() which is being assigned the value of zero, or pure virtual void something()? Also, can I assign to a method anything else besides zero? Why?

    Freedom of expression!!!!


  • Banned

    @boomzilla said in Converting to "the cloud":

    OTOH, the = 0 makes sense, too, since you're putting that into the vtable.

    • Vtable is compiler's implementation detail.
    • When you mark virtual function with = 0, you don't put zero in vtable, but a pointer to a function wrapping abort(). But that's compiler's implementation detail.
    • C++ standard doesn't ever mention vtable. You cannot use the vtable argument without breaking the abstraction that C++ standard provides.
    • = 0 isn't assignment - if it was, it would allow other values than 0. It kinda, sorta does in C++11, but = default is used in different context, and = delete has even less to do with assignment than = 0. It's a hardcoded string of two random tokens that really should be one token, specialized for this one use.

Log in to reply