Jump to content

Spirited

Administrator
  • Posts

    527
  • Joined

  • Last visited

Everything posted by Spirited

  1. I think the main problem is the length you're providing in the packet. With the structure you defined above, that's 325 bytes + 8 which is the expected 333 bytes (given a junk padding length of 12). Looking at your packet structure snippet though, you're initializing the length at only 314 bytes. I'd try fixing that length and seeing if that helps. *fingers crossed*
  2. I personally don't have much feedback to give on the React part - I enjoyed it for the brief time I worked with it - but the demo you gave looks pretty cool. I don't know many people who've worked with C3 in the last decade... not even enough people to count on one hand. So this is pretty cool to see. I'm going to move this to the Conquer Online projects section if you don't mind since it's more specific than web development, but I'll leave a shadow link from the web section. I'm looking forward to your future plans for a viewer (will be cool to see a demo when you make more progress).
  3. Thank you so much for the quick reply! I'll take a look at this. I was also wondering if there are any legality concerns attached to making a private server/source besides the TQ Binary's. And how would you know if certain code are made with these? Is it at all legal to make a private server/source? All private servers are technically illegal if you're also using a copyrighted client. I don't believe they've ever come after people before for Conquer Online, but you see it all the time with World of Warcraft private servers. They usually get a cease and desist letter to stop all operations. There's really no way of making it legal besides writing your own game that is legally distinct and doesn't infringe on copyrights (not that TQ cares about infringing on other games' copyrights).
  4. I wouldn't stress over it too much. It might be just micro-optimizing with little benefit. I personally use a switch statement just for instantiation and then rely on an interface for general decode / execute methods, but that doesn't mean I wouldn't be open to suggestions.
  5. Sure thing. If you're looking for some info about how Conquer Online does logins (the most complicated part), then I wrote up a little document here. You can use the drop down to select a supported patch. That repo as a whole is my documented server skeleton project for Conquer Online. You're welcome to check it out - it's fully documented. I also wrote an article about multi-threaded game server design if you're interested. Some additional wiki and project stuff can also be found here. I hope that's at least a good starting point.
  6. Yeah, that would be a better approach! Thanks for the suggestion. I'll look into doing that after work today.
  7. Ah, I don't think this is documented very well in Comet. Comet's client send method creates a copy of the packet with the server footer automatically appended to it and writes the packet length. Since the initial handshake packet is length 325 given the inputs you provided, +8 for the footer (TQServer) would give you the correct packet length of 333 (which is what it's expecting from you).
  8. Nice job with this. It's an interesting idea, for sure. Something to keep in mind though is that this won't necessarily yield any better performance (it might actually be magnitudes slower). In Go, the language compiler makes optimizations automatically on your behalf. In the case of a constant switch, it's likely being implemented as a jump table (I need to double check this). A map, on the other hand, is implemented using a chained hash table. It has to iterate over buckets of increasing sizes... and depending on the size of your map, that could get increasingly more expensive than a simple jump table. Not to say there's no value in a mux pattern. I do enjoy that. I would try running a benchmark test with the two approaches though and see what performance penalty the mux pattern comes with. Here's the source code to golang's map implementation if you're interested as well: https://go.googlesource.com/go/+/refs/heads/master/src/runtime/map.go. I'd be curious to know what the results are. PS: I don't know if this is really a tutorial, so I'm going to move this to the Projects section.
  9. Usually it has to do with the packet length being incorrect. In my implementation, I have the following definition: https://gitlab.com/spirited/comet/-/blob/5187/src/Comet.Game/Packets/MsgHandshake.cs#L83. I'm at work right now so I can't really check your work very closely, but I'm not 100% following your length calculation.
  10. So when decoding the message, Comet only skips in 7 bytes before it reads in the length. So perhaps you're skipping that? See here: https://gitlab.com/spirited/comet/-/blob/5187/src/Comet.Game/Packets/MsgHandshake.cs#L65
  11. All good. It's often a simple mistake like that. Glad you're making progress again.
  12. This was just something I had to setup again recently and I thought I'd post it this time around. This snippet allows for any website utilizing .htaccess to be a go-get repository by redirecting traffic from go get commands (contains go-get=1 in the request) to GitLab or another git repository hosting website. So for example, rather than importing my projects from "gitlab.com/spirited/projectname", I'd use my domain "spirited.io/projectname". That allows me to either redirect human traffic to the project page on my website or redirect go import traffic to the actual repo. Link to most up-to-date: https://gitlab.com/-/snippets/2121085 .htaccess # BEGIN GolangRedirect <IfModule mod_rewrite.c> RewriteEngine On RewriteBase / RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{QUERY_STRING} (^|&)go-get=1($|&) RewriteRule . /goimport.php [L] </IfModule> # END GolangRedirect goimport.php <?php $importpath = rtrim(strtok($_SERVER["REQUEST_URI"],'?'), '/'); $domain = 'spirited.io'; $githublink = 'https://gitlab.com/spirited'; $goImport = $domain . $importpath . ' git ' . $githublink . $importpath . '.git'; ?> <html> <head> <meta name="go-import" content="<?= $goImport; ?>"> <meta http-equiv="refresh" content="1;url=<?= $githublink . $importpath; ?>" /> </head> </html>
  13. Yeah, it might be worth looking into how you're sending MsgEncryptCode. Are you able to take a packet dump before encrypting and sending that? Maybe also double check that you're not re-generating keys after sending MsgEncryptCode. It all looks pretty reasonable to me just looking from the outside in. I think you meant to underline one byte sooner in your packet dump, right? Otherwise that's only 15 characters.
  14. It's a bit tricky to make a recommendation at this point with the limited visibility. Have you tried using Comet's RC5 implementation and did it produce those same values? Maybe you can run them side-by-side and see what values get outputted by each, or use Comet's values to create a unit test for your project. If you can start ruling out the ciphers, then you might have an easier time with the MsgAccount packet as a whole. And just a quick side note - Phoenix was one of my first open source projects and was really experimental. I don't recommend using it as a reference.
  15. No worries, just letting you know that some of my older posts aren't super reliable or friendly. I was a really different person a decade ago. Anyways, I don't think I was as clear as I could have been. I was referring to the Decrypt in the scan code cipher, not RC5. I think your RC5 is probably fine if you're using either implementation.
  16. Oh man, maybe don't listen to anything I said a decade ago. That was exactly when I started learning how to program... lol. Just looking at the code sample you provided, did you need to ref pwd_data when passing it into Decrypt for the scan codes? That's one of the reasons why I avoided using ref in a lot of those ciphers and opted for passing in a source and destination (even if the destination completely overlaps).
  17. Hm. So I think I understand what you're going for, but I'm a bit confused as to why you need a separate identifier for zones. Conquer Online already supports a static map id and dynamic map id, which means you should be able to spin up as many duplicate instances as you want without additional identifiers. If you want to partition players to existing instances of a map like how GW2 does it (sorry I'm not familiar with GW1), then that's still keyed by static map id. You just might need the value to be an array of maps rather than a single map (or have that as a separate cache). Then just have an algorithm for selecting a map instance like round robin, lowest capacity first, or player id / assigned partition id. I guess this brings up a larger question though: are you looking to completely duplicate a map or phase players in-and-out of content within small areas of a map? If it's the later, then you might benefit from having instanced map entity collections rather than instanced maps as a whole. That way, you're not completely duplicating floor grids over and over again. I suppose you could make this as complicated as you need it to be; but in its most basic form, you could index entities by a map progression id that defaults to zero. WoW calls this technique "phasing", which they use all the time for quests. Edit: Just a side note, I hope you don't feel like you owe anyone in this community anything. Please don't feel obligated to release any of your work if you don't really want to. In this community especially, I want to make it very clear that all levels of programming are welcome. You have nobody to impress and nothing to prove. There are no "elites" here.
  18. Yep, all good. And don't worry about asking questions. Asking questions and starting discussions is absolutely contributing.
  19. So, the reason why CptSky implements it with a static key is because patches before 5174(ish) don't generate the key using a random seed. You can see this difference in Comet as well between the patches (link). In newer patches, the seed is a random number that gets passed to the client in this packet. Additionally, there's a new "scan code" cipher (just what I'm calling it) that translates virtual key scan codes into ASCII characters. You can use the cipher I reverse engineered by hand here (it handles numkey for you as part of the cipher). The full process can be found here.
  20. Awesome! I'm glad it could be of help, and I'm glad to see you're still involved with this.
  21. Ahh, yeah. The surface type is a cool addition I wanted to get into as well, but it definitely takes up a lot of memory. Hmm... so I don't think your tile definition needs the X and Y coordinate. It looks like your array is already indexed on X and Y. Removing those would free up some space. Also you could change your Valid boolean to a byte for a tile bitflag system at no extra space cost, which would allow detecting if a monster or item has already been placed at a coordinate (totally optional). Your height might be problematic since some maps go well into the thousands for height. I suppose changing that to a short could be optional though as long as you're ceiling your values so they don't wrap around on overflow. You have to be a bit careful with how you reduce memory consumption, overall. In a lot of cases, it's much more performant to rely on in-memory caches and bitmaps (such as the case for using map tile flags for O(1) lookups rather than performing collection scans for at worst O(n) floor items / spawned monsters).
  22. Yeah, for sure - loading game maps with tile information can be pretty memory intensive. I've seen a few approaches, like unloading maps entirely / or unloading quadrants / chunks of maps that aren't in use (like what Minecraft does). That can be helpful for lots of lesser used maps or portions of maps that are never loaded. But ultimately, game servers are just memory intensive. It's a big reason why huge MMORPGs like World of Warcraft or Guild Wars 2 have zones that players can "phase into" or "load to" via a loading screen (really transferring you to new game servers). Just spit balling ideas, but you could make loading elevation optional. Aka. if a map is completely flat, then disable all height checks and load in a simpler tile definition (maybe make that an interface for tile flags and extend that interface for tile elevation). What you definitely want to avoid is memory compression techniques. I've seen that... and the performance is abysmal. What's your current tile definition?
  23. Heh, that definitely sounds maddening to track down when you assume everything is working correctly. May I ask what server you use to own back in the day? I never really "owned" a server, I more prototyped server architecture and my close friends would hop on to test features / stability. Technically, I think I started with CoFuture in Dec 2009 and then tried building on top of Impulse's base source in Aug 2010, but I started writing my own servers after about a year after doing that in Jan 2012? Now I work in the game industry, so I don't really get a lot of time / motivation to work on my old projects again. Maybe I'll get back to Chimera though (my "current" project on the back burner). I've had the itch to for a while.
  24. Hey Munsie! I don't know much about client edits, but I spoke with a friend who knows a bit more (working on getting their password reset potentially). He asks: did you fixed up the 3dobj.ini and 3dtexture.ini files for your edits? Hopefully we can get his account going soon (he's on a phone at the moment).
  25. Ahhhhh, all good. It happens, man. I had a bug that caused players to drop randomly. Turned out it was an off-by-one error with the packet length back when I wrote packets into static buffers rather than using byte streams. That was absolutely agonizing. Anyways, glad you figured it out!
×
×
  • Create New...