Thread: Unnamed C# server development thread

Page 4 of 5 FirstFirst ... 2345 LastLast
Results 31 to 40 of 49
  1. #31  
    Registered Member
    Join Date
    May 2017
    Posts
    35
    Thanks given
    5
    Thanks received
    18
    Rep Power
    33
    Quote Originally Posted by Greg View Post
    Rsps in a nutshell

    The solution you've put isn't very practical, if there's 50 identical stalls you're going to have to go round one by one and get the positions and rotations. You only really need to store the id, depleted id and restore time. Locations, face & type can all be found using the server objects map.
    Yeah iterating the entire world object list isn't very practical, but for now it's faster than what was there and some bugs are fixed so I'm happy with it for now. I've had a look around the forums for the whole server objects map thing but not sure I really understand how it works. Basically if the server I'm working on doesn't currently use it I don't know about it. Something else to add to the list of things to learn about

    Quote Originally Posted by Kris View Post
    I don't see a point in storing this kind of information as you've done, you probably based it off of the old code but in reality, there aren't that many objects that replenish and handling it this way would probably even be more hassle than it should.
    E.g. some examples of where this is used are.. mining, thieving. In both scenarios it'd be cleaner storing the from/to information in the same collection where the rest of the information is held (such as xp and whatnot), especially when you consider how many special circumstances most of these things hold, having generic code to spawn this is just meh IMO. An example of a special circumstance would be mining rock replenishing based on the amount of players online (this is how it's in RS), the time isn't a constant and varies based on it. IMO it's cleaner storing it all in the same enum and having its own methods to spawn this stuff.. but ey that's just me, whatever floats your boat ;_;
    It'd be a lot easier to implement that if this source had any semblance of storing all related information in the same place, but sadly it doesn't. It's not like it would be unreasonable to store a base time and then calculate actual time based on player count. Old logic was as follows:
    • Find object base on ID and location
    • Remove that object from the list and replace it with the empty object (calculated by ID)
    • Set an event to wait X seconds (again calculated by ID) and then respawn it
    • Remove the depleted object from the list
    • Re-add original object to list


    The entire thing being such a clusterfuck right now would have meant a complete rewrite of the world object manager which is too closely tied to many other classes such as skills and therefore would also have required a rewrite (ad infinitum, at least until I've rewritten the whole thing from scratch). Having this separation of responsibility is an improvement in the long run IMO and will make it easier to make further changes down the line.

    Take the ThievingData class as it is right now for example.
    Code:
    protected static int[][] NPCS = {
    	new int[] {1, 2, 3, 7875, 7877, 7879}, // Men.
    	new int[] {4, 5, 6, 7881, 7883}, // Women.
    	new int[] {7}, // Farmer.
    	new int[] {1715}, // Female HAM members.
    	new int[] {1716}, // Male HAM members.
    	new int[] {15}, // Warrior
    	new int[] {187}, // Rogue
    	//Cave goblin here (no need for them in an RSPS..)
    	new int[] {2234}, // Master farmer.
    	new int[] {9, 32, 296, 297, 298, 299}, // Guard.
    	//'Fremmenik' here
    	new int[] {6174, 1880}, // Bandit guard.
    	new int[] {1926, 1931}, // Desert bandits.
    	new int[] {23, 26}, // Knights
    	new int[] {34}, // Watchman
    	//Menaphite thug here.
    	new int[] {20}, // Paladin
    	new int[] {66, 67, 68}, // Gnomes.
    	new int[] {21}, // Hero.
    	new int[] {2363, 2364, 2365, 2366, 2367}, // Elf
    };
    
    protected static int[] NPC_LVL = {
    	1, // Men.
    	1, // Women.
    	10, // Farmer.
    	15, // Female HAM.
    	20, // Male HAM.
    	25, // Warrior.
    	32, // Rogue.
    	38, // Master farmer.
    	40, // Guard.
    	45, // Bandit guard.
    	53, // Desert bandits.
    	55, // Knights.
    	65, // Watchman.
    	70, // Paladin.
    	75, // Gnome.
    	80, // Hero.
    	85, // Elf.
    };
    
    protected static int[][] NPC_REWARD = {
    	new int[] {995}, // Men.
    	new int[] {995}, // Women.
    	new int[] {995, 5318}, // Farmer
    	new int[] {4298, 4300, 4302, 4304, 4306, 4308, 4310, 1511, 688, 689, 687, 686, 1605, 314, 946, 995, 1267, 371, 199, 453, 444, 201, 203, 205, 175, 884, 2138, 385}, // Female H.A.M TODO - lvl 1 clue
    	new int[] {4298, 4300, 4302, 4304, 4306, 4308, 4310, 1511, 688, 689, 687, 686, 1605, 314, 946, 995, 1267, 371, 199, 453, 444, 201, 203, 205, 175, 884, 2138, 385}, // Male H.A.M TODO - lvl 1 clue
    	new int[] {995}, // Warrior
    	new int[] {995, 1523, 954, 554, 555, 556, 175}, // Rogue
    	new int[] {5318, 5319, 5320, 5321, 5322, 5323, 5324, 5305, 5306, 5307, 5308, 5309, 5310, 5311, 5096, 5097, 5098, 5099, 5100, 5101, 5102, 5103, 5104, 5105, 5106}, // Master farmer.
    	new int[] {995}, // Guard
    	new int[] {995, 175, 1523, 1823}, // Bandit guard
    	new int[] {995, 175, 1523, 1823}, // Bandits
    	new int[] {995}, // Knight
    	new int[] {995, 2309}, // Watchman
    	new int[] {995, 562}, // Paladin
    	new int[] {995, 2357, 561}, // Gnome
    	new int[] {995}, // Hero
    	new int[] {995}, // Elf
    };
    
    protected static int[][] NPC_REWARD_AMOUNT = {
    	new int[] {35}, // Men.
    	new int[] {35}, // Women.
    	new int[] {150, 1}, // Farmer
    	new int[] {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 6000, 1, 1, 1, 1, 1, 1, 1, 1, 1, 100, 1, 1}, // Female H.A.M
    	new int[] {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 6000, 1, 1, 1, 1, 1, 1, 1, 1, 1, 100, 1, 1}, // Male H.A.M
    	new int[] {300}, // Warrior
    	new int[] {500, 1, 1, 10, 10, 10, 1}, // Rogue
    	new int[] {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, // Master farmer.
    	new int[] {500}, // Guard
    	new int[] {400, 1, 1, 1}, // Bandit guard
    	new int[] {340, 1, 1, 1}, // Bandit
    	new int[] {550, 1}, // Knight
    	new int[] {600, 1}, // Watchman
    	new int[] {750, 5}, // Paladin
    	new int[] {900, 1, 2}, // Gnome
    	new int[] {1100}, // Hero
    	new int[] {1500}, // Elf
    };
    
    protected static double[] NPC_XP = {
    	8, // Men & women.
    	8, // Women.
    	14.5, // Farmer.
    	18.5, // Female HAM.
    	22.5, // Male HAM.
    	26, // Warrior.
    	35.5, // Rogue.
    	43, // Master farmer.
    	46.8, // Guard.
    	65, // Bandit guard.
    	79.4, // Desert bandit.
    	84.3, // Knights.
    	137.5, // Watchman.
    	151.75, // Paladin.
    	198.5, // Gnome.
    	275, // Hero
        353 // Elf
    };
    All of this should be stored together in SomeClass which contains IDs of NPCs, XP they give and so on. But unfortunately it's all stored separately and iterated over in its entirety. When this comes to a point where related data is stored together (and I'll probably store it on disk as well, hardcoded values in memory are meh) it'll be a lot easier to remove unnecessary information.
    Reply With Quote  
     

  2. #32  
    Registered Member
    Greg's Avatar
    Join Date
    Jun 2010
    Posts
    721
    Thanks given
    121
    Thanks received
    249
    Rep Power
    402
    Quote Originally Posted by testicles View Post
    Yeah iterating the entire world object list isn't very practical, but for now it's faster than what was there and some bugs are fixed so I'm happy with it for now. I've had a look around the forums for the whole server objects map thing but not sure I really understand how it works. Basically if the server I'm working on doesn't currently use it I don't know about it. Something else to add to the list of things to learn about
    So essentially the server should be loading map files from the cache into a clipping array used for path finding & collision, but it should also be used to verify object interactions server side. It contains id's, types, positions, rotations of every object in every region of the world.
    Reply With Quote  
     

  3. #33  
    

    Kris's Avatar
    Join Date
    Jun 2016
    Age
    20
    Posts
    3,211
    Thanks given
    489
    Thanks received
    1,720
    Rep Power
    1610
    Quote Originally Posted by testicles View Post
    Yeah iterating the entire world object list isn't very practical, but for now it's faster than what was there and some bugs are fixed so I'm happy with it for now. I've had a look around the forums for the whole server objects map thing but not sure I really understand how it works. Basically if the server I'm working on doesn't currently use it I don't know about it. Something else to add to the list of things to learn about



    It'd be a lot easier to implement that if this source had any semblance of storing all related information in the same place, but sadly it doesn't. It's not like it would be unreasonable to store a base time and then calculate actual time based on player count. Old logic was as follows:
    • Find object base on ID and location
    • Remove that object from the list and replace it with the empty object (calculated by ID)
    • Set an event to wait X seconds (again calculated by ID) and then respawn it
    • Remove the depleted object from the list
    • Re-add original object to list


    The entire thing being such a clusterfuck right now would have meant a complete rewrite of the world object manager which is too closely tied to many other classes such as skills and therefore would also have required a rewrite (ad infinitum, at least until I've rewritten the whole thing from scratch). Having this separation of responsibility is an improvement in the long run IMO and will make it easier to make further changes down the line.

    Take the ThievingData class as it is right now for example.
    Code:
    protected static int[][] NPCS = {
    	new int[] {1, 2, 3, 7875, 7877, 7879}, // Men.
    	new int[] {4, 5, 6, 7881, 7883}, // Women.
    	new int[] {7}, // Farmer.
    	new int[] {1715}, // Female HAM members.
    	new int[] {1716}, // Male HAM members.
    	new int[] {15}, // Warrior
    	new int[] {187}, // Rogue
    	//Cave goblin here (no need for them in an RSPS..)
    	new int[] {2234}, // Master farmer.
    	new int[] {9, 32, 296, 297, 298, 299}, // Guard.
    	//'Fremmenik' here
    	new int[] {6174, 1880}, // Bandit guard.
    	new int[] {1926, 1931}, // Desert bandits.
    	new int[] {23, 26}, // Knights
    	new int[] {34}, // Watchman
    	//Menaphite thug here.
    	new int[] {20}, // Paladin
    	new int[] {66, 67, 68}, // Gnomes.
    	new int[] {21}, // Hero.
    	new int[] {2363, 2364, 2365, 2366, 2367}, // Elf
    };
    
    protected static int[] NPC_LVL = {
    	1, // Men.
    	1, // Women.
    	10, // Farmer.
    	15, // Female HAM.
    	20, // Male HAM.
    	25, // Warrior.
    	32, // Rogue.
    	38, // Master farmer.
    	40, // Guard.
    	45, // Bandit guard.
    	53, // Desert bandits.
    	55, // Knights.
    	65, // Watchman.
    	70, // Paladin.
    	75, // Gnome.
    	80, // Hero.
    	85, // Elf.
    };
    
    protected static int[][] NPC_REWARD = {
    	new int[] {995}, // Men.
    	new int[] {995}, // Women.
    	new int[] {995, 5318}, // Farmer
    	new int[] {4298, 4300, 4302, 4304, 4306, 4308, 4310, 1511, 688, 689, 687, 686, 1605, 314, 946, 995, 1267, 371, 199, 453, 444, 201, 203, 205, 175, 884, 2138, 385}, // Female H.A.M TODO - lvl 1 clue
    	new int[] {4298, 4300, 4302, 4304, 4306, 4308, 4310, 1511, 688, 689, 687, 686, 1605, 314, 946, 995, 1267, 371, 199, 453, 444, 201, 203, 205, 175, 884, 2138, 385}, // Male H.A.M TODO - lvl 1 clue
    	new int[] {995}, // Warrior
    	new int[] {995, 1523, 954, 554, 555, 556, 175}, // Rogue
    	new int[] {5318, 5319, 5320, 5321, 5322, 5323, 5324, 5305, 5306, 5307, 5308, 5309, 5310, 5311, 5096, 5097, 5098, 5099, 5100, 5101, 5102, 5103, 5104, 5105, 5106}, // Master farmer.
    	new int[] {995}, // Guard
    	new int[] {995, 175, 1523, 1823}, // Bandit guard
    	new int[] {995, 175, 1523, 1823}, // Bandits
    	new int[] {995}, // Knight
    	new int[] {995, 2309}, // Watchman
    	new int[] {995, 562}, // Paladin
    	new int[] {995, 2357, 561}, // Gnome
    	new int[] {995}, // Hero
    	new int[] {995}, // Elf
    };
    
    protected static int[][] NPC_REWARD_AMOUNT = {
    	new int[] {35}, // Men.
    	new int[] {35}, // Women.
    	new int[] {150, 1}, // Farmer
    	new int[] {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 6000, 1, 1, 1, 1, 1, 1, 1, 1, 1, 100, 1, 1}, // Female H.A.M
    	new int[] {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 6000, 1, 1, 1, 1, 1, 1, 1, 1, 1, 100, 1, 1}, // Male H.A.M
    	new int[] {300}, // Warrior
    	new int[] {500, 1, 1, 10, 10, 10, 1}, // Rogue
    	new int[] {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, // Master farmer.
    	new int[] {500}, // Guard
    	new int[] {400, 1, 1, 1}, // Bandit guard
    	new int[] {340, 1, 1, 1}, // Bandit
    	new int[] {550, 1}, // Knight
    	new int[] {600, 1}, // Watchman
    	new int[] {750, 5}, // Paladin
    	new int[] {900, 1, 2}, // Gnome
    	new int[] {1100}, // Hero
    	new int[] {1500}, // Elf
    };
    
    protected static double[] NPC_XP = {
    	8, // Men & women.
    	8, // Women.
    	14.5, // Farmer.
    	18.5, // Female HAM.
    	22.5, // Male HAM.
    	26, // Warrior.
    	35.5, // Rogue.
    	43, // Master farmer.
    	46.8, // Guard.
    	65, // Bandit guard.
    	79.4, // Desert bandit.
    	84.3, // Knights.
    	137.5, // Watchman.
    	151.75, // Paladin.
    	198.5, // Gnome.
    	275, // Hero
        353 // Elf
    };
    All of this should be stored together in SomeClass which contains IDs of NPCs, XP they give and so on. But unfortunately it's all stored separately and iterated over in its entirety. When this comes to a point where related data is stored together (and I'll probably store it on disk as well, hardcoded values in memory are meh) it'll be a lot easier to remove unnecessary information.
    Oh my god that's disgusting lol; I understand that the source may be old and whatever but what I don't understand is why people preferred storing different type of information regarding the same object in different arrays, as opposed to having it all inside an enum. I mean enums were added in java 5 which was released in 2005.. so that's no excuse. Clueless tbh.
    The way I have this type of data is this:
    Code:
    MAN(1, 8, true, 5, 1, 1, new String[] { "What do you think you're doing?" }, new ImmutableItem[] { new ImmutableItem(995, 3) }, "Man", "Woman"),
    FARMER(10, 14.5, true, 5, 1, 1, new String[] { "Cor blimey mate, what are ye doing in me pockets?" }, new ImmutableItem[] { new ImmutableItem(995, 9), new ImmutableItem(5318, 1) }, "Farmer"),
    Note: The reason I've chosen "ImmutableItem" over just Item is because it's a special obj allowing me to store more variables (min, max, % chance etc) which is used in certain cases.
    Also don't ask why I've kept the messages as an array; I can't think of any npc that'd have more than one forced message on failure but I might be wrong and there may be some.. I wrote this though so yeah.

    [Only registered and activated users can see links. ]
    Discord: Kris#1337
    Reply With Quote  
     

  4. #34  
    Registered Member
    Join Date
    May 2017
    Posts
    35
    Thanks given
    5
    Thanks received
    18
    Rep Power
    33
    Quote Originally Posted by Kris View Post
    Oh my god that's disgusting lol; I understand that the source may be old and whatever but what I don't understand is why people preferred storing different type of information regarding the same object in different arrays, as opposed to having it all inside an enum. I mean enums were added in java 5 which was released in 2005.. so that's no excuse. Clueless tbh.
    The way I have this type of data is this:
    Code:
    MAN(1, 8, true, 5, 1, 1, new String[] { "What do you think you're doing?" }, new ImmutableItem[] { new ImmutableItem(995, 3) }, "Man", "Woman"),
    FARMER(10, 14.5, true, 5, 1, 1, new String[] { "Cor blimey mate, what are ye doing in me pockets?" }, new ImmutableItem[] { new ImmutableItem(995, 9), new ImmutableItem(5318, 1) }, "Farmer"),
    Note: The reason I've chosen "ImmutableItem" over just Item is because it's a special obj allowing me to store more variables (min, max, % chance etc) which is used in certain cases.
    Also don't ask why I've kept the messages as an array; I can't think of any npc that'd have more than one forced message on failure but I might be wrong and there may be some.. I wrote this though so yeah.
    One of the things that I like very much about enums in Java is that they can essentially be turned in to instances of a class and still have a unique identifier that can be called from anywhere with access to it. In C# we don't have that sort of luxury, an enum can only really go as far as dictating finite state and is intended to be used like any other field or property.

    I've had a few attempts over the years at writing C# wrapper classes which then behave in the same fashion as Java enums, but it always seems too messy vs just using an instance of a class
    Reply With Quote  
     

  5. #35  
    Extreme Donator


    Join Date
    Jul 2009
    Age
    22
    Posts
    4,349
    Thanks given
    823
    Thanks received
    1,236
    Rep Power
    1789
    Quote Originally Posted by testicles View Post
    One of the things that I like very much about enums in Java is that they can essentially be turned in to instances of a class and still have a unique identifier that can be called from anywhere with access to it. In C# we don't have that sort of luxury, an enum can only really go as far as dictating finite state and is intended to be used like any other field or property.

    I've had a few attempts over the years at writing C# wrapper classes which then behave in the same fashion as Java enums, but it always seems too messy vs just using an instance of a class
    Regarding enums this is something I ran into when programming a C# server I did a few months back. One of the nice things you can do though is use attributes, which isn't too much of a pain in the ass.

    Edit: included an example of attributes

    Here's an example I had from my Zen project.

    Code:
    
    using System;
    
    namespace Zen.Builder
    {
        public enum DataType
        {
            [DataTypeAttr(1)] Byte,
            [DataTypeAttr(2)] Short,
            [DataTypeAttr(3)] TriByte,
            [DataTypeAttr(4)] Int,
            [DataTypeAttr(8)] Long
        }
    
        public class DataTypeAttr : Attribute
        {
            internal DataTypeAttr(int bytes)
            {
                Bytes = bytes;
            }
    
            public int Bytes { get; }
        }
    }
    And here's a small example of usage
    Code:
    public void TestAttr(DataType type) {
    	var attr = GetAttr(type);
    	if (attr == null) return;
    	
    	// .. do something with the attribute
    	var length = attr.Bytes;
    	
    }
    The GetAttr function would be as follows:
    Code:
    	private static DataTypeAttr GetAttr(DataType t) => (DataTypeAttr) Attribute.GetCustomAttribute(ForValue(t), typeof(DataTypeAttr));
    Then the ForValue would be
    Code:
    	private static MemberInfo ForValue(DataType t) => typeof(DataType).GetField(Enum.GetName(typeof(DataType), t));

    You can find my [Only registered and activated users can see links. ], for what I'm currently working on.
    Reply With Quote  
     

  6. #36  
    Registered Member
    Spyr0's Avatar
    Join Date
    Oct 2012
    Age
    25
    Posts
    1,775
    Thanks given
    350
    Thanks received
    207
    Rep Power
    253
    Best of luck bro
    Reply With Quote  
     

  7. #37  
    Registered Member

    Join Date
    Jul 2015
    Posts
    566
    Thanks given
    206
    Thanks received
    214
    Rep Power
    231
    Quote Originally Posted by Kris View Post
    Oh my god that's disgusting lol; I understand that the source may be old and whatever but what I don't understand is why people preferred storing different type of information regarding the same object in different arrays, as opposed to having it all inside an enum. I mean enums were added in java 5 which was released in 2005.. so that's no excuse. Clueless tbh.
    The way I have this type of data is this:
    Code:
    MAN(1, 8, true, 5, 1, 1, new String[] { "What do you think you're doing?" }, new ImmutableItem[] { new ImmutableItem(995, 3) }, "Man", "Woman"),
    FARMER(10, 14.5, true, 5, 1, 1, new String[] { "Cor blimey mate, what are ye doing in me pockets?" }, new ImmutableItem[] { new ImmutableItem(995, 9), new ImmutableItem(5318, 1) }, "Farmer"),
    Note: The reason I've chosen "ImmutableItem" over just Item is because it's a special obj allowing me to store more variables (min, max, % chance etc) which is used in certain cases.
    Also don't ask why I've kept the messages as an array; I can't think of any npc that'd have more than one forced message on failure but I might be wrong and there may be some.. I wrote this though so yeah.
    Nah, putting all related information in one array would be too logical
    Reply With Quote  
     

  8. Thankful user:


  9. #38  
    Registered Member
    Join Date
    May 2017
    Posts
    35
    Thanks given
    5
    Thanks received
    18
    Rep Power
    33
    In between finishing off bits of work, I've been rewriting chunks of code to increase testability. Today I've been working on introducing a Continuous Integration system called TeamCity (free, supports most environments and is fully customizable) to automate my build process and test every time a commit hits a new branch. I'm hosting it locally for the time being and it took about half an hour to set up.



    The red square indicates that the default branch (master) in its current state is failing builds because it has no tests and NUnit exits with a failure exit code.

    Here's an isolated build, which uses MSBuild, Nuget and NUnit command line to restore packages, build the project and run all tests from their related DLL files. I've written 5 basic domain object tests as an example for the lad I'm teaching. Once we've gone through these together, we'll focus on writing useful tests to ensure we don't break behaviour going forward.

    Code coverage is also automated using DotCover and coverage reports are uploaded with each build:



    Using some basic project settings I can set my default branch as well as include/filter whatever branches I want TeamCity to monitor. In this case, I just want everything monitored, so using the wildcard with +:refs/heads/* to monitor all branches.



    Current build steps are super simple. I've set up my test runner with wildcards to find any files matching the file name structure that I'll be using for all tests.



    I can also set my own failure conditions. Using the code coverage report, I'm going to label a build a failure if the coverage has dropped by more than 0.1%. With a project this large, that's a significant enough drop that it'll allow for rounding errors to be ignored, while still catching large coverave drops.



    I'll be moving this to an AWS box ASAP, so I can start chewing up those free credits that I never use
    Reply With Quote  
     

  10. #39  
    Registered Member
    _jordan's Avatar
    Join Date
    Nov 2012
    Age
    21
    Posts
    2,588
    Thanks given
    17
    Thanks received
    1,248
    Rep Power
    4766
    Goodluck with the server.
    [Only registered and activated users can see links. ]

    [Only registered and activated users can see links. ]
    [Only registered and activated users can see links. ] for veteran rank | [Only registered and activated users can see links. ] | [Only registered and activated users can see links. ]
    Reply With Quote  
     

  11. #40  
    Registered Member
    Spyr0's Avatar
    Join Date
    Oct 2012
    Age
    25
    Posts
    1,775
    Thanks given
    350
    Thanks received
    207
    Rep Power
    253
    Good luck with the project.
    Reply With Quote  
     

Page 4 of 5 FirstFirst ... 2345 LastLast

Thread Information
Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Similar Threads

  1. Unnamed Project Development Thread
    By Moronic in forum Projects
    Replies: 25
    Last Post: 01-18-2014, 01:54 AM
  2. Project #448 - Server Developers thread
    By Mainframe in forum Requests
    Replies: 0
    Last Post: 01-04-2013, 12:00 AM
  3. Replies: 11
    Last Post: 11-11-2012, 07:57 PM
  4. Replies: 12
    Last Post: 08-28-2010, 02:44 AM
  5. Nexus Server Developement Thread
    By Nexus old in forum Projects
    Replies: 8
    Last Post: 09-22-2009, 03:35 AM
Posting Permissions
  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •