Print a warning + backtrace when we manually call remove() on an entity that hasn't been destroyed properly.

This commit is contained in:
Marco Cawthorne 2022-11-30 16:47:24 -08:00
parent 15d6e69eeb
commit 74b61f35ed
Signed by: eukara
GPG Key ID: CE2032F0A2882A22
9 changed files with 144 additions and 48 deletions

View File

@ -573,8 +573,9 @@ remove the playback of sounds, skeletal objects and so on.
void
CSQC_Ent_Remove(void)
{
if (self.isCSQC) {
if (self.identity) {
NSEntity me = (NSEntity)self;
me.removed = 1; /* mark this as cleanly removed */
/* we don't want to call Destroy, as that's delayed by a frame...
so we need to call this ourselves */

View File

@ -97,12 +97,11 @@ inet_refreshframe(void)
int count = 0;
int added = 0;
Master_RefreshCache();
/* only rebuild every half a frame */
if (refreshtime > time)
return;
Master_RefreshCache();
count = gethostcachevalue(SLIST_HOSTCACHEVIEWCOUNT);
refreshtime = time + 0.5f;

View File

@ -14,6 +14,8 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
var int g_lanrefresh = FALSE;
CWidget fn_lan;
CMainButton lan_btnJoin;
CMainButton lan_btnCreate;
@ -29,6 +31,59 @@ CListBox lan_lbServers_Game;
CListBox lan_lbServers_Players;
CListBox lan_lbServers_Addresses;
CScrollbar lan_sbServers;
CDialog lan_dgRefresh;
CMainButton lan_btnRefDone;
void
lan_refreshframe(void)
{
static float refreshtime;
int count = 0;
int added = 0;
/* only rebuild every half a frame */
if (refreshtime > time)
return;
refreshtime = time + 0.5f;
Master_RefreshCache();
count = gethostcachevalue(SLIST_HOSTCACHEVIEWCOUNT);
lan_lbServers_Name.Clear();
lan_lbServers_Ping.Clear();
lan_lbServers_Map.Clear();
lan_lbServers_Game.Clear();
lan_lbServers_Players.Clear();
lan_lbServers_Addresses.Clear();
for (int i = 0; i < count; i++) {
string address;
string players;
string ping;
address = gethostcachestring(srv_fldAdress, i);
if (!address || !Server_IsLan(address)) {
continue;
}
players = sprintf("%d/%d",
stof(gethostcachestring(srv_fldPlayers, i)),
stof(gethostcachestring(srv_fldMaxplayers, i))
);
ping = sprintf("%d", stof(gethostcachestring(srv_fldPing, i)));
lan_lbServers_Name.AddEntry(gethostcachestring(srv_fldName, i));
lan_lbServers_Ping.AddEntry(ping);
lan_lbServers_Map.AddEntry(gethostcachestring(srv_fldMap, i));
lan_lbServers_Game.AddEntry(gethostcachestring(srv_fldGame, i));
lan_lbServers_Players.AddEntry(players);
lan_lbServers_Addresses.AddEntry(address);
print(sprintf("Adding %s to the LAN server list\n", address));
added++;
}
print(sprintf("Added %i LAN servers (of %i).\n", added, count));
lan_sbServers.SetMax(added);
}
/* Button Callbacks */
void
@ -78,44 +133,13 @@ lan_btndone_start(void)
void
lan_btnrefresh(void)
{
int count = 0;
int added = 0;
g_lanrefresh = TRUE;
}
Master_RefreshCache();
count = gethostcachevalue(SLIST_HOSTCACHEVIEWCOUNT);
lan_lbServers_Name.Clear();
lan_lbServers_Ping.Clear();
lan_lbServers_Map.Clear();
lan_lbServers_Game.Clear();
lan_lbServers_Players.Clear();
lan_lbServers_Addresses.Clear();
for (int i = 0; i < count; i++) {
string address;
string players;
string ping;
address = gethostcachestring(srv_fldAdress, i);
if (!address || !Server_IsLan(address)) {
continue;
}
players = sprintf("%d/%d",
stof(gethostcachestring(srv_fldPlayers, i)),
stof(gethostcachestring(srv_fldMaxplayers, i))
);
ping = sprintf("%d", stof(gethostcachestring(srv_fldPing, i)));
lan_lbServers_Name.AddEntry(gethostcachestring(srv_fldName, i));
lan_lbServers_Ping.AddEntry(ping);
lan_lbServers_Map.AddEntry(gethostcachestring(srv_fldMap, i));
lan_lbServers_Game.AddEntry(gethostcachestring(srv_fldGame, i));
lan_lbServers_Players.AddEntry(players);
lan_lbServers_Addresses.AddEntry(address);
print(sprintf("Adding %s to the LAN server list\n", address));
added++;
}
print(sprintf("Added %i LAN servers.\n", added));
lan_sbServers.SetMax(added);
void
lan_refreshfinish(void)
{
g_lanrefresh = FALSE;
}
void
@ -218,6 +242,14 @@ menu_langames_init(void)
lan_sbServers.SetCallback(lan_lb_changed);
//xlan_sbServers.SetMax(g_resolutions.length);
Widget_Add(fn_lan, lan_sbServers);
lan_dgRefresh = spawn(CDialog);
lan_btnRefDone = spawn(CMainButton);
lan_btnRefDone.SetImage(BTN_DONE);
lan_btnRefDone.SetPos(233,291);
lan_btnRefDone.SetLength(68);
lan_btnRefDone.SetExecute(lan_refreshfinish);
Widget_Add(lan_dgRefresh, lan_btnRefDone);
}
void
@ -238,10 +270,26 @@ menu_langames_draw(void)
1.0f, 0, font_arial);
WLabel_Static(572, 128, m_reslbl[IDS_SERVER_PLAYERS], 10, 10, [1,1,1],
1.0f, 0, font_arial);
if (!g_lanrefresh)
return;
lan_refreshframe();
lan_dgRefresh.Draw();
Widget_Draw(lan_dgRefresh);
WField_Static(162, 180, "Refreshing LAN server list...", 320, 260,
col_prompt_text, 1.0f, 2, font_label_p);
WField_Static(162, 220, sprintf("Listing %i applicable servers\n",
Master_GetLANServers()), 320, 260,
col_prompt_title, 1.0f, 2, font_label_p);
}
void
menu_langames_input(float evtype, float scanx, float chary, float devid)
{
Widget_Input(fn_lan, evtype, scanx, chary, devid);
if (!g_lanrefresh) {
Widget_Input(fn_lan, evtype, scanx, chary, devid);
} else {
Widget_Input(lan_dgRefresh, evtype, scanx, chary, devid);
}
}

View File

@ -34,6 +34,8 @@ int Master_GetTotalServers(void);
/* returns the amount of internet games */
int Master_GetInternetServers(void);
int Master_GetLANServers(void);
/* get completely new list of servers, hard-reset the cache */
void Master_UpdateCache(void);

View File

@ -42,6 +42,28 @@ Master_GetTotalServers(void)
return gethostcachevalue(SLIST_HOSTCACHETOTALCOUNT);
}
int
Master_GetLANServers(void)
{
int count = 0;
int tcount = 0;
count = gethostcachevalue(SLIST_HOSTCACHEVIEWCOUNT);
for (int i = 0; i < count; i++) {
string address;
address = gethostcachestring(srv_fldAdress, i);
/* skip LAN */
if (!address || !Server_IsLan(address)) {
continue;
}
tcount++;
}
return tcount;
}
int
Master_GetInternetServers(void)
{
@ -112,7 +134,7 @@ Master_ResortCache(void)
void
Master_GetInternetList(void)
{
/*string url = sprintf("%s:%d",MASTER_DNS,MASTER_PORT);
string url = sprintf("%s:%d",MASTER_DNS,MASTER_PORT);
localcmd("net_master1 \"localhost\"\n");
localcmd("net_master2 \"\"\n");
localcmd("net_master3 \"\"\n");
@ -128,7 +150,7 @@ Master_GetInternetList(void)
localcmd("net_masterextra5 \"\"\n");
localcmd("net_masterextra6 \"\"\n");
localcmd("net_masterextra7 \"\"\n");
localcmd("net_masterextra8 \"\"\n");*/
localcmd("net_masterextra8 \"\"\n");
Master_UpdateCache();
}
@ -136,7 +158,7 @@ Master_GetInternetList(void)
void
Master_GetLANList(void)
{
/*localcmd("net_master1 \"localhost\"\n");
localcmd("net_master1 \"localhost\"\n");
localcmd("net_master2 \"\"\n");
localcmd("net_master3 \"\"\n");
localcmd("net_master4 \"\"\n");
@ -151,7 +173,7 @@ Master_GetLANList(void)
localcmd("net_masterextra5 \"\"\n");
localcmd("net_masterextra6 \"\"\n");
localcmd("net_masterextra7 \"\"\n");
localcmd("net_masterextra8 \"\"\n");*/
localcmd("net_masterextra8 \"\"\n");
Master_UpdateCache();
}

View File

@ -120,7 +120,6 @@ entity eActivator;
.entity eUser;
.float material;
.float deaths;
.float identity;
.float botinfo;
/* in idTech the .owner field causes collisions to fail against set entity,

View File

@ -177,6 +177,10 @@ NSClientPlayer::predraw(void)
}
}
if (!p_model) {
p_model = spawn(NSRenderableEntity);
}
/* make sure we're enabling shadow rendering on us! */
effects &= ~EF_NOSHADOW;

View File

@ -22,9 +22,7 @@ client doesn't have to do a whole lot here
============
*/
void NSEntity::NSEntity( void ) {
#ifdef SERVER
identity = 1;
#endif
}
@ -856,6 +854,7 @@ through your own hoops. This however will be sufficient 99,99% of the time.
============
*/
void NSEntity::Destroy( void ) {
removed = 1; /* mark this as cleanly removed */
OnRemoveEntity();
ScheduleThink( Util_Destroy, 0.0f );
}

View File

@ -224,6 +224,28 @@ memalloc(int size)
return prior(size);
}
.float identity;
.float removed;
__wrap void
remove(entity target)
{
/* it's an NSEntity sub-class */
if (target.identity) {
NSEntity ent = (NSEntity)target;
/* if we're calling remove() on it and not .Destroy()... it's being uncleanly removed! */
if (ent.removed == 0) {
ent.OnRemoveEntity();
breakpoint();
print(sprintf("^1WARNING: Entity %d of class %s uncleanly removed!\n", num_for_edict(ent), ent.classname));
ent.removed = 1;
}
}
target.removed = 0;
prior(target);
}
void
setorigin_safe(entity target, vector testorg)
{