Skip to content

Commit abe8de4

Browse files
committed
bm: better fix for wall breaking. Fix release of bomb-up items
Send intact wall (all FF) to game as soon as it signals the end of game. Allocate even bomb slots first to work around a game bug at release time. Keep server assigned bomb slot on bomb-up power ups. Transition from Visible/Appearing to Broken allowed but final state.
1 parent 9651f84 commit abe8de4

5 files changed

Lines changed: 73 additions & 53 deletions

File tree

bm_dissect.cpp

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,6 @@ int main(int argc, char *argv[])
286286
printf("\tP%d %g:%g st %x dir %x\n", i + 1, p1.pos.xpos(), p1.pos.ypos(), p1.status, p1.dir);
287287
}
288288
}
289-
//dumpData(data + 0x10, size - 0x10, " ");
290289
if (timestamp) {
291290
const uint32_t time = read32(data, 0x34);
292291
printf(" TIMESTAMP %x\n", time);
@@ -325,18 +324,9 @@ int main(int argc, char *argv[])
325324
for (int i = 0; i < 28; i++, p += 4)
326325
{
327326
PowerUp pup(data + 0x34 + sizeof(PowerUp) * i);
328-
//if (p[0] != 0 || p[1] != 0 || (p[2] != 0 && p[2] != 0x10) || p[3] != 0)
329327
if (pup.state > 1)
330-
{
331-
// 00 00 20 00
332-
// 00 00 30 00
333-
// 00 00 b1 01
334-
// 00 00 31 01
335328
printf(" POWER-UP[%d]: %d %d state %X slot %d bombUp %d bombSlot %d\n", i, pup.pos.x, pup.pos.y, pup.state,
336329
pup.slot, pup.bombUp, (pup.bombSlotHigh << 2) | pup.bombSlotLow);
337-
//dumpData(data + 0x10, size - 0x10, " ");
338-
//break;
339-
}
340330
}
341331
}
342332
if (brickMap)
@@ -348,7 +338,6 @@ int main(int argc, char *argv[])
348338
if (eogMarker != 0)
349339
printf(" EoG %02x", eogMarker);
350340
printf("\n");
351-
//dumpData(data + 0x10, size - 0x10, " ");
352341
break;
353342

354343
default:

bomberman.cpp

Lines changed: 67 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -483,12 +483,17 @@ void BMRoom::savePowerUps(Player *player, const uint8_t *data)
483483
for (unsigned i = 0; i < powerUps.size(); i++)
484484
{
485485
PowerUp pup(data + i * sizeof(pup));
486+
// The bomb slot is assigned by the server
487+
pup.bombSlotLow = powerUps[i].bombSlotLow;
488+
pup.bombSlotHigh = powerUps[i].bombSlotHigh;
489+
486490
uint16_t curState = powerUps[i].state;
487491
switch (curState)
488492
{
489493
case PowerUp::Hidden:
490494
powerUps[i] = pup;
491495
break;
496+
492497
case PowerUp::Appearing:
493498
if (pup.state == PowerUp::Visible) {
494499
powerUps[i] = pup;
@@ -497,19 +502,30 @@ void BMRoom::savePowerUps(Player *player, const uint8_t *data)
497502
pup.state = PowerUp::Judge;
498503
powerUps[i] = pup;
499504
}
505+
else if (pup.state == PowerUp::Broken) {
506+
DEBUG_LOG(game, "PowerUp[%d] Appearing -> Broken. Slot %d coords %d %d. BombUp %d", i, pup.slot, pup.pos.x, pup.pos.y, pup.bombUp);
507+
powerUps[i] = pup;
508+
}
500509
break;
510+
501511
case PowerUp::Visible:
502512
if (pup.state == PowerUp::Claimed) {
503513
pup.state = PowerUp::Judge;
504514
powerUps[i] = pup;
505515
}
516+
else if (pup.state == PowerUp::Broken) {
517+
DEBUG_LOG(game, "PowerUp[%d] Visible -> Broken. Slot %d coords %d %d. BombUp %d", i, pup.slot, pup.pos.x, pup.pos.y, pup.bombUp);
518+
powerUps[i] = pup;
519+
}
506520
break;
521+
507522
case PowerUp::Broken:
508523
if (pup.state == PowerUp::Claimed)
509524
DEBUG_LOG(game, "Can't claim a broken item");
510-
else if (pup.state == PowerUp::None)
511-
powerUps[i] = pup;
525+
else if (pup.state != powerUps[i].state)
526+
DEBUG_LOG(game, "PowerUp[%d] Broken -> %d. Slot %d coords %d %d. BombUp %d (ignored)", i, pup.slot, pup.pos.x, pup.pos.y, pup.bombUp);
512527
break;
528+
513529
case PowerUp::Owned: // Picked up by a player
514530
if (pup.slot == powerUps[i].slot)
515531
{
@@ -522,7 +538,8 @@ void BMRoom::savePowerUps(Player *player, const uint8_t *data)
522538
// Item has been lost. Happens when a player dies and releases his items
523539
pup.state = PowerUp::Lost;
524540
powerUps[i] = pup;
525-
DEBUG_LOG(game, "PowerUp[%d] Owned -> Released (Lost). Slot %d coords %d %d", i, pup.slot, pup.pos.x, pup.pos.y);
541+
DEBUG_LOG(game, "PowerUp[%d] Owned -> Released (Lost). Slot %d coords %d %d. BombUp %d bombSlot %d", i, pup.slot, pup.pos.x, pup.pos.y, pup.bombUp,
542+
(pup.bombSlotHigh << 2) | pup.bombSlotLow);
526543
if (pup.bombUp == 1)
527544
releaseBombSlot(pup.slot, i);
528545
}
@@ -536,42 +553,44 @@ void BMRoom::savePowerUps(Player *player, const uint8_t *data)
536553
break;
537554

538555
case PowerUp::Judge:
556+
if (pup.state == PowerUp::Claimed
557+
&& pup.slot == powerUps[i].slot)
539558
{
540-
if (pup.state == PowerUp::Claimed
541-
&& pup.slot == powerUps[i].slot)
559+
DEBUG_LOG(game, "PowerUp[%d] Judge -> Granted. pos %d %d slot %d unk %02x", i, pup.pos.x, pup.pos.y, pup.slot, pup.param & 0xff);
560+
pup.state = PowerUp::Granted;
561+
if (pup.bombUp == 1)
542562
{
543-
DEBUG_LOG(game, "PowerUp[%d] Judge -> Granted. pos %d %d slot %d unk %02x", i, pup.pos.x, pup.pos.y, pup.slot, pup.param & 0xff);
544-
pup.state = PowerUp::Granted;
545-
if (pup.bombUp == 1)
546-
{
547-
// Bomb-up item -> assign bomb slot for new bomb
548-
int idx = assignBombSlot(pup.slot, i);
549-
pup.bombSlotLow = idx & 3;
550-
pup.bombSlotHigh = idx >> 2;
551-
}
552-
powerUps[i] = pup;
563+
// Bomb-up item -> assign bomb slot for new bomb
564+
int idx = assignBombSlot(pup.slot, i);
565+
pup.bombSlotLow = idx & 3;
566+
pup.bombSlotHigh = idx >> 2;
553567
}
554-
break;
568+
powerUps[i] = pup;
555569
}
570+
break;
556571

557572
case PowerUp::Granted: // Granted to a player by the server
558-
if (pup.state == PowerUp::Owned && pup.slot == powerUps[i].slot)
573+
if (pup.state == PowerUp::Owned && pup.slot == powerUps[i].slot) {
574+
pup.bombUp = powerUps[i].bombUp;
559575
powerUps[i] = pup;
576+
}
560577
else if (pup.state != powerUps[i].state
561578
&& pup.state != PowerUp::Visible
562579
&& pup.state != PowerUp::Claimed
563580
&& pup.state != 9 // TODO what is this?
564-
&& pup.slot == powerUps[i].slot)
581+
&& pup.slot == powerUps[i].slot) {
565582
WARN_LOG(game, "PowerUp[%d] current state not handled: Granted -> %x", i, pup.state);
583+
}
566584
break;
567585

568586
case PowerUp::Lost:
569587
if ((pup.state == PowerUp::Appearing || pup.state == PowerUp::Visible)
570588
&& pup.slot == powerUps[i].slot)
589+
{
590+
pup.bombSlotLow = 0;
591+
pup.bombSlotHigh = 0;
571592
powerUps[i] = pup;
572-
else if (pup.state != PowerUp::Lost && pup.slot == powerUps[i].slot)
573-
// Happens after player has died: owned -> released -> (lost) -> owned -> released... visual effect?
574-
powerUps[i] = pup;
593+
}
575594
break;
576595

577596
default:
@@ -667,7 +686,7 @@ void BMRoom::writePlayersPos(Packet& packet)
667686
void BMRoom::processBombData(Player *player, const uint8_t *data, Packet& reply, Packet& relay)
668687
{
669688
State *state = getPlayerState(player);
670-
if (state != nullptr && state->status == State::GameEnding)
689+
if (state == nullptr || state->status == State::GameEnded)
671690
return;
672691
const uint32_t clientTime = read32(data, 0x34);
673692
if (clientTime > lastClientTime) {
@@ -677,7 +696,7 @@ void BMRoom::processBombData(Player *player, const uint8_t *data, Packet& reply,
677696
savePlayerCoords(player, data + 0x14);
678697
saveBombState(player, data + 0x38, clientTime);
679698
saveBrickMap(player, data + 0xC8);
680-
makeCmd1Packet(player, reply, lastClientTime);
699+
makeCmd1Packet(player, reply, lastClientTime, data[0x13] != 0 || state->status != State::InGame);
681700
if (checkEndOfGame(player, BMCmd::BOMB_DATA, data[0x13]))
682701
{
683702
player->send(reply);
@@ -689,12 +708,12 @@ void BMRoom::processBombData(Player *player, const uint8_t *data, Packet& reply,
689708
void BMRoom::processMapData(Player *player, const uint8_t *data, Packet& reply, Packet& relay)
690709
{
691710
State *state = getPlayerState(player);
692-
if (state != nullptr && state->status == State::GameEnding)
711+
if (state == nullptr || state->status == State::GameEnded)
693712
return;
694713
savePlayerCoords(player, data + 0x14);
695714
savePowerUps(player, data + 0x34);
696715
saveBrickMap(player, data + 0xA4);
697-
makeCmd2Packet(reply);
716+
makeCmd2Packet(reply, data[0x13] != 0 || state->status != State::InGame);
698717
if (checkEndOfGame(player, BMCmd::MAP_DATA, data[0x13]))
699718
{
700719
player->send(reply);
@@ -718,7 +737,7 @@ void BMRoom::processPosData(Player *player, const uint8_t *data, Packet& reply,
718737
}
719738
}
720739

721-
void BMRoom::makeCmd1Packet(Player *player, Packet& packet, uint32_t stateTime)
740+
void BMRoom::makeCmd1Packet(Player *player, Packet& packet, uint32_t stateTime, bool endOfGame)
722741
{
723742
packet.init(Packet::REQ_CHAT);
724743
BMCmd cmd { BMCmd::BOMB_DATA, 0xC8 };
@@ -728,10 +747,14 @@ void BMRoom::makeCmd1Packet(Player *player, Packet& packet, uint32_t stateTime)
728747
packet.writeData(stateTime);
729748
for (const Bomb& bomb : bombs)
730749
bomb.writeTo(packet.advance(sizeof(Bomb)));
731-
packet.writeData(brickMap.data(), brickMap.size());
750+
if (endOfGame)
751+
// Send an intact wall to prevent immediate destruction in the next game
752+
memset(packet.advance(brickMap.size()), 0xff, brickMap.size());
753+
else
754+
packet.writeData(brickMap.data(), brickMap.size());
732755
}
733756

734-
void BMRoom::makeCmd2Packet(Packet& packet)
757+
void BMRoom::makeCmd2Packet(Packet& packet, bool endOfGame)
735758
{
736759
packet.init(Packet::REQ_CHAT);
737760
BMCmd cmd { BMCmd::MAP_DATA, 0xA4 };
@@ -740,7 +763,11 @@ void BMRoom::makeCmd2Packet(Packet& packet)
740763
writePlayersPos(packet);
741764
for (const PowerUp& pup : powerUps)
742765
pup.writeTo(packet.advance(sizeof(PowerUp)));
743-
packet.writeData(brickMap.data(), brickMap.size());
766+
if (endOfGame)
767+
// Send an intact wall to prevent immediate destruction in the next game
768+
memset(packet.advance(brickMap.size()), 0xff, brickMap.size());
769+
else
770+
packet.writeData(brickMap.data(), brickMap.size());
744771
}
745772

746773
void BMRoom::makeCmd3Packet(Packet& packet)
@@ -791,15 +818,18 @@ void BMRoom::saveMapInfo(Player *player, const uint8_t *data, bool last)
791818

792819
int BMRoom::assignBombSlot(int slot, int powerUpIdx)
793820
{
794-
for (unsigned i = 0; i < bombSlots.size(); i++)
795-
{
796-
if (bombSlots[i].first == -1)
821+
// A game bug prevents releasing odd slots so start with even ones
822+
for (unsigned start = 0; start < 2; start++)
823+
for (unsigned i = start; i < bombSlots.size(); i += 2)
797824
{
798-
bombSlots[i].first = slot;
799-
bombSlots[i].second = powerUpIdx;
800-
return i;
825+
if (bombSlots[i].first == -1)
826+
{
827+
bombSlots[i].first = slot;
828+
bombSlots[i].second = powerUpIdx;
829+
DEBUG_LOG(game, "Bomb slot %d assigned to player %d powerUp[%d]", i, slot, powerUpIdx);
830+
return i;
831+
}
801832
}
802-
}
803833
WARN_LOG(game, "Can't assign bomb slot to %d: all slot occupied", slot);
804834
return 0;
805835
}
@@ -812,6 +842,7 @@ void BMRoom::releaseBombSlot(int slot, int powerUpIdx)
812842
{
813843
bombSlots[i].first = -1;
814844
bombSlots[i].second = -1;
845+
DEBUG_LOG(game, "Bomb slot %d released from player %d powerUp[%d]", i, slot, powerUpIdx);
815846
return;
816847
}
817848
}

bomberman.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -388,8 +388,8 @@ class BMRoom : public Room
388388
void savePlayerCoords(Player *player, const uint8_t *data);
389389
void savePowerUps(Player *player, const uint8_t *data);
390390
void saveBrickMap(Player *player, const uint8_t *data);
391-
void makeCmd1Packet(Player *player, Packet& packet, uint32_t stateTime);
392-
void makeCmd2Packet(Packet& packet);
391+
void makeCmd1Packet(Player *player, Packet& packet, uint32_t stateTime, bool endOfGame);
392+
void makeCmd2Packet(Packet& packet, bool endOfGame);
393393
void makeCmd3Packet(Packet& packet);
394394
bool checkEndOfGame(Player *player, uint8_t command, uint8_t marker);
395395
void sendEndOfGame(Player *player, Packet& reply, Packet& relay);

kageserver.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ void BootstrapServer::handlePacket(const uint8_t *data, size_t len)
155155
break;
156156

157157
default:
158-
ERROR_LOG(Game::None, "Bootstrap: Unhandled msg type %x", data[3]);
158+
ERROR_LOG(Game::None, "Bootstrap: Unhandled msg type %x from %s", data[3], source.address().to_string().c_str());
159159
break;
160160
}
161161
}

model.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ void Server::read()
180180
// socket.local_endpoint().port(), source.address().to_string().c_str(), source.port());
181181
if (len < 0x14)
182182
{
183-
ERROR_LOG(Game::None, "datagram too small: %zd bytes", len);
183+
ERROR_LOG(Game::None, "[%s] datagram too small: %zd bytes", source.address().to_string().c_str(), len);
184184
read();
185185
return;
186186
}
@@ -189,12 +189,12 @@ void Server::read()
189189
do {
190190
uint16_t pktSize = read16(recvbuf.data(), idx) & 0x3ff;
191191
if (pktSize < 0x10) {
192-
ERROR_LOG(Game::None, "packet too small: %d bytes", pktSize);
192+
ERROR_LOG(Game::None, "[%s] packet too small: %d bytes", source.address().to_string().c_str(), pktSize);
193193
break;
194194
}
195195
// Ack packets have length 0x14 for some reason...
196196
if (pktSize > len - idx && recvbuf[idx + 3] != Packet::REQ_NOP) {
197-
ERROR_LOG(Game::None, "packet truncated: %d bytes > %zd bytes", pktSize, len - idx);
197+
ERROR_LOG(Game::None, "[%s] packet truncated: %d bytes > %zd bytes", source.address().to_string().c_str(), pktSize, len - idx);
198198
break;
199199
}
200200
handlePacket(&recvbuf[idx], pktSize);

0 commit comments

Comments
 (0)