- The server should apply the property set immediately, not wait until

the event trundles through the queue, especially since the 'test' was
  being done immediately.
- Simplified some stuff on the server.
- Fixed up the test, as EZgame arrays will auto-grow.
- Do not set the property immediately on the client! Dangerz! We will add
  a new function for that, so that set() behaves like testAndSet() without the
  test, and set() behaves like setImmediate() without the immediate.
  (And there's no such thing as test and set immediately.)


git-svn-id: svn+ssh://src.earth.threerings.net/vilya/trunk@196 c613c5cb-e716-0410-b11b-feb51c14d237
This commit is contained in:
Ray Greenwell
2007-02-19 21:12:43 +00:00
parent 83e02730cf
commit 38016c0ab0
5 changed files with 79 additions and 46 deletions
@@ -173,9 +173,6 @@ public class GameControlBackend
_ezObj.ezGameService.setProperty(
_ctx.getClient(), propName, encoded, index,
false, null, createLoggingConfirmListener("setProperty"));
// set it immediately in the game object
_ezObj.applyPropertySet(propName, value, index);
}
public function testAndSetProperty_v1 (
@@ -34,6 +34,7 @@ public class PropertySetEvent extends NamedEvent
// from abstract DEvent
override public function applyToObject (target :DObject) :Boolean
{
// since we're in actionscript, we're always on the client
_oldValue =
EZGameObject(target).applyPropertySet(_name, _data, _index);
return true;
@@ -9,6 +9,8 @@ import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import com.samskivert.util.ObjectUtil;
import com.threerings.util.Name;
import com.threerings.io.ObjectInputStream;
@@ -85,6 +87,8 @@ public class EZGameObject extends GameObject
/**
* Called by PropertySetEvent to effect the property update.
*
* @return the old value.
*/
public Object applyPropertySet (String propName, Object data, int index)
{
@@ -123,6 +127,7 @@ public class EZGameObject extends GameObject
} else if (data != null) {
_props.put(propName, data);
} else {
_props.remove(propName);
}
@@ -131,44 +136,70 @@ public class EZGameObject extends GameObject
}
/**
* Compares whether the old value and the test value are the same.
* Test the specified property against the specified value. This is
* called on the server to validate testAndSet events.
*
* @return true if the property contains the value specified.
*/
public boolean testProperty (
String propName, int index, boolean testAndSet, Object testValue)
String propName, int index, Object testValue)
{
boolean result = false;
if (! isOnServer() || // if this is the client, don't test - only test on server
! testAndSet) // test was not requested
{
result = true;
} else {
Object oldValue = _props.get(propName);
// test if both are null
if (testValue == null || oldValue == null) {
result = (oldValue == testValue);
} else {
Object curValue = _props.get(propName);
// if the old value is an array, extract the appropriate element first
if (index >= 0 && oldValue instanceof byte[][])
{
byte[][] arr = (byte[][]) oldValue;
if (arr != null) { oldValue = arr[index]; }
if (curValue != null && index >= 0) {
// see if there's an array there already
if (isOnServer()) {
if (curValue instanceof byte[][]) {
byte[][] curArray = (byte[][]) curValue;
if (curArray.length > index) {
curValue = curArray[index];
} else {
// the index is out of range, but since we auto-grow,
// we treat it like null
curValue = null;
}
} else {
// curData is not an array, so the test fails
return false;
}
// now perform byte comparison
if (oldValue instanceof byte[] &&
testValue instanceof byte[])
{
result = Arrays.equals (
(byte[]) oldValue, (byte[]) testValue);
} else {
if (curValue instanceof Object[]) {
Object[] curArray = (Object[]) curValue;
if (curArray.length > index) {
curValue = curArray[index];
} else {
// the index is out of range, but since we auto-grow,
// we treat it like null
curValue = null;
}
} else {
// curData is not an array, so the test fails
return false;
}
}
}
return result;
// let's test the values!
if ((testValue instanceof Object[]) && (curValue instanceof Object[])) {
// testing an array against another array
return Arrays.deepEquals((Object[]) testValue, (Object[]) curValue);
} else if ((testValue instanceof byte[]) && (curValue instanceof byte[])) {
// testing a property against another property (may have
// been from inside an array)
return Arrays.equals((byte[]) testValue, (byte[]) curValue);
// TODO: other array types must be tested if we're on the client
// ??
} else {
// will catch null == null...
return ObjectUtil.equals(testValue, curValue);
}
}
@@ -30,11 +30,12 @@ public class PropertySetEvent extends NamedEvent
* Create a PropertySetEvent.
*/
public PropertySetEvent (
int targetOid, String propName, Object value, int index)
int targetOid, String propName, Object value, int index, Object oldValue)
{
super(targetOid, propName);
_data = value;
_index = index;
_oldValue = oldValue;
}
/**
@@ -68,7 +69,10 @@ public class PropertySetEvent extends NamedEvent
if (!ezObj.isOnServer()) {
_data = EZObjectMarshaller.decode(_data);
}
_oldValue = ezObj.applyPropertySet(_name, _data, _index);
if (_oldValue == UNSET_OLD_VALUE) {
// only apply the property change if we haven't already
_oldValue = ezObj.applyPropertySet(_name, _data, _index);
}
return true;
}
@@ -95,5 +99,5 @@ public class PropertySetEvent extends NamedEvent
protected Object _data;
/** The old value. */
protected transient Object _oldValue;
protected transient Object _oldValue = UNSET_OLD_VALUE;
}
@@ -132,7 +132,10 @@ public class EZGameManager extends GameManager
throws InvocationException
{
validateUser(caller);
setProperty(propName, data, index, testAndSet, testValue);
if (testAndSet && !_gameObj.testProperty(propName, index, testValue)) {
return; // the test failed: do not set the property
}
setProperty(propName, data, index);
}
// from EZGameProvider
@@ -221,7 +224,7 @@ public class EZGameManager extends GameManager
}
if (playerId == 0) {
setProperty(msgOrPropName, result, -1, false, null);
setProperty(msgOrPropName, result, -1);
} else {
sendPrivateMessage(playerId, msgOrPropName, result);
@@ -402,15 +405,12 @@ public class EZGameManager extends GameManager
* Helper method to post a property set event.
*/
protected void setProperty (
String propName, Object value, int index,
boolean testAndSet, Object testValue)
String propName, Object value, int index)
{
if (_gameObj.testProperty (propName, index, testAndSet, testValue))
{
_gameObj.postEvent(
new PropertySetEvent(
_gameObj.getOid(), propName, value, index));
}
// apply the property set immediately
Object oldValue = _gameObj.applyPropertySet(propName, value, index);
_gameObj.postEvent(new PropertySetEvent(
_gameObj.getOid(), propName, value, index, oldValue));
}
/**