mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Fix netsync of race checkpoints and associated map lines
- Use srb2::MobjList to keep checkpoint objects list
intact after savegame load
- Use std::unordered_map of line tag and vector of line_t
pointers
- Use line tag for the key so multiple checkpoints may
be associated to the same set of lines
This commit is contained in:
parent
f579d25770
commit
e68bb676db
1 changed files with 50 additions and 65 deletions
|
|
@ -9,6 +9,8 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <algorithm>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
|
|
@ -35,8 +37,6 @@
|
|||
#include "../sounds.h"
|
||||
#include "../tables.h"
|
||||
|
||||
using std::vector;
|
||||
using std::pair;
|
||||
using std::min;
|
||||
using std::max;
|
||||
using std::clamp;
|
||||
|
|
@ -45,7 +45,6 @@ extern mobj_t* svg_checkpoints;
|
|||
|
||||
#define checkpoint_id(o) ((o)->thing_args[0])
|
||||
#define checkpoint_linetag(o) ((o)->thing_args[1])
|
||||
#define checkpoint_extralength(o) ((o)->thing_args[2])
|
||||
#define checkpoint_other(o) ((o)->target)
|
||||
#define checkpoint_orb(o) ((o)->tracer)
|
||||
#define checkpoint_arm(o) ((o)->hnext)
|
||||
|
|
@ -132,6 +131,7 @@ struct Checkpoint : mobj_t
|
|||
struct Arm : mobj_t {};
|
||||
|
||||
INT32 id() const { return checkpoint_id(this); }
|
||||
INT32 linetag() const { return checkpoint_linetag(this); }
|
||||
|
||||
Checkpoint* other() const { return static_cast<Checkpoint*>(checkpoint_other(this)); }
|
||||
void other(Checkpoint* n) { P_SetTarget(&checkpoint_other(this), n); }
|
||||
|
|
@ -453,39 +453,16 @@ struct CheckpointManager
|
|||
auto begin() { return list_.begin(); }
|
||||
auto end() { return list_.end(); }
|
||||
|
||||
auto find_checkpoint(INT32 id) {
|
||||
auto it = find_if(list_.begin(), list_.end(), [id](auto pair) { return pair.first->id() == id; });
|
||||
if (it != list_.end())
|
||||
{
|
||||
return it->first;
|
||||
}
|
||||
return static_cast<Checkpoint*>(nullptr);
|
||||
}
|
||||
|
||||
// auto find_pair(Checkpoint* chk) {
|
||||
// pair<Checkpoint*, vector<line_t*>> retpair;
|
||||
// auto it = find_if(list_.begin(), list_.end(), [chk](auto pair) { return pair.first == chk; });
|
||||
// if (it != list_.end())
|
||||
// {
|
||||
// retpair = *it;
|
||||
// return retpair;
|
||||
// }
|
||||
// return static_cast<pair<Checkpoint*, vector<line_t*>>>(nullptr);
|
||||
// }
|
||||
|
||||
void remove_checkpoint(mobj_t* end)
|
||||
{
|
||||
auto chk = static_cast<Checkpoint*>(end);
|
||||
auto it = find_if(list_.begin(), list_.end(), [&](auto pair) { return pair.first == chk; });
|
||||
if (it != list_.end())
|
||||
{
|
||||
list_.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void link_checkpoint(mobj_t* end)
|
||||
auto find_checkpoint(INT32 id)
|
||||
{
|
||||
auto it = std::find_if(begin(), end(), [id](Checkpoint* chk) { return chk->id() == id; });
|
||||
return it != end() ? *it : nullptr;
|
||||
}
|
||||
|
||||
void remove_checkpoint(Checkpoint* end) { list_.erase(end); }
|
||||
|
||||
void link_checkpoint(Checkpoint* chk)
|
||||
{
|
||||
auto chk = static_cast<Checkpoint*>(end);
|
||||
auto id = chk->id();
|
||||
if (chk->spawnpoint && id == 0)
|
||||
{
|
||||
|
|
@ -517,29 +494,39 @@ struct CheckpointManager
|
|||
}
|
||||
else // Checkpoint isn't in the list, find any associated tagged lines and make the pair
|
||||
{
|
||||
vector<line_t*> checklines;
|
||||
if (checkpoint_linetag(chk))
|
||||
{
|
||||
INT32 li;
|
||||
INT32 tag = checkpoint_linetag(chk);
|
||||
TAG_ITER_LINES(tag, li)
|
||||
{
|
||||
line_t* line = lines + li;
|
||||
checklines.push_back(line);
|
||||
}
|
||||
}
|
||||
list_.emplace_back(chk, move(checklines));
|
||||
if (chk->linetag())
|
||||
lines_.try_emplace(chk->linetag(), std::move(tagged_lines(chk->linetag())));
|
||||
list_.push_front(chk);
|
||||
}
|
||||
|
||||
chk->gingerbread();
|
||||
}
|
||||
|
||||
void clear() { list_.clear(); }
|
||||
void clear() { lines_.clear(); }
|
||||
|
||||
auto count() { return list_.size(); }
|
||||
auto count() { return list_.count(); }
|
||||
|
||||
const std::vector<line_t*>* lines_for(const Checkpoint* chk) const
|
||||
{
|
||||
auto it = lines_.find(chk->linetag());
|
||||
return it != lines_.end() ? &it->second : nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
vector<pair<Checkpoint*, vector<line_t*>>> list_;
|
||||
srb2::MobjList<Checkpoint, svg_checkpoints> list_;
|
||||
std::unordered_map<INT32, std::vector<line_t*>> lines_;
|
||||
|
||||
static std::vector<line_t*> tagged_lines(INT32 tag)
|
||||
{
|
||||
std::vector<line_t*> checklines;
|
||||
INT32 li;
|
||||
TAG_ITER_LINES(tag, li)
|
||||
{
|
||||
line_t* line = lines + li;
|
||||
checklines.push_back(line);
|
||||
}
|
||||
return checklines;
|
||||
}
|
||||
};
|
||||
|
||||
CheckpointManager g_checkpoints;
|
||||
|
|
@ -548,13 +535,13 @@ CheckpointManager g_checkpoints;
|
|||
|
||||
void Obj_LinkCheckpoint(mobj_t* end)
|
||||
{
|
||||
g_checkpoints.link_checkpoint(end);
|
||||
g_checkpoints.link_checkpoint(static_cast<Checkpoint*>(end));
|
||||
}
|
||||
|
||||
void Obj_UnlinkCheckpoint(mobj_t* end)
|
||||
{
|
||||
auto chk = static_cast<Checkpoint*>(end);
|
||||
g_checkpoints.remove_checkpoint(end);
|
||||
g_checkpoints.remove_checkpoint(chk);
|
||||
P_RemoveMobj(chk->orb());
|
||||
P_RemoveMobj(chk->arm());
|
||||
}
|
||||
|
|
@ -575,20 +562,20 @@ void __attribute__((optimize("O0"))) Obj_CrossCheckpoints(player_t* player, fixe
|
|||
{
|
||||
LineOnDemand ray(old_x, old_y, player->mo->x, player->mo->y, player->mo->radius);
|
||||
|
||||
auto it = find_if(
|
||||
auto it = std::find_if(
|
||||
g_checkpoints.begin(),
|
||||
g_checkpoints.end(),
|
||||
[&](auto chkpair)
|
||||
[&](Checkpoint* chk)
|
||||
{
|
||||
Checkpoint* chk = chkpair.first;
|
||||
if (!chk->valid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
LineOnDemand* gate;
|
||||
const std::vector<line_t*>* lines = g_checkpoints.lines_for(chk);
|
||||
|
||||
if (chkpair.second.empty())
|
||||
if (!lines || lines->empty())
|
||||
{
|
||||
LineOnDemand dyngate = chk->crossing_line();
|
||||
if (!ray.overlaps(dyngate))
|
||||
|
|
@ -598,15 +585,15 @@ void __attribute__((optimize("O0"))) Obj_CrossCheckpoints(player_t* player, fixe
|
|||
else
|
||||
{
|
||||
auto it = find_if(
|
||||
chkpair.second.begin(),
|
||||
chkpair.second.end(),
|
||||
lines->begin(),
|
||||
lines->end(),
|
||||
[&](const line_t* line)
|
||||
{
|
||||
return ray.overlaps(*line);
|
||||
}
|
||||
);
|
||||
|
||||
if (it == chkpair.second.end())
|
||||
if (it == lines->end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -640,7 +627,7 @@ void __attribute__((optimize("O0"))) Obj_CrossCheckpoints(player_t* player, fixe
|
|||
return;
|
||||
}
|
||||
|
||||
Checkpoint* chk = it->first;
|
||||
Checkpoint* chk = *it;
|
||||
|
||||
if (player->checkpointId == chk->id())
|
||||
{
|
||||
|
|
@ -657,9 +644,8 @@ void __attribute__((optimize("O0"))) Obj_CrossCheckpoints(player_t* player, fixe
|
|||
|
||||
if (gametyperules & GTR_CHECKPOINTS)
|
||||
{
|
||||
for (auto chkpair : g_checkpoints)
|
||||
for (Checkpoint* chk : g_checkpoints)
|
||||
{
|
||||
Checkpoint* chk = chkpair.first;
|
||||
if (chk->valid())
|
||||
{
|
||||
chk->untwirl();
|
||||
|
|
@ -741,13 +727,12 @@ void Obj_ClearCheckpoints()
|
|||
|
||||
void Obj_DeactivateCheckpoints()
|
||||
{
|
||||
for (auto chkpair : g_checkpoints)
|
||||
for (Checkpoint* chk : g_checkpoints)
|
||||
{
|
||||
Checkpoint* chk = chkpair.first;
|
||||
if (chk->valid())
|
||||
{
|
||||
chk->untwirl();
|
||||
chk->other()->untwirl();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue