added ProposingFixture
M src/main/net/dermetfan/kryonet/box2d/multiplayer/proposing/ProposingBody.java +17 -8
@@ 43,7 43,7 @@ public class ProposingBody implements Po
 	private Body body;
 	private int objectHash;
 
-	private final Callback callback = new Callback() {
+	private final Callback createFixtureCllback = new Callback() {
 		private final WorldUpdater.Listener resultUpdater = new WorldUpdater.Listener.Adapter() {
 			@Override
 			public void created(Fixture fixture, FixtureCreation creation) {

          
@@ 75,14 75,15 @@ public class ProposingBody implements Po
 		objectHash = 0;
 	}
 
-	public Fixture createFixture(FixtureDef def) {
+	public ProposingFixture createFixture(FixtureDef def) {
 		FixtureCreation creation = Pools.obtain(FixtureCreation.class);
-		creation.setObjectHash((int) System.nanoTime()); // FIXME proper hash?
+		int hash = (int) System.nanoTime(); // FIXME proper hash?
+		creation.setObjectHash(hash);
 		creation.setBodyHash(objectHash);
 		creation.setFixtureDef(def);
 
 		resultFixture = null;
-		boolean accepted = world.proposeBlocking(creation, world.getConnection(), callback);
+		boolean accepted = world.proposeBlocking(creation, world.getConnection(), createFixtureCllback);
 		assert resultFixture != null == accepted;
 
 		Pools.free(creation);

          
@@ 90,16 91,17 @@ public class ProposingBody implements Po
 		if(!accepted)
 			return null;
 
-		// TODO ProposingFixture
-		return resultFixture;
+		ProposingFixture fixture = world.fixturePool.obtain();
+		fixture.init(this, resultFixture, hash);
+		return fixture;
 	}
 
-	public Fixture createFixture(Shape shape, float density) {
+	public ProposingFixture createFixture(Shape shape, float density) {
 		FixtureDef fixtureDef = Pools.obtain(FixtureDef.class);
 		reset(fixtureDef);
 		fixtureDef.shape = shape;
 		fixtureDef.density = density;
-		Fixture fixture = createFixture(fixtureDef);
+		ProposingFixture fixture = createFixture(fixtureDef);
 		reset(fixtureDef);
 		Pools.free(fixtureDef);
 		return fixture;

          
@@ 116,6 118,13 @@ public class ProposingBody implements Po
 		def.filter.groupIndex = 0;
 	}
 
+	public boolean destroyFixture(ProposingFixture fixture) {
+		boolean destroyed = destroyFixture(fixture.getFixture());
+		if(destroyed)
+			world.fixturePool.free(fixture);
+		return destroyed;
+	}
+
 	public boolean destroyFixture(Fixture fixture) {
 		return world.destroyObject(fixture);
 	}

          
A => src/main/net/dermetfan/kryonet/box2d/multiplayer/proposing/ProposingFixture.java +189 -0
@@ 0,0 1,189 @@ 
+package net.dermetfan.kryonet.box2d.multiplayer.proposing;
+
+import com.badlogic.gdx.math.Vector2;
+import com.badlogic.gdx.physics.box2d.Filter;
+import com.badlogic.gdx.physics.box2d.Fixture;
+import com.badlogic.gdx.physics.box2d.Shape;
+import com.badlogic.gdx.physics.box2d.Shape.Type;
+import com.badlogic.gdx.utils.Pool.Poolable;
+import com.badlogic.gdx.utils.Pools;
+import net.dermetfan.gdx.physics.box2d.Box2DUtils;
+import net.dermetfan.gdx.physics.box2d.WorldObserver.FixtureChange;
+import net.dermetfan.kryonet.box2d.multiplayer.packets.updates.Change;
+
+public class ProposingFixture implements Poolable {
+
+	private final ProposingWorld world;
+	private ProposingBody body;
+
+	private Fixture fixture;
+	private int objectHash;
+
+	ProposingFixture(ProposingWorld world) {
+		this.world = world;
+	}
+
+	void init(ProposingBody body, Fixture fixture, int objectHash) {
+		this.body = body;
+		this.fixture = fixture;
+		this.objectHash = objectHash;
+	}
+
+	@Override
+	public void reset() {
+		body = null;
+		fixture = null;
+		objectHash = 0;
+	}
+
+	public boolean setDensity(float density) {
+		if(density == fixture.getDensity())
+			return true;
+
+		FixtureChange change = Pools.obtain(FixtureChange.class);
+		change.newDensity = density;
+
+		@SuppressWarnings("unchecked")
+		Change<Fixture> update = Pools.obtain(Change.class);
+		update.setObjectHash(objectHash);
+		update.setChange(change);
+
+		boolean accepted = world.proposeBlocking(update, world.getConnection());
+
+		Pools.free(change);
+		Pools.free(update);
+
+		if(accepted)
+			fixture.setDensity(density);
+		return accepted;
+	}
+
+	public boolean setRestitution(float restitution) {
+		if(restitution == fixture.getRestitution())
+			return true;
+
+		FixtureChange change = Pools.obtain(FixtureChange.class);
+		change.newRestitution = restitution;
+
+		@SuppressWarnings("unchecked")
+		Change<Fixture> update = Pools.obtain(Change.class);
+		update.setObjectHash(objectHash);
+		update.setChange(change);
+
+		boolean accepted = world.proposeBlocking(update, world.getConnection());
+
+		Pools.free(change);
+		Pools.free(update);
+
+		if(accepted)
+			fixture.setRestitution(restitution);
+		return accepted;
+	}
+
+	public boolean setSensor(boolean sensor) {
+		if(sensor == fixture.isSensor())
+			return true;
+
+		FixtureChange change = Pools.obtain(FixtureChange.class);
+		change.newSensor = sensor;
+
+		@SuppressWarnings("unchecked")
+		Change<Fixture> update = Pools.obtain(Change.class);
+		update.setObjectHash(objectHash);
+		update.setChange(change);
+
+		boolean accepted = world.proposeBlocking(update, world.getConnection());
+
+		Pools.free(change);
+		Pools.free(update);
+
+		if(accepted)
+			fixture.setSensor(sensor);
+		return accepted;
+	}
+
+	public boolean setFriction(float friction) {
+		if(friction == fixture.getFriction())
+			return true;
+
+		FixtureChange change = Pools.obtain(FixtureChange.class);
+		change.newFriction = friction;
+
+		@SuppressWarnings("unchecked")
+		Change<Fixture> update = Pools.obtain(Change.class);
+		update.setObjectHash(objectHash);
+		update.setChange(change);
+
+		boolean accepted = world.proposeBlocking(update, world.getConnection());
+
+		Pools.free(change);
+		Pools.free(update);
+
+		if(accepted)
+			fixture.setFriction(friction);
+		return accepted;
+	}
+
+	public boolean setFilterData(Filter filter) {
+		if(Box2DUtils.equals(filter, fixture.getFilterData()))
+			return true;
+
+		FixtureChange change = Pools.obtain(FixtureChange.class);
+		change.newFilter = filter;
+
+		@SuppressWarnings("unchecked")
+		Change<Fixture> update = Pools.obtain(Change.class);
+		update.setObjectHash(objectHash);
+		update.setChange(change);
+
+		boolean accepted = world.proposeBlocking(update, world.getConnection());
+
+		Pools.free(change);
+		Pools.free(update);
+
+		if(accepted)
+			fixture.setFilterData(filter);
+		return accepted;
+	}
+
+	// local delegates
+
+	public Type getType() {return fixture.getType();}
+
+	public float getDensity() {return fixture.getDensity();}
+
+	public float getRestitution() {return fixture.getRestitution();}
+
+	public boolean isSensor() {return fixture.isSensor();}
+
+	public float getFriction() {return fixture.getFriction();}
+
+	public Object getUserData() {return fixture.getUserData();}
+
+	public void setUserData(Object userData) {fixture.setUserData(userData);}
+
+	public Filter getFilterData() {return fixture.getFilterData();}
+
+	public Shape getShape() {return fixture.getShape();}
+
+	public void refilter() {fixture.refilter();}
+
+	public boolean testPoint(float x, float y) {return fixture.testPoint(x, y);}
+
+	public boolean testPoint(Vector2 p) {return fixture.testPoint(p);}
+
+	// getters and setters
+
+	public ProposingBody getBody() {
+		return body;
+	}
+
+	public Fixture getFixture() {
+		return fixture;
+	}
+
+	public int getObjectHash() {
+		return objectHash;
+	}
+
+}

          
M src/main/net/dermetfan/kryonet/box2d/multiplayer/proposing/ProposingWorld.java +7 -2
@@ 97,6 97,13 @@ public class ProposingWorld extends Upda
 		}
 	};
 
+	final Pool<ProposingFixture> fixturePool = new Pool<ProposingFixture>(5, 250) {
+		@Override
+		protected ProposingFixture newObject() {
+			return new ProposingFixture(ProposingWorld.this);
+		}
+	};
+
 	/** @see #ProposingWorld(World, DualIntMap, Connection) */
 	public ProposingWorld(World world, DualIntMap<Object> index) {
 		this.world = world;

          
@@ 110,8 117,6 @@ public class ProposingWorld extends Upda
 		setConnection(connection);
 	}
 
-	// requires proposal
-
 	public ProposingBody createBody(BodyDef def) {
 		BodyCreation creation = Pools.obtain(BodyCreation.class);
 		int hash = (int) System.nanoTime(); // FIXME proper hash?