Welcome!

Join our community of MMO enthusiasts and game developers! By registering, you'll gain access to discussions on the latest developments in MMO server files and collaborate with like-minded individuals. Join us today and unlock the potential of MMO server development!

Join Today!

MapleScala

Junior Spellweaver
Joined
Apr 20, 2013
Messages
103
Reaction score
24
I guess I have been lurking here to long again, so here I am to share something
I have decided I wanted to learn Scala and the best way of doing such is obviously writing a source from scratch.

The version I have chosen for is v83, simply because it is one of the version where public sources already exists for and it also has nice piece of nostalgic feeling to it.
While I doubt I will be able to fling out a complete source, I will see how far I can get by smashing a few keys here and there

After fighting a whole day with the lack of unsigned values, I managed to finish packet decryption, after that I threw it on Github, which its link can be found here;


The packages I will be using are;
Akka, for its TCP and Actor handling
Scalatest, for unit tests
ScalikeJDBC, for database connectivity

Any other packages I will probably figure out on the go.
I wont be using any packages for the AES handling, as, well, I already wrote my own (as mentioned above)

Feel free to help me out by creating pull request, but keep in mind this is a project that merily exists to easy my boredom.
 
Junior Spellweaver
Joined
Jan 2, 2014
Messages
150
Reaction score
50
Hopefully you continue this long enough for it to get somewhere, people usually lose dedication before that happens.
 
Junior Spellweaver
Joined
Apr 20, 2013
Messages
103
Reaction score
24
Hopefully you continue this long enough for it to get somewhere, people usually lose dedication before that happens.

Yeah, the major share of projects end up that way.
Though I think sharing the crypto I wrote is quite useful on its own

Anyhow, today wasted most of the day fixing crypto related bugs.
Currently it seems sending any data causes the client to disconnect, so I will work on that tomorrow

Update:
Minike - MapleScala - RaGEZONE Forums

Encryption / Decryption works now
 
Last edited:
Junior Spellweaver
Joined
Mar 21, 2015
Messages
126
Reaction score
13
It's always refreshing to see new languages being utilized for maple sources. Scala seems quite interesting, I wish you the best.
 
Junior Spellweaver
Joined
Apr 20, 2013
Messages
103
Reaction score
24
I just pushed another update to git.
Currently registering a PIN and using it to login works, I actually ended up writing quite a lot of code as unlike any Odin sources, I want a proper login system.
All user authorization goes through a single class, the "AuthHandler", this so it would be easier to split the load between multiple servers in the future.
I also encountered a few security flaws in MoopleDev, so I was quite entertained while doing this.
 
Last edited:
Experienced Elementalist
Joined
Feb 10, 2008
Messages
249
Reaction score
161
Yeah, the major share of projects end up that way.
Though I think sharing the crypto I wrote is quite useful on its own

Anyhow, today wasted most of the day fixing crypto related bugs.
Currently it seems sending any data causes the client to disconnect, so I will work on that tomorrow

Update:
Minike - MapleScala - RaGEZONE Forums

Encryption / Decryption works now

what IDE are you using?
 
Junior Spellweaver
Joined
Apr 20, 2013
Messages
103
Reaction score
24
what IDE are you using?

I use IntelliJ as its one of the few IDEs that actually run Scala properly.
Though on that image, I ran the server by starting it on activator
 
Experienced Elementalist
Joined
Nov 21, 2008
Messages
297
Reaction score
38
This is very interesting. Any updates? :eek:tt:
 
Junior Spellweaver
Joined
Apr 20, 2013
Messages
103
Reaction score
24
This is very interesting. Any updates? :eek:tt:

Most code up to character selection is finished, though I did not have any time yet to write anything beyond that.
And as this is still a solo project, there has been little progress.
 
Junior Spellweaver
Joined
Apr 20, 2013
Messages
103
Reaction score
24
Today I ported aaronweiss his PKGNX to Scala, mainly because I found the XML reading support of Scala to be utterly horrible.
Though I have only added the Lazy loading variant and non-audio / bitmap types

I also got characters to display (without equips) and they are loading from the database
 
Skilled Illusionist
Joined
Apr 21, 2012
Messages
337
Reaction score
144
You do know that Scala has complete interoperability with Java, right? There's no reason to make a non-specification-compliant version of pkgnx just to use Scala. This is especially relevant because what you wrote is not even idiomatic Scala as it's in Java-style (idiomatic Scala is functional!).
 
Last edited:
Junior Spellweaver
Joined
Apr 20, 2013
Messages
103
Reaction score
24
You do know that Scala has complete interoperability with Java, right? There's no reason to make a non-specification-compliant version of pkgnx just to use Scala. This is especially relevant because what you wrote is not even idiomatic Scala as it's in Java-style (idiomatic Scala is functional!).

I ported it to Scala 1 on 1 for now so I have the possibility of changing it later.
I am fully aware Scala has interoperability with Java, but like I said, this way I would lose the freedom of directly editing it as Scala.

On a side note;
The tone in your post is set completely wrong, so I would like to ask you to other be helpful or not reply at all.
As like I mentioned, I have no previous experience with Scala, so you are just behaving like a complete butt to somebody who is still learning.
But if you happen to have any good tips or hints, please feel free to post those.
 
Junior Spellweaver
Joined
Apr 10, 2008
Messages
131
Reaction score
45
I ported it to Scala 1 on 1 for now so I have the possibility of changing it later.
I am fully aware Scala has interoperability with Java, but like I said, this way I would lose the freedom of directly editing it as Scala.
You're not editing it as Scala. You're writing Java. If that was an important freedom, why didn't you just do that at the outset?

The tone in your post is set completely wrong


so I would like to ask you to other be helpful or not reply at all.
As like I mentioned, I have no previous experience with Scala, so you are just behaving like a complete butt to somebody who is still learning.
You could at least change the license if you're going to copy-paste the entire thing and call it your own. Previous experience with Scala does not have anything to do with what he's saying.
 
Junior Spellweaver
Joined
Apr 10, 2008
Messages
131
Reaction score
45
You might have actually wanted to view the source before you start spouting baseless things


I'm not sure how to reply to a visitor message and it doesn't seem like you have them enabled, so I'll have to respond here.

I realize that you may be slightly stupid, but do you understand what the word baseless means?





Baseless means that there is no evidence for the claim.

They are exactly the same. This is as far from baseless as it gets. There is direct and irrefutable evidence that they are the same. Your suggestion that it is baseless is baseless.
 
Last edited:
Skilled Illusionist
Joined
Apr 21, 2012
Messages
337
Reaction score
144
I ported it to Scala 1 on 1 for now so I have the possibility of changing it later.
I am fully aware Scala has interoperability with Java, but like I said, this way I would lose the freedom of directly editing it as Scala.

The library is 100% feature-complete, seeing as we invented the format. I don't see a particular reason why you'd bother copy-pasteing all of my code and then updating the syntax. Also, please remove attribution to me on this code that I did not write, and change the name of the library in your project. It's a derivative work. I'm not responsible for it. It is not in any way associated with me.

The tone in your post is set completely wrong, so I would like to ask you to other be helpful or not reply at all.
Thank you, tone police.

As like I mentioned, I have no previous experience with Scala, so you are just behaving like a complete butt to somebody who is still learning.

I'm behaving like an butt because I said that you wrote this in Java style? Ok then.

But if you happen to have any good tips or hints, please feel free to post those.

You use Java-style inheritance like so:

Code:
class NXLongNode(override val name: String,
                 override val file: NXFile,
                 override val childIndex: Int,
                 override val childCount: Int,
                 val reader: BufferedReader)
  extends NXNode(name, file, childIndex, childCount) {

  final val value = reader.getLong

  override def get(): Long = value

}

Use a trait like so:
Code:
sealed trait NXNode(name: String, file: NXFile, childIndex: Int, childCount: Int)
case class NXLongNode(name: String, file: NXFile, childIndex: Int, childCount: Int, value: Long) extends NXNode(name, file, childIndex, childCount)
...

You allow things to be null:
Code:
class NXNullNode(override val name: String,
                 override val file: NXFile,
                 override val childIndex: Int,
                 override val childCount: Int,
                 val reader: BufferedReader)
  extends NXNode(name, file, childIndex, childCount) {

  reader.skip(8)

  override def get(): Any = null
}

Use Unit (the only value of type Unit is ()) in this case.

Code:
def resolve(path: Array[String]): NXNode = {
    var cursor: NXNode = getRoot
    for (piece <- path) {
      if (cursor == null)
        return null
      cursor = cursor.getChild(piece)
    }

    cursor
  }

Use Option!

On that note, you also use Java-style iterators and for loops.

Code:
for (node <- reader.resolve("MakeCharInfo.img/Info")) {
      for (subNode <- node) {
        // CharFemale | CharMale
        for (valueNode <- subNode) {
          val value = valueNode.asInstanceOf[NXLongNode].get()
          if (value > 1e6)
            allowedEquips += value
        }
      }
    }

Use maps and folds!

Also, if you use traits, you won't have to write garbage like this:
Code:
valueNode.asInstanceOf[NXLongNode].get()

You also have mutability everywhere. The whole thing should be stateless. You don't need state at all for this task!

EDIT: adding more things

You keep writing unnecessary things like keywords for constructor parameters.

Code:
class LazyNXFile(val buffer: ByteBuffer)
can just be
Code:
class LazyNXFile(buffer: ByteBuffer)

You have an empty Iterator.

Code:
final class EmptyNodeIterator
  extends Iterator[NXNode] {

  override def hasNext: Boolean = false

  override def next(): NXNode = null
}

This is normal crufty Java boilerplate, but if you used Seq, you wouldn't need this.
 
Last edited:
Junior Spellweaver
Joined
Apr 20, 2013
Messages
103
Reaction score
24
Also, please remove attribution to me on this code that I did not write

Actually according to the MIT license I should mention the original license on anything that would be a copy (Possibly this is just my misunderstanding of what a 'copy' could be considered to be)

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

Thank you, tone police.

The whole point why I said this was because my expectations of any reply would be such as your later, not like the first one.

Anyways, thank you for this reply, I will use as a reference to create my own reader. (as you apparently do not like the fact your public source is re-used)
 
Joined
Apr 5, 2008
Messages
663
Reaction score
537

Code:
    using(getClass.getResourceAsStream("/XML/Etc.nx.gz"))(stream => {
      bytes = GzipParser.readGzip(stream)
    })
Really? You're loading compressed NX files?
I find it hilarious how people are using the NX file format.
NX was designed first and foremost for me, for my C++/Rust, so that I can memory map the file and access the data directory with almost no loading and without using up significant amounts of memory.
Meanwhile here you are compressing your NX files so that not only do you have all the loaded NX data in memory, but you also have the decompressed file itself in memory.
The set of NX files for servers (so no bitmaps or sounds) was 451 MB back in GMS v141. Do you really want to throw that much memory away, plus the CPU time to decompress that, just for the sake of saving a bit of hard drive space?
 
Skilled Illusionist
Joined
Apr 21, 2012
Messages
337
Reaction score
144
Actually according to the MIT license I should mention the original license on anything that would be a copy (Possibly this is just my misunderstanding of what a 'copy' could be considered to be)

Yes, the license says to maintain the license. I still request that you change the name of the library, as while that is basically copy+paste of my code, I don't want my library to be associated with such a lousy "port."

Anyways, thank you for this reply, I will use as a reference to create my own reader.
Or you could just use the library to begin with and submit a PR if you want to make changes.

(as you apparently do not like the fact your public source is re-used)
The snark is real. The issue isn't that it's being re-used. The issue is that you're not actually using it. You "ported" it to Scala by taking the exact same code and rewriting it with Scala syntax.
 
Last edited:
Junior Spellweaver
Joined
Apr 20, 2013
Messages
103
Reaction score
24

Code:
    using(getClass.getResourceAsStream("/XML/Etc.nx.gz"))(stream => {
      bytes = GzipParser.readGzip(stream)
    })
Really? You're loading compressed NX files?
I find it hilarious how people are using the NX file format.
NX was designed first and foremost for me, for my C++/Rust, so that I can memory map the file and access the data directory with almost no loading and without using up significant amounts of memory.
Meanwhile here you are compressing your NX files so that not only do you have all the loaded NX data in memory, but you also have the decompressed file itself in memory.
The set of NX files for servers (so no bitmaps or sounds) was 451 MB back in GMS v141. Do you really want to throw that much memory away, plus the CPU time to decompress that, just for the sake of saving a bit of hard drive space?

I did this because most files will be parsed (almost) completely and I will only save the information I need in the memory.
So the extra allocated memory for the files will be cleared right after I have collected all data.

As for the compression, I do not understand the problem of it taking a little more cpu time, as it will only be called when the server is started.
 
Joined
Apr 5, 2008
Messages
663
Reaction score
537
I did this because most files will be parsed (almost) completely and I will only save the information I need in the memory.
So the extra allocated memory for the files will be cleared right after I have collected all data.

As for the compression, I do not understand the problem of it taking a little more cpu time, as it will only be called when the server is started.
I just find it incredulous that anyone would be willing to have their server take longer to startup just to save a bit of hard drive space.
 
Back
Top