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 <algorithm>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
|
||||||
|
|
@ -35,8 +37,6 @@
|
||||||
#include "../sounds.h"
|
#include "../sounds.h"
|
||||||
#include "../tables.h"
|
#include "../tables.h"
|
||||||
|
|
||||||
using std::vector;
|
|
||||||
using std::pair;
|
|
||||||
using std::min;
|
using std::min;
|
||||||
using std::max;
|
using std::max;
|
||||||
using std::clamp;
|
using std::clamp;
|
||||||
|
|
@ -45,7 +45,6 @@ extern mobj_t* svg_checkpoints;
|
||||||
|
|
||||||
#define checkpoint_id(o) ((o)->thing_args[0])
|
#define checkpoint_id(o) ((o)->thing_args[0])
|
||||||
#define checkpoint_linetag(o) ((o)->thing_args[1])
|
#define checkpoint_linetag(o) ((o)->thing_args[1])
|
||||||
#define checkpoint_extralength(o) ((o)->thing_args[2])
|
|
||||||
#define checkpoint_other(o) ((o)->target)
|
#define checkpoint_other(o) ((o)->target)
|
||||||
#define checkpoint_orb(o) ((o)->tracer)
|
#define checkpoint_orb(o) ((o)->tracer)
|
||||||
#define checkpoint_arm(o) ((o)->hnext)
|
#define checkpoint_arm(o) ((o)->hnext)
|
||||||
|
|
@ -132,6 +131,7 @@ struct Checkpoint : mobj_t
|
||||||
struct Arm : mobj_t {};
|
struct Arm : mobj_t {};
|
||||||
|
|
||||||
INT32 id() const { return checkpoint_id(this); }
|
INT32 id() const { return checkpoint_id(this); }
|
||||||
|
INT32 linetag() const { return checkpoint_linetag(this); }
|
||||||
|
|
||||||
Checkpoint* other() const { return static_cast<Checkpoint*>(checkpoint_other(this)); }
|
Checkpoint* other() const { return static_cast<Checkpoint*>(checkpoint_other(this)); }
|
||||||
void other(Checkpoint* n) { P_SetTarget(&checkpoint_other(this), n); }
|
void other(Checkpoint* n) { P_SetTarget(&checkpoint_other(this), n); }
|
||||||
|
|
@ -453,39 +453,16 @@ struct CheckpointManager
|
||||||
auto begin() { return list_.begin(); }
|
auto begin() { return list_.begin(); }
|
||||||
auto end() { return list_.end(); }
|
auto end() { return list_.end(); }
|
||||||
|
|
||||||
auto find_checkpoint(INT32 id) {
|
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())
|
auto it = std::find_if(begin(), end(), [id](Checkpoint* chk) { return chk->id() == id; });
|
||||||
{
|
return it != end() ? *it : nullptr;
|
||||||
return it->first;
|
}
|
||||||
}
|
|
||||||
return static_cast<Checkpoint*>(nullptr);
|
void remove_checkpoint(Checkpoint* end) { list_.erase(end); }
|
||||||
}
|
|
||||||
|
void link_checkpoint(Checkpoint* chk)
|
||||||
// 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 chk = static_cast<Checkpoint*>(end);
|
|
||||||
auto id = chk->id();
|
auto id = chk->id();
|
||||||
if (chk->spawnpoint && id == 0)
|
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
|
else // Checkpoint isn't in the list, find any associated tagged lines and make the pair
|
||||||
{
|
{
|
||||||
vector<line_t*> checklines;
|
if (chk->linetag())
|
||||||
if (checkpoint_linetag(chk))
|
lines_.try_emplace(chk->linetag(), std::move(tagged_lines(chk->linetag())));
|
||||||
{
|
list_.push_front(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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
chk->gingerbread();
|
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:
|
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;
|
CheckpointManager g_checkpoints;
|
||||||
|
|
@ -548,13 +535,13 @@ CheckpointManager g_checkpoints;
|
||||||
|
|
||||||
void Obj_LinkCheckpoint(mobj_t* end)
|
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)
|
void Obj_UnlinkCheckpoint(mobj_t* end)
|
||||||
{
|
{
|
||||||
auto chk = static_cast<Checkpoint*>(end);
|
auto chk = static_cast<Checkpoint*>(end);
|
||||||
g_checkpoints.remove_checkpoint(end);
|
g_checkpoints.remove_checkpoint(chk);
|
||||||
P_RemoveMobj(chk->orb());
|
P_RemoveMobj(chk->orb());
|
||||||
P_RemoveMobj(chk->arm());
|
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);
|
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.begin(),
|
||||||
g_checkpoints.end(),
|
g_checkpoints.end(),
|
||||||
[&](auto chkpair)
|
[&](Checkpoint* chk)
|
||||||
{
|
{
|
||||||
Checkpoint* chk = chkpair.first;
|
|
||||||
if (!chk->valid())
|
if (!chk->valid())
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
LineOnDemand* gate;
|
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();
|
LineOnDemand dyngate = chk->crossing_line();
|
||||||
if (!ray.overlaps(dyngate))
|
if (!ray.overlaps(dyngate))
|
||||||
|
|
@ -598,15 +585,15 @@ void __attribute__((optimize("O0"))) Obj_CrossCheckpoints(player_t* player, fixe
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto it = find_if(
|
auto it = find_if(
|
||||||
chkpair.second.begin(),
|
lines->begin(),
|
||||||
chkpair.second.end(),
|
lines->end(),
|
||||||
[&](const line_t* line)
|
[&](const line_t* line)
|
||||||
{
|
{
|
||||||
return ray.overlaps(*line);
|
return ray.overlaps(*line);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
if (it == chkpair.second.end())
|
if (it == lines->end())
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -640,7 +627,7 @@ void __attribute__((optimize("O0"))) Obj_CrossCheckpoints(player_t* player, fixe
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Checkpoint* chk = it->first;
|
Checkpoint* chk = *it;
|
||||||
|
|
||||||
if (player->checkpointId == chk->id())
|
if (player->checkpointId == chk->id())
|
||||||
{
|
{
|
||||||
|
|
@ -657,9 +644,8 @@ void __attribute__((optimize("O0"))) Obj_CrossCheckpoints(player_t* player, fixe
|
||||||
|
|
||||||
if (gametyperules & GTR_CHECKPOINTS)
|
if (gametyperules & GTR_CHECKPOINTS)
|
||||||
{
|
{
|
||||||
for (auto chkpair : g_checkpoints)
|
for (Checkpoint* chk : g_checkpoints)
|
||||||
{
|
{
|
||||||
Checkpoint* chk = chkpair.first;
|
|
||||||
if (chk->valid())
|
if (chk->valid())
|
||||||
{
|
{
|
||||||
chk->untwirl();
|
chk->untwirl();
|
||||||
|
|
@ -741,13 +727,12 @@ void Obj_ClearCheckpoints()
|
||||||
|
|
||||||
void Obj_DeactivateCheckpoints()
|
void Obj_DeactivateCheckpoints()
|
||||||
{
|
{
|
||||||
for (auto chkpair : g_checkpoints)
|
for (Checkpoint* chk : g_checkpoints)
|
||||||
{
|
{
|
||||||
Checkpoint* chk = chkpair.first;
|
|
||||||
if (chk->valid())
|
if (chk->valid())
|
||||||
{
|
{
|
||||||
chk->untwirl();
|
chk->untwirl();
|
||||||
chk->other()->untwirl();
|
chk->other()->untwirl();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue