Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (538)
Games in Android Showcase (132)
games submitted by our members
Games in WIP (600)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  [Kryonet] Any way to avoid instanceof check?  (Read 1307 times)
0 Members and 1 Guest are viewing this topic.
Offline Evil-Devil

Senior Devvie


Medals: 2


Fir Tree Master


« Posted 2014-07-02 13:03:30 »

Hi guys,

while thinking about how to use Kryonet for sending many different objects between the client and server I wondered how to avoid the instanceof check.

Is this even possible at all?

From my current thoughts I came up with the idea of having a simple packat class that encapsulate an op-code and some arbitrary data. In that case I would end up with some kind of lookup table to create my corresponding object.

However I really hope there is some more easier/fluent way of handling many different data objects.

Greetz
Evil-Devil
Offline Riven
« League of Dukes »

« JGO Overlord »


Medals: 840
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #1 - Posted 2014-07-02 13:46:51 »

KryoNet does exactly that behind the scenes: a lookup table with class-ids to instanciate a class. Why would you want to add an abstraction layer that replicates this behavior?

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social
Offline Evil-Devil

Senior Devvie


Medals: 2


Fir Tree Master


« Reply #2 - Posted 2014-07-02 15:26:07 »

The tutorials don't state that it is doing something like that. I've seen the serialize stuff and so on. But no real example. Every example, even those shipped with kryonet have a long list of conditionals with instance of checks
1  
2  
3  
4  
5  
6  
7  
8  
9  
[...]
public void received (Connection c, Object object) {
    if (object instanceof MyObjectA) { ... }
    if (object instanceof MyObjectB) { ... }
    if (object instanceof MyObjectC) { ... }
    if (object instanceof MyObjectD) { ... }
    [...]    
}
[...]


That is why I'm asking. Maybe I just haven't found the right source of documentation/tutorial.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Riven
« League of Dukes »

« JGO Overlord »


Medals: 840
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #3 - Posted 2014-07-02 15:30:34 »

Is an if-else chain really a problem in your code, or is this premature optimization?

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social
Offline Evil-Devil

Senior Devvie


Medals: 2


Fir Tree Master


« Reply #4 - Posted 2014-07-02 15:46:46 »

It is not about the if-else chain. It is about the annoying instanceof checking.

I was hoping there is some kind of mechanism where I can just plugin my method and object. And as you said Kryonet will take core of it with its own lookup table.
If reasonable even with an delegate interface.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
public void updateLocation(Connection c, Location location) {
    // location might be serialized
    c.send(location)
}

public void updateInventory(Connection c, Item item) {
    // serialized object
    c.send(item);
}

public void sendChatMessage(Connection c, ChatMessage msg) {
    // serialized object
    c.send(msg);
}


Depending on the actual project I might end up with > 100 type of objects to check. Such a big conditional is not maintainable. Even when using a lookup table for just the conditional check o_O

And it is not clean code Wink
Offline Riven
« League of Dukes »

« JGO Overlord »


Medals: 840
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #5 - Posted 2014-07-02 15:55:02 »

Reflection to the rescue!

Old:
1  
2  
3  
4  
5  
6  
7  
8  
9  
if(packet instanceof Location) {
   this.updateLocation(conn, (Location)packet);
}
else if(packet instanceof Item) {
   this.updateItem(conn, (Item)packet);
}
else if(packet instanceof ChatMessage) {
   this.updateChatMessage(conn, (ChatMessage)packet);
}


New:
1  
2  
3  
String packetType = packet.getClass().getSimpleName();
Method method = this.getClass().getMethod("update"+packetType, new Class[]{Connection.class, packet.getClass()});
method.invoke(this, new Object[]{conn, packet});

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social
Offline Evil-Devil

Senior Devvie


Medals: 2


Fir Tree Master


« Reply #6 - Posted 2014-07-02 16:07:45 »

Thanks riven. That might be my rescue. That way I can define a common interface and still have small maintainable source Smiley
The overhead caused by the reflection on the serverside is probably not that big. But that would be another issue when it arise.

Thx Riven!
Offline Riven
« League of Dukes »

« JGO Overlord »


Medals: 840
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #7 - Posted 2014-07-02 16:17:19 »

Just think about the packet rate on a server... Even when handling 1000 packets per second the reflection overhead will be insignificant.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social
Offline Longarmx
« Reply #8 - Posted 2014-07-02 16:48:18 »

1  
2  
3  
String packetType = packet.getClass().getSimpleName();
Method method = this.getClass().getMethod("update"+packetType, new Class[]{Connection.class, packet.getClass()});
method.invoke(this, new Object[]{conn, packet});


Wow! I have always wanted to do something like this, I just didn't know that it existed!

Online theagentd

« JGO Bitwise Duke »


Medals: 365
Projects: 2
Exp: 8 years



« Reply #9 - Posted 2014-07-02 20:25:47 »

You could do this in a "cleaner" way by defining a packet interface that all packets implement with a simple handle() function.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
public interface Packet{
    public void handle();
}

public class LocationUpdate implements Packet{
   
    ...
   
    public void handle(){
        ...
    }
}

etc


So whenever you get a packet, you simply cast it to your Packet interface and call handle() on it.

Myomyomyo.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline BurntPizza

« JGO Bitwise Duke »


Medals: 288
Exp: 5 years



« Reply #10 - Posted 2014-07-03 01:35:53 »

You could do this in a "cleaner" way by doing defining a packet interface that all packets implement with a simple handle() function.
So whenever you get a packet, you simply cast it to a Packet interface and call handle() on it.

Wouldn't even need to cast, right? Isn't that the whole point of common interfaces?

EDIT: (oh, well if it was received as an Object, then yeah I guess it would...)
Offline tberthel
« Reply #11 - Posted 2014-07-03 04:13:53 »

I don't use instanceof.  Instead I use an int value indicating type.  int comparison is cheaper than reflection or instanceof.

Still using "if" statements is also slow so you should use them only when you need them.  You can often replace the if chain with an an extended method of the same name.

if(o.type == o2.type)
{
...
}

Pages: [1]
  ignore  |  Print  
 
 

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

rwatson462 (28 views)
2014-12-15 09:26:44

Mr.CodeIt (19 views)
2014-12-14 19:50:38

BurntPizza (39 views)
2014-12-09 22:41:13

BurntPizza (74 views)
2014-12-08 04:46:31

JscottyBieshaar (36 views)
2014-12-05 12:39:02

SHC (49 views)
2014-12-03 16:27:13

CopyableCougar4 (44 views)
2014-11-29 21:32:03

toopeicgaming1999 (112 views)
2014-11-26 15:22:04

toopeicgaming1999 (98 views)
2014-11-26 15:20:36

toopeicgaming1999 (29 views)
2014-11-26 15:20:08
Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!