summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsignde <signde@openttd.org>2004-09-13 22:49:11 +0000
committersignde <signde@openttd.org>2004-09-13 22:49:11 +0000
commitbb2f8d8d1abf3ed4951eea13361d64127e4a6b8c (patch)
tree02ce8b5c8de35962f0c0bf28891aae99421d0ea7
parent9258f81405dd8080737d45fc72b365eac4154749 (diff)
downloadopenttd-bb2f8d8d1abf3ed4951eea13361d64127e4a6b8c.tar.xz
(svn r240) -Fix: desync on subsidy generation
-Fix: sometimes commands got executed to early on some clients -Feature: universal event packets for transmitting subsidys
-rw-r--r--economy.c39
-rw-r--r--economy.h1
-rw-r--r--functions.h3
-rw-r--r--macros.h1
-rw-r--r--misc.c5
-rw-r--r--network.c49
-rw-r--r--network.h4
-rw-r--r--ttd.c2
8 files changed, 91 insertions, 13 deletions
diff --git a/economy.c b/economy.c
index cf23e65fd..68fd142e1 100644
--- a/economy.c
+++ b/economy.c
@@ -11,6 +11,7 @@
#include "economy.h"
#include "industry.h"
#include "town.h"
+#include "network.h"
void UpdatePlayerHouse(Player *p, uint score)
{
@@ -807,11 +808,11 @@ static void FindSubsidyPassengerRoute(FoundRoute *fr)
fr->distance = (uint)-1;
- fr->from = from = DEREF_TOWN(RandomRange(_total_towns));
+ fr->from = from = DEREF_TOWN(InteractiveRandomRange(_total_towns));
if (from->xy == 0 || from->population < 400)
return;
- fr->to = to = DEREF_TOWN(RandomRange(_total_towns));
+ fr->to = to = DEREF_TOWN(InteractiveRandomRange(_total_towns));
if (from==to || to->xy == 0 || to->population < 400 || to->pct_pass_transported > 42)
return;
@@ -826,12 +827,12 @@ static void FindSubsidyCargoRoute(FoundRoute *fr)
fr->distance = (uint)-1;
- fr->from = i = DEREF_INDUSTRY(RandomRange(_total_industries));
+ fr->from = i = DEREF_INDUSTRY(InteractiveRandomRange(_total_industries));
if (i->xy == 0)
return;
// Randomize cargo type
- if (Random()&1 && i->produced_cargo[1] != 0xFF) {
+ if (InteractiveRandom()&1 && i->produced_cargo[1] != 0xFF) {
cargo = i->produced_cargo[1];
trans = i->pct_transported[1];
total = i->total_production[1];
@@ -851,7 +852,7 @@ static void FindSubsidyCargoRoute(FoundRoute *fr)
if (cargo == CT_GOODS || cargo == CT_FOOD) {
// The destination is a town
- Town *t = DEREF_TOWN(RandomRange(_total_towns));
+ Town *t = DEREF_TOWN(InteractiveRandomRange(_total_towns));
// Only want big towns
if (t->xy == 0 || t->population < 900)
@@ -860,7 +861,7 @@ static void FindSubsidyCargoRoute(FoundRoute *fr)
fr->to = t;
} else {
// The destination is an industry
- Industry *i2 = DEREF_INDUSTRY(RandomRange(_total_industries));
+ Industry *i2 = DEREF_INDUSTRY(InteractiveRandomRange(_total_industries));
// The industry must accept the cargo
if (i == i2 || i2->xy == 0 ||
@@ -890,6 +891,25 @@ static bool CheckSubsidyDuplicate(Subsidy *s)
return false;
}
+void RemoteSubsidyAdd(Subsidy *s_new)
+{
+ Subsidy *s;
+ Pair pair;
+
+ // search the first free subsidy
+ for(s=_subsidies; s != endof(_subsidies); s++)
+ if (s->cargo_type == 0xFF)
+ break;
+
+ memcpy(s,s_new,sizeof(Subsidy));
+
+ pair = SetupSubsidyDecodeParam(s, 0);
+ AddNewsItem(STR_2030_SERVICE_SUBSIDY_OFFERED, NEWS_FLAGS(NM_NORMAL, NF_TILE, NT_SUBSIDIES, 0), pair.a, pair.b);
+
+ InvalidateWindow(WC_SUBSIDIES_LIST, 0);
+
+}
+
static void SubsidyMonthlyHandler()
{
Subsidy *s;
@@ -921,8 +941,10 @@ static void SubsidyMonthlyHandler()
}
}
+ if ((_networking) && (!_networking_server)) return;
+
// 25% chance to go on
- if (CHANCE16(1,4)) {
+ if (ICHANCE16(1,4)) {
// Find a free slot
s = _subsidies;
while (s->cargo_type != 0xFF) {
@@ -948,12 +970,13 @@ static void SubsidyMonthlyHandler()
if (!CheckSubsidyDuplicate(s)) {
s->age = 0;
pair = SetupSubsidyDecodeParam(s, 0);
+ if (_networking_server) NetworkSendEvent(NET_EVENT_SUBSIDY,sizeof(Subsidy),s);
AddNewsItem(STR_2030_SERVICE_SUBSIDY_OFFERED, NEWS_FLAGS(NM_NORMAL, NF_TILE, NT_SUBSIDIES, 0), pair.a, pair.b);
modified = true;
break;
}
}
- } while (--n);
+ } while (n--);
}
no_add:;
if (modified)
diff --git a/economy.h b/economy.h
index 690fc61fc..c9c043ff1 100644
--- a/economy.h
+++ b/economy.h
@@ -70,6 +70,7 @@ VARDEF Subsidy _subsidies[MAX_PLAYERS];
Pair SetupSubsidyDecodeParam(Subsidy *s, bool mode);
void DeleteSubsidyWithIndustry(byte index);
void DeleteSubsidyWithStation(byte index);
+void RemoteSubsidyAdd(Subsidy *s_new);
int32 GetTransportedGoodsIncome(uint num_pieces, uint dist, byte transit_days, byte cargo_type);
uint MoveGoodsToStation(uint tile, int w, int h, int type, uint amount);
diff --git a/functions.h b/functions.h
index ab9ec0b4e..7d729c0ee 100644
--- a/functions.h
+++ b/functions.h
@@ -100,6 +100,8 @@ uint RandomRange(uint max);
void InitPlayerRandoms();
uint32 InteractiveRandom(); /* Used for random sequences that are not the same on the other end of the multiplayer link */
+uint InteractiveRandomRange(uint max);
+
void SetDate(uint date);
/* facedraw.c */
void DrawPlayerFace(uint32 face, int color, int x, int y);
@@ -132,6 +134,7 @@ void NetworkListen();
void NetworkInitialize();
void NetworkShutdown();
void NetworkSendCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback);
+void NetworkSendEvent(uint16 type, uint16 data_len, void * data);
void NetworkStartSync(bool fcreset);
void NetworkClose(bool client);
void NetworkSendReadyPacket();
diff --git a/macros.h b/macros.h
index 40c923f7e..6bde10e4a 100644
--- a/macros.h
+++ b/macros.h
@@ -170,6 +170,7 @@ static INLINE int FindFirstBit2x64(int value)
#define CHANCE16(a,b) ((uint16)Random() <= (uint16)((65536 * a) / b))
+#define ICHANCE16(a,b) ((uint16)InteractiveRandom() <= (uint16)((65536 * a) / b))
#define CHANCE16R(a,b,r) ((uint16)(r=Random()) <= (uint16)((65536 * a) / b))
#define CHANCE16I(a,b,v) ((uint16)(v) <= (uint16)((65536 * a) / b))
diff --git a/misc.c b/misc.c
index dcaf494db..b353c5e27 100644
--- a/misc.c
+++ b/misc.c
@@ -44,6 +44,11 @@ uint32 InteractiveRandom()
return _random_seeds[1][1] = ROR(s, 3);
}
+uint InteractiveRandomRange(uint max)
+{
+ return (uint16)InteractiveRandom() * max >> 16;
+}
+
void InitPlayerRandoms()
{
int i;
diff --git a/network.c b/network.c
index 5ec84508f..6d7cadab8 100644
--- a/network.c
+++ b/network.c
@@ -4,6 +4,7 @@
#include "command.h"
#include "player.h"
#include "console.h"
+#include "economy.h"
#if defined(WIN32)
# include <windows.h>
@@ -87,6 +88,7 @@ enum {
PACKET_TYPE_FSYNC,
PACKET_TYPE_XMIT,
PACKET_TYPE_COMMAND,
+ PACKET_TYPE_EVENT,
};
// sent from client -> server whenever the client wants to exec a command.
@@ -102,6 +104,13 @@ typedef struct CommandPacket {
uint32 dp[8];
} CommandPacket;
+typedef struct EventPacket {
+ byte packet_length;
+ byte packet_type;
+ byte event_type;
+ byte data_start;
+} EventPacket;
+
#define COMMAND_PACKET_BASE_SIZE (sizeof(CommandPacket) - 8 * sizeof(uint32))
// sent from server -> client periodically to tell the client about the current tick in the server
@@ -343,9 +352,9 @@ static void QueueClear(CommandQueue *nq)
static int GetNextSyncFrame()
{
uint32 newframe;
- if (_frame_fsync_last == 0) return -1;
- newframe = (_frame_fsync_last + 9);
- if ( (newframe + 4) > _frame_counter_max) return -1;
+ if (_frame_fsync_last == 0) return -5;
+ newframe = (_frame_fsync_last + 16);
+ if ( (newframe + 4) > _frame_counter_max) return -5;
return (_frame_counter_max - newframe);
}
@@ -367,7 +376,7 @@ void NetworkProcessCommands()
if (!(nq->head = qp->next)) nq->last = &nq->head;
if (qp->frame < _frame_counter && _networking_sync) {
- DEBUG(net,0) ("error: !qp->cp.frame < _frame_counter, %d < %d\n", qp->frame, _frame_counter);
+ DEBUG(net,0) ("warning: !qp->cp.frame < _frame_counter, %d < %d [%d]\n", qp->frame, _frame_counter, _frame_counter_srv+4);
}
// run the command
@@ -495,6 +504,25 @@ void NetworkSendCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, Comman
}
}
+void NetworkSendEvent(uint16 type, uint16 data_len, void * data)
+{
+ EventPacket * ep;
+ ClientState *cs;
+
+ // encode the event ... add its data
+ ep=malloc(data_len+sizeof(EventPacket)-1);
+ ep->event_type = type;
+ ep->packet_length = data_len+sizeof(EventPacket)-1;
+ ep->packet_type = PACKET_TYPE_EVENT;
+ memcpy(&ep->data_start,data,data_len);
+
+ // send it to the peers
+ for(cs=_clients; cs->socket != INVALID_SOCKET; cs++) if (!cs->inactive) SendBytes(cs, ep, ep->packet_length);
+
+ // free the temp packet
+ free(ep);
+}
+
// client:
// server sends a command from another player that we should execute.
// put it in the command queue.
@@ -572,6 +600,15 @@ static void HandleCommandPacket(ClientState *cs, CommandPacket *np)
}
}
+static void HandleEventPacket(EventPacket *ep)
+{
+ switch (ep->event_type) {
+ case NET_EVENT_SUBSIDY:
+ RemoteSubsidyAdd((Subsidy *)&ep->data_start);
+ break;
+ }
+}
+
// sent from server -> client periodically to tell the client about the current tick in the server
// and how far the client may progress.
static void HandleSyncPacket(SyncPacket *sp)
@@ -785,6 +822,9 @@ static bool ReadPackets(ClientState *cs)
case PACKET_TYPE_READY:
HandleReadyPacket((ReadyPacket*)packet, cs);
break;
+ case PACKET_TYPE_EVENT:
+ HandleEventPacket((EventPacket*)packet);
+ break;
default:
DEBUG (net,0) ("net: unknown packet type");
}
@@ -1907,6 +1947,7 @@ void NetworkConnect(const char *hostname, int port) {}
void NetworkReceive() {}
void NetworkSend() {}
void NetworkSendCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback) {}
+void NetworkSendEvent(uint16 type, uint16 data_len, void * data) {};
void NetworkProcessCommands() {}
void NetworkStartSync(bool fcreset) {}
void NetworkSendReadyPacket() {}
diff --git a/network.h b/network.h
index df4871ba9..9b8169069 100644
--- a/network.h
+++ b/network.h
@@ -24,6 +24,10 @@ typedef struct NetworkGameList {
struct NetworkGameList * _next;
} NetworkGameList;
+enum {
+ NET_EVENT_SUBSIDY = 0,
+};
+
NetworkGameInfo _network_game;
NetworkGameList * _network_game_list;
diff --git a/ttd.c b/ttd.c
index 2e760e188..88021d6a8 100644
--- a/ttd.c
+++ b/ttd.c
@@ -889,7 +889,7 @@ void StateGameLoop()
// store the random seed to be able to detect out of sync errors
_sync_seed_1 = _random_seeds[0][0];
_sync_seed_2 = _random_seeds[0][1];
- if (_networking) disable_computer=true;
+ if (_networking) disable_computer=true;
if (_savedump_path[0] && (uint)_frame_counter >= _savedump_first && (uint)(_frame_counter -_savedump_first) % _savedump_freq == 0 ) {
char buf[100];