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!

[LATEST] Icarus Emulator [Java, Netty, MySQL, Plugins, Camera]

Status
Not open for further replies.
Developer
Developer
Joined
Dec 11, 2010
Messages
2,955
Reaction score
2,685
re: Icarus Server (Production) - [Python, Multi-DB/MySQL]

Sorry for lack of updates, been doing some stuff but not much since I've been focusing on something personal, however there has been updates, you can view them here:



Updates (so far):

- Implemented plugin system with event system
- Started on room items

Example plugin found here:



Plugin system is heavily, heavily inspired by the Bukkit system. I believe the Bukkit plugin system is one of the most user-friendliest systems ever, so that's why I've chosen the plugin layout for my server.

Here is a link:

Thanks babe :love:
 
Developer
Developer
Joined
Dec 11, 2010
Messages
2,955
Reaction score
2,685
re: Icarus Server (Production) - [Python, Multi-DB/MySQL]


No.

Maybe if this thread was active I'd get motivation but clearly no one gives two shits so why should I bother?

Also upon reinstalling my operating system, I accidentally wiped the wrong partition with all my client data on it so I haven't bothered to set it up again.
 
Joined
Apr 24, 2013
Messages
1,680
Reaction score
1,119
re: Icarus Server (Production) - [Python, Multi-DB/MySQL]

No.

Maybe if this thread was active I'd get motivation but clearly no one gives two shits so why should I bother?

Also upon reinstalling my operating system, I accidentally wiped the wrong partition with all my client data on it so I haven't bothered to set it up again.

You should bother because you develop to learn something new and gain more experience, not to earn likes on RZ.
 
Developer
Developer
Joined
Dec 11, 2010
Messages
2,955
Reaction score
2,685
re: Icarus Server (Production) - [Python, Multi-DB/MySQL]

You should bother because you develop to learn something new and gain more experience, not to earn likes on RZ.

What an ignorant statement.

If I'm not receiving support for a development, then there's no incentive for it.
 
Joined
Apr 24, 2013
Messages
1,680
Reaction score
1,119
re: Icarus Server (Production) - [Python, Multi-DB/MySQL]

What an ignorant statement.

If I'm not receiving support for a development, then there's no incentive for it.

You've got 6 pages full of support. Of course people will not post a page full of support after each update. We have a saying here which is; no response is good response haha. What is your goal for developing this project? Since you don't earn money from it, it should be to gaining more knowledge right? ^^
 
Developer
Developer
Joined
Dec 11, 2010
Messages
2,955
Reaction score
2,685
re: Icarus Server (Production) - [Python, Multi-DB/MySQL]

You've got 6 pages full of support. Of course people will not post a page full of support after each update. We have a saying here which is; no response is good response haha. What is your goal for developing this project? Since you don't earn money from it, it should be to gaining more knowledge right? ^^

Alright, you've got a point there.

I've had some personal issues which has stopped me from developing, and lack of thread activity is just icing on the cake.
 
Developer
Developer
Joined
Dec 11, 2010
Messages
2,955
Reaction score
2,685
re: Icarus Server (Production) - [Python, Multi-DB/MySQL]

It will continue. I've just been busy right now.

I'm not going to cease development but I'm just taking a break.
 
Master Summoner
Joined
Dec 1, 2013
Messages
547
Reaction score
694
re: Icarus Server (Production) - [Python, Multi-DB/MySQL]

I understand you Quackster . I always visit the thread to see the progress and I think alot of people do the same without giving a reply. Did follow your git everyday. (3 weeks no update's anymore :( ).

I wish you the best of luck with your development don't look at the thread. Problem is alot of people aren't intrested in the base development of an emulator (Only active developers and Habbo retro die hards watch every thread like ovflowd ).

When people see that the emulator is getting heavily developed the activity will be high ;)
 
Developer
Developer
Joined
Dec 11, 2010
Messages
2,955
Reaction score
2,685
re: Icarus Server (Production) - [Python, Multi-DB/MySQL]

Updates or riot

I lost all my client data files and poop after reinstalling my operating system and wiping the wrong harddrive partition after Ducking up a Windows prompt command, so I haven't bothered to redownload them for ages on my crappy Australian internet.

However I finally downloaded them overnight (because downloading them whilst doing other poop would lag my internet) so I should be cracking on updates shortly. :):
 
Developer
Developer
Joined
Dec 11, 2010
Messages
2,955
Reaction score
2,685
re: Icarus Server (Production) - [Python, Multi-DB/MySQL]

Added event timeout for plugins after Hoshiko opened up an . The timeout time and unit can be configured in the Icarus properties file.



Basically if an event takes more than a few seconds to execute, it will cancel and throw an exception. I will add the option for events to override this if necessary.
 
Developer
Developer
Joined
Dec 11, 2010
Messages
2,955
Reaction score
2,685
re: Icarus Server (Production) - [Python, Multi-DB/MySQL]

Updates

- Recoded my item handling to support wall items (only supported floor items first so I kinda avoided this as it required rewriting parts).
- Added wall item placement
- Added load wall items when player joined a room
- Added an easier way to register tasks to be called on the room cycle.

Code:
room.getCycle().registerEvent(event, interval);

The cycle is ran every 500ms, so putting "2" for the interval would mean it would be called every 1000ms/1 second.

- Fixed a bug where if a user with rights placed an item in a room which wasn't theirs, upon reloading, the item they placed would say the original room owner owned that specific item (instead of the person who placed it).

- Fixed a bug where removing/adding items to inventory wouldn't update the inventory screen and you'd need to re-open the inventory to force an update (wrong header).



---

All the latest source commits can be found on the unstable branch:

The reason why I push to the unstable branch is because I cannot guarantee that there won't be any client crashes or anything along that nature, when I feel like it is stable enough, the source will be merged with the main branch.

You better finish something for a change Quack! I've been gone for a while so you better don't disappoint me!

It's been like 1-2 years since my last project and my last project was just.... bad :p
 
Last edited:
Retired
Loyal Member
Joined
May 5, 2007
Messages
497
Reaction score
665
re: Icarus Server (Production) - [Python, Multi-DB/MySQL]

Is this the real Quackster? Congratulations on seeing the need for DAOs! Been skimming through some of the code and this thread and this looks quite promising. Browsing your code at your repo in the browser should give you a very clear idea of why you don't want to use tabs for indentation. (You're also still using Eclipse, like come on its 2016 for crying out loud) After looking through some of your DAOs, I would believe what The General was trying to point out earlier was that if something wrong happens between opening the SQL connection (eg. aquiring a PreparedStatement) and releasing it through Storage.releaseObject. There are a number of things wrong with this approach, if you look at the function getItem(long itemId) on :
Code:
@Override
public Item getItem(long itemId) {


    try {


        PreparedStatement statement = dao.getStorage().prepare("SELECT * FROM items WHERE id = ? LIMIT 1");
        statement.setLong(1, itemId);


        ResultSet row = statement.executeQuery();


        Item item = new Item();


        if (!row.next()) {
            return null;
        }


        this.fill(item, row);


        Storage.releaseObject(row);


        return item;


    } catch (Exception e) {
        Log.exception(e);
    }


    return null;
}

If an exception is thrown at statement.executeQuery, the connection to the database would remain open. I can see that you have some finally blocks here and there but this is still a dangerous practice as you have to remember to write the finally block. You also get code duplication for this across all the places where you handle the closing of the connection. This is what solves. By making the PreparedStatement implement the AutoClosable interface, you avoid zombie connections, code duplication and having to remember these retarded things that can duck you up really bad.
And don't do SELECT *, don't. You rely on a specific order from the database (but in this case you specify them later on so thats fine), but then if something is missing you get an exception on a far later stage than if it is in the query itself (An exception would be thrown when querying the database instead of in the fill command).
I really dislike the set functions where you specify the index of an argument (setLong in your case) as it is not maintainable when you get a few more parameters. Using parameter names is far easier to read and maintain. I'm also questioning why you have a LIMIT 1 on a query where it would be reasonable that the id field is the primary key and it would therefore always return either one or zero rows.
Your code also demonstrates a good example of error hiding where if an exception is thrown in the try-catch block, the caller does not know whether the database call failed or if the item does not exist.
The code I quoted has some really strong dependencies that makes it hard to test, but this is up to you.

I'm not gonna say this is code is good, because it wasn't (Yet it was actually consistently formatted which I find rare in the Java world for some strange reason [???]). But I still think this is a really good project compared to the other I've seen so far and it got a great potential. Good luck! (And are you the real Quackster????)
 
Joined
Aug 10, 2011
Messages
7,401
Reaction score
3,299
re: Icarus Server (Production) - [Python, Multi-DB/MySQL]

And then they say my double try-catch was overkill and I don't know what I'm doing.

Pfft.

And yeah, don't use tabs. 4 spaces for each tab. Always. Nothing is more annoying that crappy formatted code because someone put his tab width on 2 spaces and then opening it on another platform or software.
 
Retired
Loyal Member
Joined
May 5, 2007
Messages
497
Reaction score
665
re: Icarus Server (Production) - [Python, Multi-DB/MySQL]

And then they say my double try-catch was overkill and I don't know what I'm doing.

I didn't. If I were ever to comment on that, it would be that you should use try-with-resource instead of those ugly double try-catches.
 
Developer
Developer
Joined
Dec 11, 2010
Messages
2,955
Reaction score
2,685
re: Icarus Server (Production) - [Python, Multi-DB/MySQL]

Is this the real Quackster? Congratulations on seeing the need for DAOs! Been skimming through some of the code and this thread and this looks quite promising. Browsing your code at your repo in the browser should give you a very clear idea of why you don't want to use tabs for indentation. (You're also still using Eclipse, like come on its 2016 for crying out loud) After looking through some of your DAOs, I would believe what The General was trying to point out earlier was that if something wrong happens between opening the SQL connection (eg. aquiring a PreparedStatement) and releasing it through Storage.releaseObject. There are a number of things wrong with this approach, if you look at the function getItem(long itemId) on :
Code:
@Override
public Item getItem(long itemId) {


    try {


        PreparedStatement statement = dao.getStorage().prepare("SELECT * FROM items WHERE id = ? LIMIT 1");
        statement.setLong(1, itemId);


        ResultSet row = statement.executeQuery();


        Item item = new Item();


        if (!row.next()) {
            return null;
        }


        this.fill(item, row);


        Storage.releaseObject(row);


        return item;


    } catch (Exception e) {
        Log.exception(e);
    }


    return null;
}

If an exception is thrown at statement.executeQuery, the connection to the database would remain open. I can see that you have some finally blocks here and there but this is still a dangerous practice as you have to remember to write the finally block. You also get code duplication for this across all the places where you handle the closing of the connection. This is what solves. By making the PreparedStatement implement the AutoClosable interface, you avoid zombie connections, code duplication and having to remember these retarded things that can duck you up really bad.
And don't do SELECT *, don't. You rely on a specific order from the database (but in this case you specify them later on so thats fine), but then if something is missing you get an exception on a far later stage than if it is in the query itself (An exception would be thrown when querying the database instead of in the fill command).
I really dislike the set functions where you specify the index of an argument (setLong in your case) as it is not maintainable when you get a few more parameters. Using parameter names is far easier to read and maintain. I'm also questioning why you have a LIMIT 1 on a query where it would be reasonable that the id field is the primary key and it would therefore always return either one or zero rows.
Your code also demonstrates a good example of error hiding where if an exception is thrown in the try-catch block, the caller does not know whether the database call failed or if the item does not exist.
The code I quoted has some really strong dependencies that makes it hard to test, but this is up to you.

I'm not gonna say this is code is good, because it wasn't (Yet it was actually consistently formatted which I find rare in the Java world for some strange reason [???]). But I still think this is a really good project compared to the other I've seen so far and it got a great potential. Good luck! (And are you the real Quackster????)

Just to be clear, are you suggesting I turn them into something like this?

Code:
@Override
public Item getItem(long itemId) {

	Item item = null;
	ResultSet row = null;

	try (PreparedStatement statement = dao.getStorage().prepare("SELECT id, user_id, item_id, room_id, x, y, z, rotation, extra_data FROM items WHERE id = ? LIMIT 1")) {

		statement.setLong(1, itemId);
		row = statement.executeQuery();

		item = new Item();

		if (!row.next()) {
			return null;
		}

		this.fill(item, row);

	} catch (Exception e) {
		Log.exception(e);
	} finally {
		Storage.releaseObject(row);
	}

	return item;
}
 
Retired
Loyal Member
Joined
May 5, 2007
Messages
497
Reaction score
665
re: Icarus Server (Production) - [Python, Multi-DB/MySQL]

Just to be clear, are you suggesting I turn them into something like this?

Code:
@Override
public Item getItem(long itemId) {

    Item item = null;
    ResultSet row = null;

    try (PreparedStatement statement = dao.getStorage().prepare("SELECT id, user_id, item_id, room_id, x, y, z, rotation, extra_data FROM items WHERE id = ? LIMIT 1")) {

        statement.setLong(1, itemId);
        row = statement.executeQuery();

        item = new Item();

        if (!row.next()) {
            return null;
        }

        this.fill(item, row);

    } catch (Exception e) {
        Log.exception(e);
    } finally {
        Storage.releaseObject(row);
    }

    return item;
}

No, more like this:
Code:
@Override
public Item getItem(final long itemId) throws DatabaseException {
    // I know long queries are pain in the butt, thats why people use ORMs, besides your database is not even normalized :^) 
    final String query = "SELECT id, user_id, item_id, room_id, x, y, z, rotation, extra_data " +
            "FROM items " +
            "WHERE id = @itemId";
            
    try (PreparedStatement statement = dao.getStorage().prepare(query)) {
        statement.setValue("@itemId", itemId); // <Not sure if this exists
        final ResultSet row = statement.executeQuery();

        if (!row.next()) {
            return null;
        }

        final Item item = itemFactory.createItem(); // < Makes the class less dependent on the new keyword (which is often refered to as glue) which then makes it more easy to write unit tests on
        this.fill(item, row);
        
        return item;
    } catch (MySQLException e) { // < not sure if this is specific enough, but you should specify concrete exception classes instead of high-level exception classes
        logger.logException(e, e.getMessage()); // < dependency inject logger
        throw new DatabaseException(e, e.getMessage());
    }
}
 
Status
Not open for further replies.
Back
Top