Как сериализовать объект JBox2d World?

У меня есть сервер, к которому подключаются несколько клиентов. У каждого клиента есть одно тело (игрок), которым он может управлять, но может быть столкновение, поэтому им нужно будет видеть тела всех остальных, чтобы знать, почему некоторые из их движений ограничены.

Мое решение состоит в том, чтобы передать объект «Мир» через поток ввода/вывода объекта. Затем я разбираю и рисую каждое тело с помощью обработки. Вот ошибка, которую я получаю:

java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: org.jbox2d.dynamics.World
    at java.io.ObjectInputStream.readObject0(Unknown Source)
    at java.io.ObjectInputStream.readObject(Unknown Source)
    at Client.setup(Client.java:30)
    at processing.core.PApplet.handleDraw(PApplet.java:2280)
    at processing.core.PGraphicsJava2D.requestDraw(PGraphicsJava2D.java:243)
    at processing.core.PApplet.run(PApplet.java:2176)
    at java.lang.Thread.run(Unknown Source)
Caused by: java.io.NotSerializableException: org.jbox2d.dynamics.World
    at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    at java.io.ObjectOutputStream.writeObject(Unknown Source)
    at Player.sendWorld(Player.java:57)
    at Server.draw(Server.java:54)
    at processing.core.PApplet.handleDraw(PApplet.java:2305)
    ... 3 more

Очевидно, что World должен быть сериализован/сериализуем, прежде чем его можно будет передать через сокет. Есть идеи, как я это сделаю? Мне нужно будет сделать для каждого тела, создать xml/json, а затем передать это вместо того, чтобы просто отправить мир?

Сервер отключен

public void sendWorld(World world) {
    try {
        out.writeObject(world);
        out.flush(); // or maybe out.reset()
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Клиент вошел

try {
    bodySocket = new Socket(serverHostname, port);
    in = new ObjectInputStream(bodySocket.getInputStream());
    Object next = in.readObject();
    System.out.println("Getting world");
    if (next instanceof World) {
        this.world = (World) next;
    }
} catch (UnknownHostException e) {
    System.err.println("Don't know about host: " + serverHostname);
    System.exit(1);
} catch (IOException e) {
    System.err.println("Couldn't get I/O for " + "the connection to: "
            + serverHostname);
    e.printStackTrace();
    System.exit(1);
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

Отрисовка клиента

public void draw() {
    // Background
    background(100);
    // Bodies (includes floors, walls, and players)
    for (Body body = world.getBodyList(); body != null; body = body
            .getNext()) {
        Vec2 playerLoc = body.getPosition();
        rectMode(PApplet.RADIUS);
        fill(255, 100);
        rect(playerLoc.x, fieldBottom - playerLoc.y, 10, 10);
    }
}

person Brantley Blanchard    schedule 07.10.2013    source источник
comment
Если я не смогу понять это в ближайшее время, я могу в конечном итоге перебрать список тел мира и создать объект json для хранения пользовательских данных, координат и типов объектов каждого тела. Было бы более эффективно работать в сети, но не так легко писать.   -  person Brantley Blanchard    schedule 08.10.2013


Ответы (2)


По этой причине я сделал пакет сериализации :)

Я включаю сериализацию в protobufs, что, вероятно, лучше всего подходит для вас (больше всего уменьшает размер). Вы можете сериализовать миры, тела, суставы, формы с любой степенью детализации.

Ознакомьтесь с PbSerializer

и вот документация по protobufs: https://code.google.com/p/protobuf/

person Daniel Murphy    schedule 08.10.2013
comment
Я не смог заставить его работать. Вся документация с примерами предназначена для С++, а не для Java. Я попробовал несколько вещей и в итоге сдался. На самом деле должна быть страница, как у них для C#, которая дает не только доступные методы, но и краткий пример того, как их использовать. - person Brantley Blanchard; 13.10.2013
comment
Документация находится на C++ и Java, проверьте еще раз: developers.google.com/protocol-buffers /docs/javatutorial :) Или, что более важно, вам не нужно беспокоиться о создании буфера протокола, поскольку я уже сделал это. Просто используйте классы PbSerializer и PbDeserializer, которые я создал в пакете jbox2d-serialization. - person Daniel Murphy; 15.11.2013
comment
Спасибо, что написали. Я просмотрел страницу, на которую вы ссылались, но на самом деле не видел примеров сериализации в Java. Может быть, я просто пропустил это. Я видел несколько методов, но не то, как они используются и чего они ожидают. Я попробовал классы PS и PD, но когда я, наконец, получил его для компиляции, мой объектный писатель передал его. В итоге я написал свой собственный анализатор JSON, но мне бы хотелось увидеть скелетный пример объекта мира, передаваемого с сервера на клиент! Мне любопытно, если вы решите отправить строку или объект через сокет. - person Brantley Blanchard; 20.11.2013
comment
Объекты protobuf имеют методы сериализации в байты, они очень эффективны и очень хорошо сжимаются. Я бы очень хотел узнать о них, это отличный инструмент, который вам хорошо послужит (они также очень популярны в отрасли). Что вы имеете в виду, что мой объектный писатель передаст это? Кроме того, все, что вам нужно сделать, это вызвать build() для мира, который вы сериализуете, а затем вы можете сделать что-то вроде toByteArray() или что-то в этом роде, взгляните на protobuf javadoc для лучшего метода сериализации. - person Daniel Murphy; 24.11.2013

Вы можете взглянуть на класс JBbSerializer. Из его javadoc: «Сериализатор для jbox2d, используемый для сериализации любого аспекта физического мира», поэтому он может делать то, что вы ищете. Найдите его в проекте jbox2d-serialization (который должен быть при загрузке). Это может быть больше проблем, чем оно того стоит.

person thomas88wp    schedule 08.10.2013
comment
Спасибо, это может сработать... PbSerializer pbs = new PbSerializer(); Строитель obj = pbs.serializeWorld(world); а затем на клиенте if (следующий экземпляр Builder) { this.world = pbd.deserializeWorld((PbWorld)next); - person Brantley Blanchard; 08.10.2013