@@ -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)
667686void 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,
689708void 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
746773void BMRoom::makeCmd3Packet (Packet& packet)
@@ -791,15 +818,18 @@ void BMRoom::saveMapInfo(Player *player, const uint8_t *data, bool last)
791818
792819int 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 }
0 commit comments