Game Maker Community YoYo Games

Welcome Guest ( Log In | Register )

 
Reply to this topicStart new topic
Sabriath's Multiplayer 39dll Scripts, Need I say more? version 2.0 is out
sabriath
post Oct 11 2009, 11:46 AM
Post #1


12013
Group Icon

Group: GMC Member
Posts: 1165
Joined: 23-July 09
From: Delaware
Member No.: 136924



Version 2.0
download here

Changes:

db_entry_new(ID, name, password, data)
Still uses password as plaintext entry, but creates 13 md5 hashes in sequence and stores it along with the data for fast reading (see authentication update)

db_entry_get_md5(ID, name)
No longer part of the main functions, placed in 'internal' grouping and renamed _db_entry_get_md5. It also has an extra argument, but this function shouldn't be used directly.

mp_id_me(player ID)
maps the "player ID" to a -2 token, it is used to determine server instance IDs to client objects

mp_id_new(player ID, object)
creates the object and maps the 'player ID' to it

mp_id_translate(player ID)
returns the object that 'player ID' is mapped to. -1 if none and -2 if self

mp_id_remove(player ID)
removes the 'player ID' mapping.

readstring/writestring
No longer accepts strings bigger than 65535, writes a 2 byte size marker in front of the string. This is similar to how the readsecret/writesecret works, but doesn't encrypt the string.

mp_key_increase_write()
mp_key_increase_read()
Collaboration sequence that will extend the encryption key. Either server or client can initiate this sequence with the *_write() script, the other must subsequently *_read() it. There is no failsafe for a nonencrypted login.


Authentication Change:

Client sends Name plaintext

Server checks database for the md5 hash, sends a random CypherA^md5. It uses a position in the CypherA modded with 13 to determine a md5 recursion to use as a check.

Client takes the message and xors it with the md5 of the password to get CypherA. It also finds the modded recursion factor and takes the Nth md5 hash ^CypherA and sends it back to Server.

Server checks for equality, sends 10 if good, 1 otherwise.

I have determined there is NO way to protect against all attacks, so I took the lesser of two evils and kept the secret key safe. An eavesdropper can take the 2 data points and come up with CypherA^md5[0] and CypherA^md5[x]. They can then xor those to get md5[0]^md5[x]. This allows them a 7.6% chance of logging in by xoring this sequence with anything the server spits back, since there are 13 hashes modded for equality checking. This can further be secured by blocking an IP address on 3 failed attempts, but I am leaving this open for others...I didn't want to create more hashes because it will saccrifice 1 byte of the secret key to have more possibility of being broken. CypherA is used for the encryption, as well as used to increase the key. Any string that is easily decryptable using simple cryptex will cause the entire scheme to unravel and the account is lost, so secret strings should be used sparingly in the game.


Version 1.0 here

Do not be overwhelmed, there are a lot of functions but I separated them the best that I could to help guide you in learning. I first wrote a 39dll action lib awhile ago, decided that it is vastly superior to just write the scripts instead...I'll get around to doing the action lib update another time. This was created on my break from my compiler for GM, spending too much time in one thing is exhaustive.

Anyway, you will need the 39dll.dll file, please check my signature for links to my tutorials as well as Tv's tutorials. You can find the 39dll.dll file here. My file contains the basic scripts so you will not need to import 39ster's dllscripts file, his scripts are located in the "direct" subgrouping, and should not be called unless you know the inner workings of the other scripts. I will not go over 39ster's functions (my second tutorial explains that stuff anyway), so I will just explain the extras in small detail until I can get another tutorial going. Before I start, I must say that I replaced a few of 39ster's originals with my own, "md5string" returns a 16 byte string return in ascii instead of 32 byte hex, the read/write functions have been renamed to dread/dwrite. Now onto the good stuff:

We will start with the "database" grouping
db_create()
This will create a database in memory and return the ID required for other db_* scripts.

db_load(filename)
This will create the database in memory based on the image stored in the file. Just like db_create, it will return the ID required for other db_* scripts. Returns -1 for file error

db_save(ID, filename)
This will save the current database to the file, retaining the database in memory. It returns -1 for file error.

db_close(ID)
Frees memory of the database.

db_entry_new(ID, name, password, data)
Creates an entry inside the database, it will store the md5 of the password, so supply it with the actual password. I just realized I shouldn't have done it, and will need to change that, but for now that's what it does. It also stores the data you supply (string) under that same name, since a server does not require a password to see data, neither does this. This will return 0 if the name already exists in the database.

db_entry_get_md5(ID, name)
This will retrieve the 16 byte md5 hash of password from the entry, if no entry was found, it returns an empty string.

db_entry_get_rest(ID, name)
Probably should rename it to data instead. This returns the data string you entered with db_entry_new. It returns an empty string if name was not found.

There is no current functions to delete entries or replace parts of them, I will have to do that later. I only did a basic database so that I could write the authentication sequences in the multiplayer step. So, now for the "multiplayer" grouping:
mp_init(filename)
This will initialize the 39dll.dll file along with all global variables required to run all scripts provided. You should call this only 1 time at the very beginning of your game, however there is a safeguard just in case you accidently call it more than once. The "filename" is the name of the dll file, it should be "39dll.dll" but 39ster allowed players to be able to rename the dll if they choose to, so if you do, you'll have to change it here too.

mp_free()
This will free the 39dll.dll. You should call this last, before the game ends. THERE IS NO SAFEGUARD! I will update this function later.

The server and client scripts have been separated. For the server we have "connections" which have 2 subgroups themselves (server and player):
mp_server_create(Port, ID, object)
Opens "Port" for listening for connections. "ID" is the database ID that the server uses to authenticate players...if you make this -1, it will automatically authenticate. "object" is the object to create for authenticated players, and contains the mp_player_* functions. Returns 1 if there was a problem and should be destroyed.

mp_server_step()
This is the actual script that will authenticate the player and create objects when needed. I just noticed when looking at it that there is no check, so make sure you destroy it if there was a problem in the create event. I hate finding problems halfway through writing something, anyway, moving on.

mp_server_destroy()
Cleans up the server object when destroyed, should be in the destroy event, just like all other functions, the name pretty much tells you where to put them.

mp_player_create()
Creates the necessary buffers for communications with the player.

mp_player_step()
This will process any outgoing data that needs to be sent, as well as buffer the incoming data. It stores the amount of data read in "bufferleft" so that you can use it for your checks. This will return a 1 if there was a problem, and you should exit your code if there was....instance will be destroyed automatically at the end of your code.

mp_player_destroy()
Do I need to explain this?

mp_player_sendmessage(Instance)
This will buffer the data to the instance of the player object. It will automatically clear the buffer afterward. If you want to send to multiple people, use the group scripts.


The "groups" scripts are used to send the same data to multiple people based on a specific similarity. For example, you could have 2 "areas" on a map, you can make a group called "Area" and give it 2 subgroups, then any player in the first subgroup will only see those in the first map, and the second group will see only those in the second group. This can also work for chat rooms, for example World of Warcraft has 2 Trade channels, 1 for horde and 1 for alliance, this is also a grouping called "Trade" with 2 subgroups. No player can be in more than 1 subgroup of the same group class, although they can be in multiple groups...so a person can be in "Area" 0, "Trade" 1, and "Guild" 4822, but that same person cannot be in "Guild" 2910. However, there are scripts that will set a player (which automatically degroups them of that group type), so in essence "moving" them from 1 subgroup to another.
mp_group_add(Name, Subgroups)
Creates a group with a given name and given number of subgroups. Returns 1 if 'Name' already exists, 0 otherwise.

mp_group_find(Name)
Returns the position in an array that points to that specific group, it is used for the other functions and really doesn't do you any good, although if it doesn't return a -1, then you know it exists.

mp_group_player_add(Name, Subgroup)
Locates the group (returns -4 if not found), and the subgroup (returns -3 if out of bounds). Checks if player is already in it (returns -2 if already in that subgroup), puts player in that subgroup (returns -1 if joining for first time), and removes him from his old subgroup if he was in that group (returns the subgroup number that player was in last)

mp_group_player_remove(Name)
Doesn't matter what subgroup player is in, just removes him from it entirely. Returns -2 if 'Name' doesn't exist, -1 if not in 'Name' at all, or the subgroup number he was in.

mp_group_sendmessage(Name, Subgroup)
Will buffer the current data to every player in that specific group/subgroup. It clears the buffer after it is done. Returns -2 if 'Name' does not exist, or -1 if out of bounds, otherwise it returns the number of players actually got sent the data.

The client scripts also have 2 different types, the first is for authentication purposes and automatically destroys itself and transfers all pertinent data to the second object. This is so that the first object can clear any trash left over from the process and leave the client with a little bit less processing.
mp_login_create(IP, Port, Name, Password, object)
Will request a connection to the specified IP/Port, and attempt to authenticate with Name and Password. It will automatically md5 the password (see below how authentication works for details on security), so just give it the direct password. "object" is created when authentication is complete (the object should contain the mp_client* scripts). If you leave 'Name' as an empty string, then it will assume the server does not authenticate and just do the request connection sequence create the object. This returns 1 if there was a problem and should be destroyed if so.

mp_login_step()
This is to process the authentication sequence communication. If it returns anything other than 0, there was a problem (2 means denied access...bad pass/name) it should be destroyed if it's not 0.

mp_login_destroy()
Really?

mp_client_create()
Yep...initialization

mp_client_step()
This will buffer in any communication the server has sent, "bufferleft" can be used to determine the size of the data left to read. The script itself returns 1 if your step code should be skipped or possibly destroyed altogether

mp_client_destroy()
And last one for de-initialization sequence

mp_client_sendmessage()
Since a client has no other person they are talking to, any data has only 1 direction, this script sends the current data to the server. This script will clear the buffer when it is done.

The messages are controlled by the read*/write* functions (not the ones 39ster provided, but my own creations). All of the read* scripts will read directly from the inward buffer of that particular object, and it will automatically subtract from "bufferleft" the amount of data read. So a good "while (bufferleft > 0){}" statement after the "_step()" scripts will do just fine. The buffer is destroyed in the "_step()" script, so make sure you read in all the data before the next step...this is a crude failsafe (just in case there is garbage in the data, it removes it before reading the next stream).

All write* scripts will write to the default buffer, I have found this more effective then creating a bunch of buffers, usually you write stuff because you are about to send it, so there is no need to write directly to a secondary buffer. For example:

CODE
writebyte(4);
writestring("hello");
writebyte(10);
mp_player_sendmessage(self.id);


Since all the "*_sendmessage" scripts automatically clear the default buffer afterward, it is good to write all your data and immediately call one of the 'send' scripts and move on. All data is sent as-is, no encryption.

However, there are 2 scripts that may look new to you. "readsecret()" and "writesecret()". These 2 scripts use the currently agreed encryption scheme between you and the connected person to create an encrypted string (see below for authentication sequence for more info). They automatically send a 2 byte length (unencrypted) value in front of the string (so the max length is 65535), and then send the string directly afterward, this allows you not to have to worry about people cracking your stuff (since lengths can be cracked easily, I pulled them out of the encryption phase). The functions are used like this:

CODE
writesecret("hello");  //sent from one end

a = readsecret();  //read on the other end

//a == "hello"


That simple.

Ok, now onto how I authenticate people (since this involves an seemingly unbreakable scheme, I'll share it publicly to see if anyone can beat it). This type of authentication I have searched EVERYWHERE on the internet and have not found 1 place that uses it. If you use it, please give credit and possibly money if it works, I'm poor. Ok, nuff begging smile.gif Here it is:

Server already knows the 16 byte md5 hash of your password (ssl is great to set up passwords using a webserver, similar to how wow does account building). This hash is considered a private key....only the server knows the hash, and the hash can only be created if the person knows the password.

The client upon connection will create a 16 byte RANDOM cypher. This is called CypherA. It takes the password the player provides and md5 hashes it, and stores this as PassCypher. With these 2 16 byte strings, it encrypts it using an xor method. It sends this 16 bytes along with the name to the server. This is known as 'CypherA^Pass+Name'

(Hackers/Man-in-the-middle see 'Trash1+Name')

The server checks the database for the player and gets the md5 hash from the database, it then performs the xor encryption on the data to retrieve the CypherA (because CypherA^Pass^Pass = CypherA). It creates 2 random cyphers known as CypherB and CypherC. It encrypts CypherB with the md5, creating 'CypherB^Pass' and sends it.

(Hackers/MITM see 'Trash2', since Trash1^Trash2 = CypherA^CypherB, there's no telling the Password nor the keys individually)

The client then decrypts using the xor function from the pass to retrieve CypherB (CypherB^Pass^Pass = CypherB). Now to determine if server/client are actually communicating the proper Password, we will do a cypher swap. One last cypher is created randomly called CypherD. Client sends CypherA^CypherD to server.

Server takes that and retrieves CypherD by xoring CypherA, then sends CypherD^CypherB along with CypherC^CypherA for the server to check against the client.

Client takes that and decrypts the server's interpretation of CypherD by xoring CypherB out....if they are equal, server has the correct keyset. It then determines CypherC by xoring CypherA out, then sends the server CypherC^CypherB. It creates the 64 byte encryption scheme of CypherA+CypherB+CypherC+CypherD for *secret scripts.

Server takes the data and takes the client's interpretation of CypherC by xoring CypherB out....if they are equal, client has the correct keyset. It creates the 64 byte encryption scheme of CypherA+CypherB+CypherC+CypherD for *secret scripts.

If the client gives the wrong password, then they will not know until the cypher exchanges, at which point the server will drop the client, and the client will report it. You can xor any data that could possibly be retrieved midstream all you want, you'll always end up with 2 patterns xored together, and no way to cancel out (as far as I can tell). 64 bytes may seem small, but keyswapping can easily scale this higher and higher.

Let me know what you think....ideas....whether or not you can break my scheme, anything. For now I'm off to bed.

This post has been edited by sabriath: Oct 16 2009, 11:11 AM
Go to the top of the page
 
+Quote Post
sabriath
post Oct 13 2009, 08:44 AM
Post #2


12013
Group Icon

Group: GMC Member
Posts: 1165
Joined: 23-July 09
From: Delaware
Member No.: 136924



[My legal bump]

Found out that my encryption scheme, although it works at keeping people from seeing what you write, is flawed. I came up with a scheme to check if my encryption is truly uncrackable and drew out a table, turns out that a person can fakely log in without knowing the password of anyone....although any secret messages would be jibberish without the proper password, it doesn't stop them from logging in:

Bogus can send server a 16 byte string X with a person's log in (This was suppose to be CypherA^md5)

Server will send back a 16 byte string with CypherB^md5

Bogus will then send server a 16 byte string Y (This was suppose to be CypherA^CypherD)

Server will send back Y^CypherA^CypherB along with CypherC^CypherA

Although Bogus does not know Any of the cyphers at all, the server is waiting for CypherC^CypherB, Bogus can create that string by doing (CypherC^CypherA)^(Y^CypherA^CypherB) which was received from the last transmission and results in CypherC^Y^CypherB, in order to get rid of Y, we just use the previous transmission we sent by (CypherC^Y^CypherB)^(Y) and we get CypherC^CypherB. Bogus has now succesfully infiltrated someone's account. Like I said, any "secret" stuff will not work because Bogus NEVER knows what md5 of the password is, so cannot recreate all the keys specifically.

I'm going to have to redo it, but on the same principles. Possibly use half the key for a keyswap instead of the key for a signature.

Please do not use these scripts for secure access, but any further feedback is welcome, thanks!
Go to the top of the page
 
+Quote Post
sabriath
post Oct 15 2009, 12:27 PM
Post #3


12013
Group Icon

Group: GMC Member
Posts: 1165
Joined: 23-July 09
From: Delaware
Member No.: 136924



[Another legal bump]

I think I may have solved the access issue. At first I was thinking of implimenting my shotgun encryption method (where it inserts the md5 hash in a nesting fashion expanding a random bitstream), but this method takes too long to process in GML. I was in the process of creating it when it hit me like a ton of bricks this morning. Still a bit groggy, but here it goes:

Client sends name in plaintext to server upon connecting. You can come up with all the encryption possibilities you want, but something has to be plaintext in order to verify information.

Server creates a 16 byte random cypher that is XORed with the md5 hash stored in the database and sends this. It is known as CypherA^Password (although the true password isn't used, it stands for the 16 byte md5 hash that is produced when the proper password is given). The server is sending a test out to verify toward the client.

Client only has the trash info of CypherA^Password, and any eavesdropper only knows it plus the plaintext name. The server is waiting for an answer, and this is what hit me. If the player enters the proper password, he can use the md5 hash xoring and leaving CypherA....can't quite just send that though, but...md5 the hash AGAIN and xor it with the cypher and you get a reply that is secure. This is known as CypherA^md5(Password) (remember, password was already a 16 byte hash, so md5() is yet another run of the one way hash function).

Server knows the proper md5, so hashing it will yield the md5(Password) required to verify CypherA response is in equality. Login successful or failed at this point. It also stands that CypherA has complete secrecy, so can be used to build a keyswapping to increase the encryption size.

Any disagreements, let me know. (Even though I haven't gotten a reply anyway, any is appreciated). I'm tired at the moment, I will have to work on the update after sleep.
Go to the top of the page
 
+Quote Post
Frederick
post Oct 15 2009, 10:11 PM
Post #4


GMS Owner
Group Icon

Group: GMC Member
Posts: 326
Joined: 24-July 09
Member No.: 136972



This is very useful. Thanks for taking the time to write all this! smile.gif
Go to the top of the page
 
+Quote Post
sabriath
post Oct 16 2009, 11:12 AM
Post #5


12013
Group Icon

Group: GMC Member
Posts: 1165
Joined: 23-July 09
From: Delaware
Member No.: 136924



Version 2.0 is out now, maybe I'll get some replies, maybe not. I'll write up a simple TDS thing for the game.
Go to the top of the page
 
+Quote Post
T-Bird
post Oct 17 2009, 08:36 AM
Post #6


GMC Member
Group Icon

Group: GMC Member
Posts: 1288
Joined: 5-November 05
Member No.: 38296



I haven't looked at the scripts, but if that encryption you are talking about is just for logging in/out then you don't really need something so elaborate. There isn't much of a reason for a host to have access to plaintext passwords is there? So the client can simply have their password hashed when the account is created and the hash can be stored in the DB. To verify login, hash the password the user supplies and compare that to the DB's hash.
Go to the top of the page
 
+Quote Post
sabriath
post Oct 17 2009, 08:55 AM
Post #7


12013
Group Icon

Group: GMC Member
Posts: 1165
Joined: 23-July 09
From: Delaware
Member No.: 136924



QUOTE (T-Bird @ Oct 17 2009, 04:36 AM) *
I haven't looked at the scripts, but if that encryption you are talking about is just for logging in/out then you don't really need something so elaborate. There isn't much of a reason for a host to have access to plaintext passwords is there? So the client can simply have their password hashed when the account is created and the hash can be stored in the DB. To verify login, hash the password the user supplies and compare that to the DB's hash.

*shakes head*

Ok, not sure if you know this or not, but there are ways to "eavesdrop" on communications. So, let's say that all you needed was a hash of the password to login:

John puts in his name and password, which is "john" and his password is "2380sje" for example. Let's have the host hash this password with a well known operation that creates a 16 byte md5 hash. We will call this "md5password" because I can't show a proper ascii of it in the forums. Now, john's computer sends "john:md5password" to the server.
Earl is eavesdropping the server's communications....he sees "john:md5password" come through, yay for Earl. Earl waits for john to disconnect, then he sends "john:md5password" to the server, and looky, he logs into John's account.

The encryption isn't just about logging in, it also sets up a secure communication similar to SSL for encrypting any data after login, and it's a random cypher each login so making it harder to crack each time.

However, as I mentioned in the original post, there are 14 hashes of the password stored in the database. When John puts in his name and password, the client program sends "john" to the server, while it waits for a communication, it calculates this:

CODE
hashes[0] = md5string(password)
for (i = 1; i < 14; i += 1)
    hashes[i] = md5string(hashes[i-1])


The server creates a random cypher and xors this cypher with the first hash of the password. When the client receives this, they can xor the hash to get the cypher. The client also takes the 5th byte in the cypher and mods it with 13 to figure out which of the 13 additional hashes are the check, it xors the cypher with it and resends it.

Earl the eavesdropper sees "john" sent from John's computer, then sees a 16 byte unknown from the server, then sees another 16 byte unknown from the client. With those points of information, there's only a 7% chance that Earl will be able to login, unlike the previous setup where it's a 100% chance. And there's no way that Earl can get the cypher.

However, registering for an account there is no way to protect anonymous computers, the D-H method comes very close, but it's an expensive method to use for GM. I suggest using https over ssl to do registering, a webserver can easily communicate behind a firewall into the database (which these scripts come with the ability to save/load database). The method I use is only AFTER the registration is complete, changing passwords still can be done with my scripts.
Go to the top of the page
 
+Quote Post
lap202
post Oct 17 2009, 07:43 PM
Post #8


GMC Member
Group Icon

Group: GMC Member
Posts: 31
Joined: 19-April 09
Member No.: 131990



Could you possibly create a tutorial on how to edit these/set this all up?
Go to the top of the page
 
+Quote Post
StarTrek
post Oct 17 2009, 07:52 PM
Post #9


Yesterdays games
Group Icon

Group: GMC Member
Posts: 614
Joined: 7-December 08
From: Sweden
Member No.: 124474



This is really good! To bad you haven't got the attention you deserve sad.gif
I'm not really into making an online game right now, but I'm putting this on my mind for sure.
Go to the top of the page
 
+Quote Post
sabriath
post Oct 17 2009, 08:05 PM
Post #10


12013
Group Icon

Group: GMC Member
Posts: 1165
Joined: 23-July 09
From: Delaware
Member No.: 136924



QUOTE (lap202 @ Oct 17 2009, 03:43 PM) *
Could you possibly create a tutorial on how to edit these/set this all up?

The file comes with a small example, download it and the 39dll.dll and you can run it out-of-the-box. The object's code is extremely small and should be understandable to any advanced user. I was busy fixing the authentication sequence so I didn't have time to make another example, since it's done, I'll work on that next along with my third tutorial.
Go to the top of the page
 
+Quote Post
T-Bird
post Oct 17 2009, 08:43 PM
Post #11


GMC Member
Group Icon

Group: GMC Member
Posts: 1288
Joined: 5-November 05
Member No.: 38296



Eh. I appreciate what you're trying to do, but I don't see that as a necessary step. The only time I can see that harsh of an encryption really being necessary is if vital personal info is being stored on the server (this is always a no-no), or there is a money transaction.

GM has so many insecurities in general, I personally would never trust a GM-made server with a money transfer. So that takes me back to using Apache/PHP with SSL.

In the case someone does packet-sniff a simple hashword then if the webmaster does a little logging of their user's account data and access information, the users account can be restored with minor inconvenience.

That's just my two cents. I can appreciate, however, that you're trying to create a professional-quality system, just seems a little like overkill to me.

Soon I'll download the scripts and actually look at them, I like the description of what you made, I'll have to check it out.
Go to the top of the page
 
+Quote Post
sabriath
post Oct 18 2009, 07:13 AM
Post #12


12013
Group Icon

Group: GMC Member
Posts: 1165
Joined: 23-July 09
From: Delaware
Member No.: 136924



QUOTE (T-Bird @ Oct 17 2009, 04:43 PM) *
Eh. I appreciate what you're trying to do, but I don't see that as a necessary step. The only time I can see that harsh of an encryption really being necessary is if vital personal info is being stored on the server (this is always a no-no), or there is a money transaction.

GM has so many insecurities in general, I personally would never trust a GM-made server with a money transfer. So that takes me back to using Apache/PHP with SSL.

In the case someone does packet-sniff a simple hashword then if the webmaster does a little logging of their user's account data and access information, the users account can be restored with minor inconvenience.

That's just my two cents. I can appreciate, however, that you're trying to create a professional-quality system, just seems a little like overkill to me.

Soon I'll download the scripts and actually look at them, I like the description of what you made, I'll have to check it out.

I acknowledge what you are saying, but it isn't about being professional, it is more on the fact that I don't know what people will make with it. I added it just in case, it shows some of my abilities for data manipulation. Although games like World of Warcraft may not have a "money transfer" ability, people on those types of games almost require some security measures. They use up years of their life to build up something great, they don't want to lose that to some hacker (although contacting staff will allow a rollback, if we can eliminate as much hacking ability as possible, this won't happen on a regular basis). There are even some people that use these types of games to make money on, which is like a transfer, but not directly....so security is a concern for them as well.

Like I said, I don't personally know what people will use it for, I did it because I could do it. I hope to build a good portfolio and get out of my dump of a job, move up into some programming status (I know GM isn't professional, but I have other projects outside of GM as well).

It's not quite "overkill"...it only took me a week to design it and an hour to program it, you should've seen the first scheme I came up with, ug, nightmare. This one is much faster and more secure, funny that simplicity overruled complex in this case. I'm glad you appreciate my work, and I appreciate you giving me your two cents, keep them coming so I can fix any issues. I look forward to your response.
Go to the top of the page
 
+Quote Post
True Valhalla
post Nov 7 2009, 10:17 AM
Post #13


Everybody Winnar!
Group Icon

Group: GMC Member
Posts: 1302
Joined: 1-July 08
From: ~~~~~~~~~~ Posts: 8254
Member No.: 109981



Sorry it's taken me so long to get around to responding to this, Sabriath.

Overall, the scripts were quite impressive. Obviously the data encryption was the most significant feature, and while I too don't have a use for it, it is very impressive, and would look great in a portfolio.

I still feel nubs would struggle to understand how to order these scripts, so these, in my opinion, are better for reference, or for compiling small sections of a game. Once again, love the coding style =)

Great work. Can't wait to see what you have in store for us next!

-Tv
Go to the top of the page
 
+Quote Post
Universal_X
post Nov 7 2009, 10:29 AM
Post #14


GMC Member
Group Icon

Group: GMC Member
Posts: 55
Joined: 7-July 09
From: Finland
Member No.: 136126



Amazing!

Is this an Online Engine?
Go to the top of the page
 
+Quote Post
sabriath
post Nov 7 2009, 07:29 PM
Post #15


12013
Group Icon

Group: GMC Member
Posts: 1165
Joined: 23-July 09
From: Delaware
Member No.: 136924



QUOTE (Universal_X @ Nov 7 2009, 05:29 AM) *
Amazing!

Is this an Online Engine?

I am currently helping a friend with his game, when I am finished, I will be updating this into an engine. It isn't quite there yet.
Go to the top of the page
 
+Quote Post
Universal_X
post Nov 12 2009, 09:54 PM
Post #16


GMC Member
Group Icon

Group: GMC Member
Posts: 55
Joined: 7-July 09
From: Finland
Member No.: 136126



QUOTE (sabriath @ Nov 7 2009, 09:29 PM) *
QUOTE (Universal_X @ Nov 7 2009, 05:29 AM) *
Amazing!

Is this an Online Engine?

I am currently helping a friend with his game, when I am finished, I will be updating this into an engine. It isn't quite there yet.


Okey. Yep I can see it now.. Nice scripts thou..
Go to the top of the page
 
+Quote Post
cori5555
post Today, 05:50 AM
Post #17


GMC Member
Group Icon

Group: GMC Member
Posts: 188
Joined: 2-May 09
Member No.: 132673



Hey, i thought i should inform you of this, but i think you need to get a new file host, i went to WHHF and got this message...

QUOTE (www.willhostforfood.com @ Nov 20 2009)
Sorry guys, the gig is up. As I am in physics I receiced an email saying WHFFs files were deleted, and i am bring kicked ofd my host. WHFF most likely wont be able to return unless we get a substantial amount of donations. We would appreciate donations but we are not begging. If you do want to donate, we will need roughly $600-$900 dollars USD. Space and bandwith is expensive and I've serve you well, and it is all i can do anymore. I am sorry for all the broken links on the internet.

R.I.P. WHFF 2007 - November 20, 2009.


This post has been edited by cori5555: Today, 05:54 AM
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 User(s) are reading this topic (1 Guests and 0 Anonymous Users)
0 Members:

 



RSS Lo-Fi Version Time is now: 22nd November 2009 - 11:59 AM