Share online membership and game setup with the server
Profile, member join/leave and building a fresh game move into the sim library, and the packet reader and writer into protocol.h, so the server can run lobbies exactly as clients do. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
465f75f6d7
commit
9613e85706
7 files changed
+181
-105
No files matched your search
@@ -1,6 +1,7 @@
|
||||
#include "match.h"
|
||||
#include "sim.h"
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
constexpr Burst FINISH_BURST = {.gravity = 200, .life = 1, .size = 3, .speed = 240, .count = 40};
|
||||
constexpr float RACE_GRACE = 15;
|
||||
@@ -746,3 +747,80 @@ void Match::leaves_take(Sim& sim)
|
||||
std::fill(std::begin(isReady), std::end(isReady), false);
|
||||
sim.cues->sound_play(SOUND_FINISH);
|
||||
}
|
||||
|
||||
// A fighter's loadout, slots and levels as a profile, to bring it back as it was (a name and colour are added by whoever
|
||||
// knows them).
|
||||
Profile profile_get(Fighter& fighter)
|
||||
{
|
||||
Profile profile;
|
||||
profile.weaponSlots = fighter.weaponSlots;
|
||||
profile.trinketSlots = fighter.trinketSlots;
|
||||
std::copy(std::begin(fighter.weaponLoadout), std::end(fighter.weaponLoadout), profile.weaponLoadout);
|
||||
std::copy(std::begin(fighter.trinketLoadout), std::end(fighter.trinketLoadout), profile.trinketLoadout);
|
||||
std::copy(std::begin(fighter.weaponSlotLevels), std::end(fighter.weaponSlotLevels), profile.weaponSlotLevels);
|
||||
std::copy(std::begin(fighter.trinketSlotLevels), std::end(fighter.trinketSlotLevels), profile.trinketSlotLevels);
|
||||
std::copy(std::begin(fighter.weaponItemLevels), std::end(fighter.weaponItemLevels), profile.weaponItemLevels);
|
||||
std::copy(std::begin(fighter.trinketItemLevels), std::end(fighter.trinketItemLevels), profile.trinketItemLevels);
|
||||
return profile;
|
||||
}
|
||||
|
||||
// Online, a member's fighter appears, set up from their profile, in the colour they asked for if it's free. Returns
|
||||
// it, or -1 when the game is full.
|
||||
int Match::member_join(Sim& sim, int member, const Profile& profile)
|
||||
{
|
||||
if (sim.fighterCount >= MAX_FIGHTERS)
|
||||
return -1;
|
||||
int index = sim.fighterCount++;
|
||||
Fighter& fighter = sim.fighters[index];
|
||||
fighter = Fighter{};
|
||||
fighter.init(sim, index);
|
||||
fighter.slots_set(std::clamp(profile.weaponSlots, 1, SLOT_MAX), std::clamp(profile.trinketSlots, 1, SLOT_MAX));
|
||||
std::copy(std::begin(profile.weaponLoadout), std::end(profile.weaponLoadout), fighter.weaponLoadout);
|
||||
std::copy(std::begin(profile.trinketLoadout), std::end(profile.trinketLoadout), fighter.trinketLoadout);
|
||||
std::copy(std::begin(profile.weaponSlotLevels), std::end(profile.weaponSlotLevels), fighter.weaponSlotLevels);
|
||||
std::copy(std::begin(profile.trinketSlotLevels), std::end(profile.trinketSlotLevels), fighter.trinketSlotLevels);
|
||||
std::copy(std::begin(profile.weaponItemLevels), std::end(profile.weaponItemLevels), fighter.weaponItemLevels);
|
||||
std::copy(std::begin(profile.trinketItemLevels), std::end(profile.trinketItemLevels), fighter.trinketItemLevels);
|
||||
owners[index] = member;
|
||||
std::memcpy(names[index], profile.name, sizeof(names[index]));
|
||||
names[index][PLAYER_NAME_MAX] = '\0';
|
||||
bool isTaken[COLOR_COUNT] = {};
|
||||
for (int i = 0; i < index; i++)
|
||||
isTaken[colors[i]] = true;
|
||||
bool isFree = profile.color >= 0 && profile.color < COLOR_COUNT && !isTaken[profile.color];
|
||||
colors[index] = isFree ? profile.color : (std::find(isTaken, isTaken + COLOR_COUNT, false) - isTaken) % COLOR_COUNT;
|
||||
return index;
|
||||
}
|
||||
|
||||
// Online, a member's fighter goes with its attacks, and the fighters after it move down a place.
|
||||
void Match::member_leave(Sim& sim, int member)
|
||||
{
|
||||
int index = fighter_find(sim, member);
|
||||
if (index < 0)
|
||||
return;
|
||||
std::vector<Attack>& attacks = sim.weapons.attacks;
|
||||
std::erase_if(attacks, [&](Attack& attack) { return attack.owner == index; });
|
||||
for (Attack& attack : attacks)
|
||||
attack.owner -= attack.owner > index;
|
||||
for (int i = index; i + 1 < sim.fighterCount; i++)
|
||||
{
|
||||
sim.fighters[i] = sim.fighters[i + 1];
|
||||
sim.fighters[i].index = i;
|
||||
sim.bot.states[i] = sim.bot.states[i + 1];
|
||||
owners[i] = owners[i + 1];
|
||||
colors[i] = colors[i + 1];
|
||||
std::memcpy(names[i], names[i + 1], sizeof(names[i]));
|
||||
}
|
||||
queue_slots_shift(index, sim.fighterCount);
|
||||
sim.fighterCount--;
|
||||
owners[sim.fighterCount] = -1;
|
||||
}
|
||||
|
||||
// Which fighter a member plays, or -1 for none.
|
||||
int Match::fighter_find(Sim& sim, int member)
|
||||
{
|
||||
for (int i = 0; i < sim.fighterCount; i++)
|
||||
if (owners[i] == member)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
Reference in new issue
Block a user