Browse Source

Fixed Unix build. Fixed counting of enemies in multiplayer NinjaSnowWar. Disabled snowball CollisionShape replication due to divergent simulation on the client. Removed previousControls from Connection as it is potentially unreliable if multiple controls packets arrive between updates.

Lasse Öörni 14 years ago
parent
commit
bd76a14249

+ 14 - 3
Bin/Data/Scripts/NinjaSnowWar.as

@@ -655,8 +655,12 @@ void SendHiscores(int playerIndex)
 
 void SpawnObjects(float timeStep)
 {
+    // If game not running, run only the random generator
     if (!gameOn)
+    {
+        Random();
         return;
+    }
 
     // Spawn powerups
     powerupSpawnTimer += timeStep;
@@ -683,8 +687,14 @@ void SpawnObjects(float timeStep)
     if (enemySpawnTimer > enemySpawnRate)
     {
         enemySpawnTimer = 0;
-        // Take the player ninja into account
-        int numEnemies = gameScene.GetChildrenWithScript("Ninja", true).length - 1;
+        int numEnemies = 0;        
+        Array<Node@> ninjaNodes = gameScene.GetChildrenWithScript("Ninja", true);
+        for (uint i = 0; i < ninjaNodes.length; ++i)
+        {
+            Ninja@ ninja = cast<Ninja>(ninjaNodes[i].scriptObject);
+            if (ninja.side == SIDE_ENEMY)
+                ++numEnemies;
+        }
 
         if (numEnemies < maxEnemies)
         {
@@ -791,9 +801,10 @@ void UpdateControls()
             else
             {
                 // If player has no ninja, respawn if fire/jump is pressed
-                if (players[i].connection.controls.IsPressed(CTRL_FIRE | CTRL_JUMP, players[i].connection.previousControls))
+                if (players[i].connection.controls.IsPressed(CTRL_FIRE | CTRL_JUMP, players[i].lastControls))
                     SpawnPlayer(players[i].connection);
             }
+            players[i].lastControls = players[i].connection.controls;
         }
     }
 }

+ 1 - 0
Bin/Data/Scripts/Player.as

@@ -4,6 +4,7 @@ class Player
     String name;
     uint nodeID;
     Connection@ connection;
+    Controls lastControls;
 
     Player()
     {

+ 3 - 2
Bin/Data/Scripts/SnowBall.as

@@ -42,8 +42,9 @@ class SnowBall : GameObject
         model.drawDistance = snowballDrawDistance;
         model.castShadows = true;
     
-        // Create collision shape
-        CollisionShape@ shape = node.CreateComponent("CollisionShape");
+        // Create collision shape. Create as local to avoid divergent simulation by the client
+        // (as the client does not have the logic scripts that destroy the snowball immediately on collision)
+        CollisionShape@ shape = node.CreateComponent("CollisionShape", LOCAL);
         shape.SetBox(Vector3(15, 15, 15), Vector3(), Quaternion());
         shape.collisionGroup = 1;
         shape.collisionMask = 3;

+ 2 - 2
Docs/Reference.dox

@@ -1049,7 +1049,7 @@ For now, creation and removal of nodes is always sent immediately, without consu
 
 The Controls structure is used to send controls information from the client to the server, by default also at 25 FPS. This includes held down buttons, which is an application-defined 32-bit bitfield, floating point yaw and pitch, and possible extra data (for example the currently selected weapon) stored within a VariantMap.
 
-It is up to the client code to ensure they are kept up-to-date, by calling \ref Connection::SetControls "SetControls()" on the server connection. The event E_NETWORKUPDDATE will be sent to remind of the impending update. The controls can then be inspected on the server side by calling \ref Connection::GetControls "GetControls()". The previous controls are also stored on both ends to allow detecting button state changes.
+It is up to the client code to ensure they are kept up-to-date, by calling \ref Connection::SetControls "SetControls()" on the server connection. The event E_NETWORKUPDDATE will be sent to remind of the impending update. The controls can then be inspected on the server side by calling \ref Connection::GetControls "GetControls()".
 
 The controls update message also includes the client's observer position for interest management.
 
@@ -1365,4 +1365,4 @@ uint       Number of shader variations
 - Inline functions are defined inside the class definitions where possible, without using the inline keyword.
 
 
-*/
+*/

+ 1 - 1
Engine/Container/String.cpp

@@ -84,7 +84,7 @@ String::String(double value) :
     buffer_(&endZero)
 {
     char tempBuffer[CONVERSION_BUFFER_LENGTH];
-    sprintf(tempBuffer, "%Lg", value);
+    sprintf(tempBuffer, "%g", value);
     *this = tempBuffer;
 }
 

+ 1 - 1
Engine/Core/Thread.cpp

@@ -106,6 +106,6 @@ void Thread::SetPriority(int priority)
     #else
     pthread_t* thread = (pthread_t*)handle_;
     if (thread)
-        pthread_setschedprio(thread, priority);
+        pthread_setschedprio(*thread, priority);
     #endif
 }

+ 0 - 1
Engine/Engine/NetworkAPI.cpp

@@ -91,7 +91,6 @@ static void RegisterConnection(asIScriptEngine* engine)
     engine->RegisterObjectMethod("Connection", "bool get_sceneLoaded() const", asMETHOD(Connection, IsSceneLoaded), asCALL_THISCALL);
     engine->RegisterObjectMethod("Connection", "void set_controls(const Controls&in)", asMETHOD(Connection, SetControls), asCALL_THISCALL);
     engine->RegisterObjectMethod("Connection", "const Controls& get_controls() const", asMETHOD(Connection, GetControls), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Connection", "const Controls& get_previousControls() const", asMETHOD(Connection, GetPreviousControls), asCALL_THISCALL);
     engine->RegisterObjectMethod("Connection", "void set_position(const Vector3&in)", asMETHOD(Connection, SetPosition), asCALL_THISCALL);
     engine->RegisterObjectMethod("Connection", "const Vector3& get_position() const", asMETHOD(Connection, GetPosition), asCALL_THISCALL);
     engine->RegisterObjectMethod("Connection", "String get_address() const", asMETHOD(Connection, GetAddress), asCALL_THISCALL);

+ 0 - 1
Engine/Network/Connection.cpp

@@ -191,7 +191,6 @@ void Connection::SetIdentity(const VariantMap& identity)
 
 void Connection::SetControls(const Controls& newControls)
 {
-    previousControls_ = controls_;
     controls_ = newControls;
 }
 

+ 0 - 4
Engine/Network/Connection.h

@@ -142,8 +142,6 @@ public:
     Scene* GetScene() const;
     /// Return the client controls of this connection
     const Controls& GetControls() const { return controls_; }
-    /// Return the previous client controls of this connection
-    const Controls& GetPreviousControls() const { return previousControls_; }
     /// Return the observer position for interest management
     const Vector3& GetPosition() const { return position_; }
     /// Return whether is a client connection
@@ -220,8 +218,6 @@ private:
     VectorBuffer msg_;
     /// Current controls
     Controls controls_;
-    /// Previous controls
-    Controls previousControls_;
     /// Observer position for interest management
     Vector3 position_;
     /// Statistics timer

+ 2 - 2
ThirdParty/kNet/include/kNet/NetworkServer.h

@@ -195,9 +195,9 @@ void NetworkServer::BroadcastStruct(const SerializableData &data, unsigned long
 
 	const size_t dataSize = data.Size();
 
-	for(ConnectionMap::Iterator iter = clientsLock->begin(); iter != clientsLock->end(); ++iter)
+	for(ConnectionMap::Iterator iter = clientsLock->Begin(); iter != clientsLock->End(); ++iter)
 	{
-		MessageConnection *connection = iter->second;
+		MessageConnection *connection = iter->second_;
 		assert(connection);
 		if (connection == exclude || !connection->IsWriteOpen())
 			continue;

+ 7 - 4
ThirdParty/kNet/src/unix/UnixEventArray.cpp

@@ -15,8 +15,11 @@
 /** @file UnixEventArray.cpp
 	@brief */
 
+// Modified by Lasse Öörni for Urho3D
+
 #include <cassert>
 #include <utility>
+#include <algorithm>
 
 #include <sys/time.h>
 #include <sys/types.h>
@@ -39,7 +42,7 @@ EventArray::EventArray()
 
 int EventArray::Size() const
 {
-	return cachedEvents.size();
+	return cachedEvents.Size();
 }
 
 void EventArray::Clear()
@@ -48,7 +51,7 @@ void EventArray::Clear()
 	FD_ZERO(&writefds);
 	nfds = -1;
 	numAdded = 0;
-	cachedEvents.clear();
+	cachedEvents.Clear();
 }
 
 void EventArray::AddEvent(const Event &e)
@@ -76,7 +79,7 @@ void EventArray::AddEvent(const Event &e)
 
 	// No need to add dummy events to select(), but need to add them to the cached events list to keep
 	// the indices matching.
-	cachedEvents.push_back(e);
+	cachedEvents.Push(e);
 	++numAdded;
 }
 
@@ -108,7 +111,7 @@ int EventArray::Wait(int msecs)
 		return WaitFailed;
 	}
 
-	for(int i = 0; i < cachedEvents.size(); ++i)
+	for(int i = 0; i < cachedEvents.Size(); ++i)
 		switch(cachedEvents[i].Type())
 		{
 		case EventWaitRead: