begin structuring sim for networking
This commit is contained in:
parent
54b1759afe
commit
25a8a3c39a
@ -750,7 +750,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Basic mixing/hashing
|
//~ Basic mixing
|
||||||
|
|
||||||
// Based on Jon Maiga's "mx3"
|
// Based on Jon Maiga's "mx3"
|
||||||
// https://jonkagstrom.com/mx3/mx3_rev2.html
|
// https://jonkagstrom.com/mx3/mx3_rev2.html
|
||||||
@ -768,23 +768,6 @@ Inline u64 MixU64s(u64 seed_a, u64 seed_b)
|
|||||||
return MixU64((seed_a * 3) + seed_b);
|
return MixU64((seed_a * 3) + seed_b);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if IsLanguageC
|
|
||||||
#define Fnv64Basis 0xCBF29CE484222325
|
|
||||||
|
|
||||||
// FNV-1a parameters for different hash sizes:
|
|
||||||
// https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function#FNV_hash_parameters
|
|
||||||
Inline u64 HashFnv64(u64 seed, String str)
|
|
||||||
{
|
|
||||||
u64 hash = seed;
|
|
||||||
for (u64 i = 0; i < str.len; ++i)
|
|
||||||
{
|
|
||||||
hash ^= (u8)str.text[i];
|
|
||||||
hash *= 0x100000001B3;
|
|
||||||
}
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ @hookdecl Core api
|
//~ @hookdecl Core api
|
||||||
|
|
||||||
|
|||||||
@ -58,7 +58,7 @@ void BootstrapCmdline(void)
|
|||||||
{
|
{
|
||||||
CommandlineArg arg = tmp_args[i];
|
CommandlineArg arg = tmp_args[i];
|
||||||
CommandlineArgNode *n = PushStruct(perm, CommandlineArgNode);
|
CommandlineArgNode *n = PushStruct(perm, CommandlineArgNode);
|
||||||
u64 hash = HashFnv64(Fnv64Basis, arg.name);
|
u64 hash = HashString(arg.name);
|
||||||
u64 bin_idx = hash % countof(Base.cmdline.arg_bins);
|
u64 bin_idx = hash % countof(Base.cmdline.arg_bins);
|
||||||
n->arg = arg;
|
n->arg = arg;
|
||||||
n->hash = hash;
|
n->hash = hash;
|
||||||
@ -85,7 +85,7 @@ String StringFromCommandlineIdx(i32 idx)
|
|||||||
CommandlineArg CommandlineArgFromName(String name)
|
CommandlineArg CommandlineArgFromName(String name)
|
||||||
{
|
{
|
||||||
CommandlineArg result = Zi;
|
CommandlineArg result = Zi;
|
||||||
u64 hash = HashFnv64(Fnv64Basis, name);
|
u64 hash = HashString(name);
|
||||||
for (CommandlineArgNode *n = Base.cmdline.arg_bins[hash % countof(Base.cmdline.arg_bins)]; n; n = n->next)
|
for (CommandlineArgNode *n = Base.cmdline.arg_bins[hash % countof(Base.cmdline.arg_bins)]; n; n = n->next)
|
||||||
{
|
{
|
||||||
if (n->hash == hash && MatchString(n->arg.name, name))
|
if (n->hash == hash && MatchString(n->arg.name, name))
|
||||||
|
|||||||
@ -19,6 +19,7 @@ void BootstrapResources(u64 archive_strings_count, String *archive_strings)
|
|||||||
u64 num_entries = BB_ReadUBits(&br, 64);
|
u64 num_entries = BB_ReadUBits(&br, 64);
|
||||||
for (u64 i = 0; i < num_entries; ++i)
|
for (u64 i = 0; i < num_entries; ++i)
|
||||||
{
|
{
|
||||||
|
u64 store_hash = BB_ReadUBits(&br, 64);
|
||||||
u64 name_start = BB_ReadUBits(&br, 64);
|
u64 name_start = BB_ReadUBits(&br, 64);
|
||||||
u64 name_len = BB_ReadUBits(&br, 64);
|
u64 name_len = BB_ReadUBits(&br, 64);
|
||||||
u64 data_start = BB_ReadUBits(&br, 64);
|
u64 data_start = BB_ReadUBits(&br, 64);
|
||||||
@ -27,7 +28,7 @@ void BootstrapResources(u64 archive_strings_count, String *archive_strings)
|
|||||||
ResourceEntry *entry = PushStruct(perm, ResourceEntry);
|
ResourceEntry *entry = PushStruct(perm, ResourceEntry);
|
||||||
entry->name = STRING(name_len, archive.text + name_start);
|
entry->name = STRING(name_len, archive.text + name_start);
|
||||||
entry->data = STRING(data_len, archive.text + data_start);
|
entry->data = STRING(data_len, archive.text + data_start);
|
||||||
entry->hash = HashFnv64(Fnv64Basis, entry->name);
|
entry->hash = HashStringEx(store_hash, entry->name);
|
||||||
|
|
||||||
ResourceEntryBin *bin = &Base.resource.bins[entry->hash % countof(Base.resource.bins)];
|
ResourceEntryBin *bin = &Base.resource.bins[entry->hash % countof(Base.resource.bins)];
|
||||||
SllQueuePushN(bin->first, bin->last, entry, next_in_bin);
|
SllQueuePushN(bin->first, bin->last, entry, next_in_bin);
|
||||||
@ -50,7 +51,7 @@ b32 IsResourceNil(ResourceKey resource)
|
|||||||
ResourceKey ResourceKeyFromStore(ResourceStore *store, String name)
|
ResourceKey ResourceKeyFromStore(ResourceStore *store, String name)
|
||||||
{
|
{
|
||||||
ResourceKey result = Zi;
|
ResourceKey result = Zi;
|
||||||
result.v = HashFnv64(store->v, name);
|
result.v = HashStringEx(store->v, name);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -502,14 +502,21 @@ String PathFromString(Arena *arena, String str, u8 path_delimiter)
|
|||||||
|
|
||||||
u64 HashStringEx(u64 seed, String str)
|
u64 HashStringEx(u64 seed, String str)
|
||||||
{
|
{
|
||||||
u64 result = HashFnv64(seed, str);
|
// FNV-1a parameters for different hash sizes:
|
||||||
|
// https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function#FNV_hash_parameters
|
||||||
|
u64 result = seed + 0xCBF29CE484222325;
|
||||||
|
for (u64 i = 0; i < str.len; ++i)
|
||||||
|
{
|
||||||
|
result ^= (u8)str.text[i];
|
||||||
|
result *= 0x100000001B3;
|
||||||
|
}
|
||||||
result = MixU64(result);
|
result = MixU64(result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 HashString(String str)
|
u64 HashString(String str)
|
||||||
{
|
{
|
||||||
return HashStringEx(Fnv64Basis, str);
|
return HashStringEx(0, str);
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 HashF_(String fmt, ...)
|
u64 HashF_(String fmt, ...)
|
||||||
|
|||||||
@ -112,7 +112,7 @@ i64 TimeNs(void)
|
|||||||
|
|
||||||
void TrueRand(String buffer)
|
void TrueRand(String buffer)
|
||||||
{
|
{
|
||||||
BCryptGenRandom(BCRYPT_RNG_ALG_HANDLE, (u8 *)buffer.text, buffer.len, 0);
|
BCryptGenRandom(BCRYPT_RNG_ALG_HANDLE, buffer.text, buffer.len, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
CpuTopologyInfo GetCpuTopologyInfo(void)
|
CpuTopologyInfo GetCpuTopologyInfo(void)
|
||||||
|
|||||||
@ -111,6 +111,7 @@ EmbedObj Embed(String store_name, String dir_path)
|
|||||||
EmbedObj result = Zi;
|
EmbedObj result = Zi;
|
||||||
|
|
||||||
// Generate resource archive contents
|
// Generate resource archive contents
|
||||||
|
u64 store_hash = HashString(store_name);
|
||||||
String arc_contents = Zi;
|
String arc_contents = Zi;
|
||||||
{
|
{
|
||||||
StringList files = Zi;
|
StringList files = Zi;
|
||||||
@ -136,7 +137,6 @@ EmbedObj Embed(String store_name, String dir_path)
|
|||||||
entry_name.len -= dir_path.len + 1;
|
entry_name.len -= dir_path.len + 1;
|
||||||
entry_name.text += dir_path.len + 1;
|
entry_name.text += dir_path.len + 1;
|
||||||
}
|
}
|
||||||
entry_name = StringF(perm, "%F/%F", FmtString(store_name), FmtString(entry_name));
|
|
||||||
for (u64 i = 0; i < entry_name.len; ++i)
|
for (u64 i = 0; i < entry_name.len; ++i)
|
||||||
{
|
{
|
||||||
if (entry_name.text[i] == '\\')
|
if (entry_name.text[i] == '\\')
|
||||||
@ -165,6 +165,7 @@ EmbedObj Embed(String store_name, String dir_path)
|
|||||||
|
|
||||||
// Reserve entries space
|
// Reserve entries space
|
||||||
u64 entry_size = 0
|
u64 entry_size = 0
|
||||||
|
+ 8 // Store hash
|
||||||
+ 8 // Name start
|
+ 8 // Name start
|
||||||
+ 8 // Name end
|
+ 8 // Name end
|
||||||
+ 8 // Data start
|
+ 8 // Data start
|
||||||
@ -196,6 +197,7 @@ EmbedObj Embed(String store_name, String dir_path)
|
|||||||
u64 data_len = BB_GetNumBytesWritten(&bw) - data_start;
|
u64 data_len = BB_GetNumBytesWritten(&bw) - data_start;
|
||||||
|
|
||||||
// Write entry
|
// Write entry
|
||||||
|
BB_WriteUBits(&entries_bw, store_hash, 64);
|
||||||
BB_WriteUBits(&entries_bw, name_start, 64);
|
BB_WriteUBits(&entries_bw, name_start, 64);
|
||||||
BB_WriteUBits(&entries_bw, name_len, 64);
|
BB_WriteUBits(&entries_bw, name_len, 64);
|
||||||
BB_WriteUBits(&entries_bw, data_start, 64);
|
BB_WriteUBits(&entries_bw, data_start, 64);
|
||||||
@ -457,6 +459,7 @@ void BuildEntryPoint(WaveLaneCtx *lane)
|
|||||||
String shader_store_name = Lit("ShadersStore");
|
String shader_store_name = Lit("ShadersStore");
|
||||||
String c_out_file = F_GetFull(perm, StringF(perm, "%F_gen.c", FmtString(cmdline.leaf_layer_name)));
|
String c_out_file = F_GetFull(perm, StringF(perm, "%F_gen.c", FmtString(cmdline.leaf_layer_name)));
|
||||||
String gpu_out_file = F_GetFull(perm, StringF(perm, "%F_gen.g", FmtString(cmdline.leaf_layer_name)));
|
String gpu_out_file = F_GetFull(perm, StringF(perm, "%F_gen.g", FmtString(cmdline.leaf_layer_name)));
|
||||||
|
u64 shader_store_hash = HashString(shader_store_name);
|
||||||
|
|
||||||
if (lane->idx == 0 && GetBuildStatus() == 0)
|
if (lane->idx == 0 && GetBuildStatus() == 0)
|
||||||
{
|
{
|
||||||
@ -505,8 +508,8 @@ void BuildEntryPoint(WaveLaneCtx *lane)
|
|||||||
String full = F_GetFullCrossPlatform(perm, StringF(perm, "%F/%F", FmtString(token_parent_dir), FmtString(arg_dir)));
|
String full = F_GetFullCrossPlatform(perm, StringF(perm, "%F/%F", FmtString(token_parent_dir), FmtString(arg_dir)));
|
||||||
if (F_IsDir(full))
|
if (F_IsDir(full))
|
||||||
{
|
{
|
||||||
u64 hash = HashFnv64(Fnv64Basis, StringF(perm, "%F/", FmtString(store_name)));
|
u64 store_hash = HashString(store_name);
|
||||||
String line = StringF(perm, "ResourceStore %F = { 0x%F };", FmtString(store_name), FmtHex(hash));
|
String line = StringF(perm, "ResourceStore %F = { 0x%F };", FmtString(store_name), FmtHex(store_hash));
|
||||||
PushStringToList(perm, &c_store_lines, line);
|
PushStringToList(perm, &c_store_lines, line);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -531,8 +534,8 @@ void BuildEntryPoint(WaveLaneCtx *lane)
|
|||||||
: kind == M_EntryKind_ComputeShader ? Lit("ComputeShader")
|
: kind == M_EntryKind_ComputeShader ? Lit("ComputeShader")
|
||||||
: Lit("");
|
: Lit("");
|
||||||
String shader_name = arg0_tok->s;
|
String shader_name = arg0_tok->s;
|
||||||
u64 hash = HashFnv64(Fnv64Basis, StringF(perm, "%F/%F", FmtString(shader_store_name), FmtString(shader_name)));
|
u64 shader_resource_hash = HashStringEx(shader_store_hash, shader_name);
|
||||||
String line = StringF(perm, "%F %F = { 0x%F };", FmtString(shader_type), FmtString(shader_name), FmtHex(hash));
|
String line = StringF(perm, "%F %F = { 0x%F };", FmtString(shader_type), FmtString(shader_name), FmtHex(shader_resource_hash));
|
||||||
PushStringToList(perm, &c_shader_lines, line);
|
PushStringToList(perm, &c_shader_lines, line);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@ -97,7 +97,7 @@ M_TokenFileList M_TokensFromSrcDirs(Arena *arena, StringList src_dirs)
|
|||||||
if (StringEndsWith(file_name, Lit(".lay")))
|
if (StringEndsWith(file_name, Lit(".lay")))
|
||||||
{
|
{
|
||||||
String tmp_full = F_GetFull(scratch.arena, file_name);
|
String tmp_full = F_GetFull(scratch.arena, file_name);
|
||||||
u64 hash = HashFnv64(Fnv64Basis, tmp_full);
|
u64 hash = HashString(tmp_full);
|
||||||
if (DictValueFromHash(dedup_dict, hash) == 0)
|
if (DictValueFromHash(dedup_dict, hash) == 0)
|
||||||
{
|
{
|
||||||
SetDictValue(scratch.arena, dedup_dict, hash, 1);
|
SetDictValue(scratch.arena, dedup_dict, hash, 1);
|
||||||
@ -255,7 +255,7 @@ M_LayerList M_LayersFromTokenFiles(Arena *arena, M_TokenFileList lexed)
|
|||||||
for (u64 i = 0; i < countof(M_entry_kind_rules); ++i)
|
for (u64 i = 0; i < countof(M_entry_kind_rules); ++i)
|
||||||
{
|
{
|
||||||
char *rule_cstr = M_entry_kind_rules[i];
|
char *rule_cstr = M_entry_kind_rules[i];
|
||||||
u64 rule_hash = HashFnv64(Fnv64Basis, StringFromCstrNoLimit(rule_cstr));
|
u64 rule_hash = HashString(StringFromCstrNoLimit(rule_cstr));
|
||||||
SetDictValue(scratch.arena, rules_dict, rule_hash, i + 1);
|
SetDictValue(scratch.arena, rules_dict, rule_hash, i + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -280,7 +280,7 @@ M_LayerList M_LayersFromTokenFiles(Arena *arena, M_TokenFileList lexed)
|
|||||||
{
|
{
|
||||||
M_Entry *entry = M_PushEntry(arena, layer, M_EntryKind_Unknown, entry_token, args_count, arg_tokens);
|
M_Entry *entry = M_PushEntry(arena, layer, M_EntryKind_Unknown, entry_token, args_count, arg_tokens);
|
||||||
{
|
{
|
||||||
u64 entry_hash = HashFnv64(Fnv64Basis, entry_token->s);
|
u64 entry_hash = HashString(entry_token->s);
|
||||||
u64 kind_plus_1 = DictValueFromHash(rules_dict, entry_hash);
|
u64 kind_plus_1 = DictValueFromHash(rules_dict, entry_hash);
|
||||||
if (kind_plus_1 > 0)
|
if (kind_plus_1 > 0)
|
||||||
{
|
{
|
||||||
@ -390,7 +390,7 @@ M_Layer M_FlattenEntries(Arena *arena, M_LayerList unflattened, StringList start
|
|||||||
|
|
||||||
String name = name_entry->arg_tokens[0]->s;
|
String name = name_entry->arg_tokens[0]->s;
|
||||||
|
|
||||||
u64 name_hash = HashFnv64(Fnv64Basis, name);
|
u64 name_hash = HashString(name);
|
||||||
DictEntry *ptr_dict_entry = EnsureDictEntry(scratch.arena, layer_ptr_to_state, (u64)layer);
|
DictEntry *ptr_dict_entry = EnsureDictEntry(scratch.arena, layer_ptr_to_state, (u64)layer);
|
||||||
DictEntry *name_dict_entry = EnsureDictEntry(scratch.arena, layer_name_to_state, name_hash);
|
DictEntry *name_dict_entry = EnsureDictEntry(scratch.arena, layer_name_to_state, name_hash);
|
||||||
|
|
||||||
@ -418,7 +418,7 @@ M_Layer M_FlattenEntries(Arena *arena, M_LayerList unflattened, StringList start
|
|||||||
for (StringListNode *sln = starting_layer_names.first; sln; sln = sln->next)
|
for (StringListNode *sln = starting_layer_names.first; sln; sln = sln->next)
|
||||||
{
|
{
|
||||||
String name = sln->s;
|
String name = sln->s;
|
||||||
u64 name_hash = HashFnv64(Fnv64Basis, name);
|
u64 name_hash = HashString(name);
|
||||||
IterState *state = (IterState *)DictValueOrNilFromHash(layer_name_to_state, name_hash, (u64)&NilIterState);
|
IterState *state = (IterState *)DictValueOrNilFromHash(layer_name_to_state, name_hash, (u64)&NilIterState);
|
||||||
M_Layer *layer = state->layer;
|
M_Layer *layer = state->layer;
|
||||||
if (layer->valid)
|
if (layer->valid)
|
||||||
@ -497,7 +497,7 @@ M_Layer M_FlattenEntries(Arena *arena, M_LayerList unflattened, StringList start
|
|||||||
if (should_include)
|
if (should_include)
|
||||||
{
|
{
|
||||||
String downstream_layer_name = downstream_layer_token->s;
|
String downstream_layer_name = downstream_layer_token->s;
|
||||||
u64 hash = HashFnv64(Fnv64Basis, downstream_layer_name);
|
u64 hash = HashString(downstream_layer_name);
|
||||||
IterState *downstream_layer_state = (IterState *)DictValueOrNilFromHash(layer_name_to_state, hash, (u64)&NilIterState);
|
IterState *downstream_layer_state = (IterState *)DictValueOrNilFromHash(layer_name_to_state, hash, (u64)&NilIterState);
|
||||||
M_Layer *downstream_layer = downstream_layer_state->layer;
|
M_Layer *downstream_layer = downstream_layer_state->layer;
|
||||||
if (downstream_layer->valid)
|
if (downstream_layer->valid)
|
||||||
@ -538,7 +538,7 @@ M_Layer M_FlattenEntries(Arena *arena, M_LayerList unflattened, StringList start
|
|||||||
if (dep_token->valid)
|
if (dep_token->valid)
|
||||||
{
|
{
|
||||||
String dep_name = dep_token->s;
|
String dep_name = dep_token->s;
|
||||||
u64 hash = HashFnv64(Fnv64Basis, dep_name);
|
u64 hash = HashString(dep_name);
|
||||||
IterState *dep_layer_state = (IterState *)DictValueOrNilFromHash(layer_name_to_state, hash, (u64)&NilIterState);
|
IterState *dep_layer_state = (IterState *)DictValueOrNilFromHash(layer_name_to_state, hash, (u64)&NilIterState);
|
||||||
M_Layer *dep_layer = dep_layer_state->layer;
|
M_Layer *dep_layer = dep_layer_state->layer;
|
||||||
if (dep_layer->valid)
|
if (dep_layer->valid)
|
||||||
|
|||||||
@ -58,7 +58,7 @@ void N_ReleaseHost(N_Host *host)
|
|||||||
|
|
||||||
u64 N_HashFromAddress(PLT_Address address)
|
u64 N_HashFromAddress(PLT_Address address)
|
||||||
{
|
{
|
||||||
return HashFnv64(Fnv64Basis, StringFromStruct(&address));
|
return HashString(StringFromStruct(&address));
|
||||||
}
|
}
|
||||||
|
|
||||||
N_Channel *N_ChannelFromAddress(N_Host *host, PLT_Address address)
|
N_Channel *N_ChannelFromAddress(N_Host *host, PLT_Address address)
|
||||||
@ -227,9 +227,9 @@ void N_ReleaseChannel(N_Channel *channel)
|
|||||||
|
|
||||||
u64 N_HashFromMsg(N_ChannelId channel_id, u64 msg_id)
|
u64 N_HashFromMsg(N_ChannelId channel_id, u64 msg_id)
|
||||||
{
|
{
|
||||||
u64 result = Fnv64Basis;
|
u64 result = 0;
|
||||||
result = HashFnv64(result, StringFromStruct(&channel_id));
|
result = HashStringEx(result, StringFromStruct(&channel_id));
|
||||||
result = HashFnv64(result, StringFromStruct(&msg_id));
|
result = HashStringEx(result, StringFromStruct(&msg_id));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
418
src/pp/pp.c
418
src/pp/pp.c
@ -6,6 +6,10 @@ Readonly P_Ent P_NilEnt = {
|
|||||||
.look = { 0, -1 },
|
.look = { 0, -1 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Readonly P_Frame P_NilFrame = {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Bootstrap
|
//~ Bootstrap
|
||||||
|
|
||||||
@ -37,14 +41,19 @@ b32 P_IsEntNil(P_Ent *ent)
|
|||||||
return ent == 0 || ent == &P_NilEnt;
|
return ent == 0 || ent == &P_NilEnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
b32 P_MatchKey(P_Key a, P_Key b)
|
b32 P_IsFrameNil(P_Frame *frame)
|
||||||
{
|
{
|
||||||
return a.v == b.v;
|
return frame == 0 || frame == &P_NilFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Key helpers
|
//~ Key helpers
|
||||||
|
|
||||||
|
b32 P_MatchKey(P_Key a, P_Key b)
|
||||||
|
{
|
||||||
|
return a.v == b.v;
|
||||||
|
}
|
||||||
|
|
||||||
P_Key P_RandKey(void)
|
P_Key P_RandKey(void)
|
||||||
{
|
{
|
||||||
// TODO: Don't use true randomness for entity keys. It's overkill & non-deterministic.
|
// TODO: Don't use true randomness for entity keys. It's overkill & non-deterministic.
|
||||||
@ -73,91 +82,6 @@ String P_NameFromTileKind(P_TileKind kind)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
//~ Delta helpers
|
|
||||||
|
|
||||||
void P_UpdateWorldFromDelta(Arena *arena, P_World *world, P_Delta *delta)
|
|
||||||
{
|
|
||||||
// FIXME: Bounds check tile deltas
|
|
||||||
if (0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
//- Reset
|
|
||||||
if (delta->kind == P_DeltaKind_Reset)
|
|
||||||
{
|
|
||||||
// FIXME: Free list entities
|
|
||||||
world->ents_count = 0;
|
|
||||||
world->first_ent = 0;
|
|
||||||
world->last_ent = 0;
|
|
||||||
ZeroStructs(world->tiles, P_TilesCount);
|
|
||||||
ZeroStructs(world->ent_bins, world->ent_bins_count);
|
|
||||||
}
|
|
||||||
//- Raw ent
|
|
||||||
if (delta->kind == P_DeltaKind_RawEnt)
|
|
||||||
{
|
|
||||||
P_Key key = delta->ent.key;
|
|
||||||
P_Ent *ent = P_EntFromKey(world, key);
|
|
||||||
if (!ent->valid)
|
|
||||||
{
|
|
||||||
// FIXME: Use ent free list
|
|
||||||
ent = PushStructNoZero(arena, P_Ent);
|
|
||||||
*ent = P_NilEnt;
|
|
||||||
ent->key = key;
|
|
||||||
P_EntBin *bin = &world->ent_bins[ent->key.v % world->ent_bins_count];
|
|
||||||
DllQueuePushNP(bin->first, bin->last, ent, next_in_bin, prev_in_bin);
|
|
||||||
DllQueuePush(world->first_ent, world->last_ent, ent);
|
|
||||||
++world->ents_count;
|
|
||||||
}
|
|
||||||
P_Ent *old_next = ent->next;
|
|
||||||
P_Ent *old_prev = ent->prev;
|
|
||||||
P_Ent *old_next_in_bin = ent->next_in_bin;
|
|
||||||
P_Ent *old_prev_in_bin = ent->prev_in_bin;
|
|
||||||
{
|
|
||||||
P_Ent *src = &delta->ent;
|
|
||||||
*ent = *src;
|
|
||||||
}
|
|
||||||
ent->next = old_next;
|
|
||||||
ent->prev = old_prev;
|
|
||||||
ent->next_in_bin = old_next_in_bin;
|
|
||||||
ent->prev_in_bin = old_prev_in_bin;
|
|
||||||
ent->valid = 1;
|
|
||||||
}
|
|
||||||
//- Raw tiles
|
|
||||||
else if (delta->kind == P_DeltaKind_RawTiles)
|
|
||||||
{
|
|
||||||
Rng2I32 range = delta->tile_range;
|
|
||||||
for (i32 tile_y = range.p0.y; tile_y < range.p1.y; ++tile_y)
|
|
||||||
{
|
|
||||||
i32 src_tile_y = tile_y - range.p0.y;
|
|
||||||
for (i32 tile_x = range.p0.x; tile_x < range.p1.x; ++tile_x)
|
|
||||||
{
|
|
||||||
i32 src_tile_x = tile_x - range.p0.x;
|
|
||||||
Vec2 src_tile_pos = VEC2(src_tile_x, src_tile_y);
|
|
||||||
i32 src_tile_idx = P_TileIdxFromTilePos(src_tile_pos);
|
|
||||||
u8 src_tile = delta->raw_tiles[src_tile_idx];
|
|
||||||
|
|
||||||
Vec2 tile_pos = VEC2(tile_x, tile_y);
|
|
||||||
i32 tile_idx = P_TileIdxFromTilePos(tile_pos);
|
|
||||||
world->tiles[tile_idx] = src_tile;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//- Tile range
|
|
||||||
else if (delta->kind == P_DeltaKind_Tile)
|
|
||||||
{
|
|
||||||
P_TileKind tile = delta->tile_kind;
|
|
||||||
Rng2I32 range = delta->tile_range;
|
|
||||||
for (i32 tile_y = range.p0.y; tile_y < range.p1.y; ++tile_y)
|
|
||||||
{
|
|
||||||
for (i32 tile_x = range.p0.x; tile_x < range.p1.x; ++tile_x)
|
|
||||||
{
|
|
||||||
Vec2 tile_pos = VEC2(tile_x, tile_y);
|
|
||||||
i32 tile_idx = P_TileIdxFromTilePos(tile_pos);
|
|
||||||
world->tiles[tile_idx] = (u8)tile;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Shape helpers
|
//~ Shape helpers
|
||||||
@ -1106,12 +1030,14 @@ Vec2 P_EdgePointFromShape(P_Shape shape, Vec2 dir)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Lookup helpers
|
//~ Lookup helpers
|
||||||
|
|
||||||
P_Ent *P_EntFromKeyEx(P_World *world, P_Key key, i64 tick)
|
P_Ent *P_EntFromKey(P_Frame *frame, P_Key key)
|
||||||
{
|
{
|
||||||
P_Ent *result = &P_NilEnt;
|
P_Ent *result = &P_NilEnt;
|
||||||
if (!P_IsKeyNil(key) && world->ent_bins_count > 0)
|
P_World *world = frame->world;
|
||||||
|
if (!P_IsKeyNil(key) && frame->tick > 0 && frame->ents_count > 0 && frame->ent_bins_count > 0)
|
||||||
{
|
{
|
||||||
P_EntBin *bin = &world->ent_bins[key.v % world->ent_bins_count];
|
i64 tick = frame->tick;
|
||||||
|
P_EntBin *bin = &frame->ent_bins[key.v % frame->ent_bins_count];
|
||||||
for (P_Ent *e = bin->first; e; e = e->next_in_bin)
|
for (P_Ent *e = bin->first; e; e = e->next_in_bin)
|
||||||
{
|
{
|
||||||
if (e->key.v == key.v)
|
if (e->key.v == key.v)
|
||||||
@ -1124,20 +1050,15 @@ P_Ent *P_EntFromKeyEx(P_World *world, P_Key key, i64 tick)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
P_Ent *P_EntFromKey(P_World *world, P_Key key)
|
|
||||||
{
|
|
||||||
return P_EntFromKeyEx(world, key, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Iteration helpers
|
//~ Iteration helpers
|
||||||
|
|
||||||
P_Ent *P_FirstEnt(P_World *world)
|
P_Ent *P_FirstEnt(P_Frame *frame)
|
||||||
{
|
{
|
||||||
P_Ent *result = &P_NilEnt;
|
P_Ent *result = &P_NilEnt;
|
||||||
if (world->first_ent)
|
if (frame->first_ent)
|
||||||
{
|
{
|
||||||
result = world->first_ent;
|
result = frame->first_ent;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -1159,51 +1080,10 @@ P_Ent *P_PushTempEnt(Arena *arena, P_EntList *list)
|
|||||||
++list->count;
|
++list->count;
|
||||||
P_Ent *ent = &n->ent;
|
P_Ent *ent = &n->ent;
|
||||||
*ent = P_NilEnt;
|
*ent = P_NilEnt;
|
||||||
ent->valid = 1;
|
|
||||||
ent->exists = 1;
|
ent->exists = 1;
|
||||||
return ent;
|
return ent;
|
||||||
}
|
}
|
||||||
|
|
||||||
void P_SpawnEntsFromList(Arena *arena, P_World *world, P_EntList ents)
|
|
||||||
{
|
|
||||||
for (P_EntListNode *n = ents.first; n; n = n->next)
|
|
||||||
{
|
|
||||||
P_Ent *src = &n->ent;
|
|
||||||
P_Key key = src->key;
|
|
||||||
if (!P_IsKeyNil(src->key))
|
|
||||||
{
|
|
||||||
P_EntBin *bin = &world->ent_bins[key.v % world->ent_bins_count];
|
|
||||||
P_Ent *dst = bin->first;
|
|
||||||
for (; dst; dst = dst->next_in_bin)
|
|
||||||
{
|
|
||||||
if (P_MatchKey(dst->key, key))
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!dst)
|
|
||||||
{
|
|
||||||
// FIXME: Use free list
|
|
||||||
dst = PushStructNoZero(arena, P_Ent);
|
|
||||||
DllQueuePush(world->first_ent, world->last_ent, dst);
|
|
||||||
DllQueuePushNP(bin->first, bin->last, dst, next_in_bin, prev_in_bin);
|
|
||||||
}
|
|
||||||
P_Ent *old_next = dst->next;
|
|
||||||
P_Ent *old_prev = dst->prev;
|
|
||||||
P_Ent *old_next_in_bin = dst->next_in_bin;
|
|
||||||
P_Ent *old_prev_in_bin = dst->prev_in_bin;
|
|
||||||
{
|
|
||||||
*dst = *src;
|
|
||||||
}
|
|
||||||
dst->next = old_next;
|
|
||||||
dst->prev = old_prev;
|
|
||||||
dst->next_in_bin = old_next_in_bin;
|
|
||||||
dst->prev_in_bin = old_prev_in_bin;
|
|
||||||
++world->ents_count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Debug draw
|
//~ Debug draw
|
||||||
|
|
||||||
@ -1267,3 +1147,263 @@ void P_DebugDrawShape(P_Shape shape, Vec4 srgb)
|
|||||||
P_tl.debug_draw_nodes_count += 1;
|
P_tl.debug_draw_nodes_count += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//~ World
|
||||||
|
|
||||||
|
P_World *P_AcquireWorld(void)
|
||||||
|
{
|
||||||
|
P_World *world = 0;
|
||||||
|
{
|
||||||
|
Arena *arena = AcquireArena(Gibi(64));
|
||||||
|
world = PushStruct(arena, P_World);
|
||||||
|
world->arena = arena;
|
||||||
|
}
|
||||||
|
world->frames_arena = AcquireArena(Gibi(64));
|
||||||
|
world->statics_arena = AcquireArena(Gibi(64));
|
||||||
|
|
||||||
|
world->first_frame = &P_NilFrame;
|
||||||
|
world->last_frame = &P_NilFrame;
|
||||||
|
world->frame_bins_count = Kibi(1);
|
||||||
|
world->frame_bins = PushStructs(world->arena, P_FrameBin, world->frame_bins_count);
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
|
||||||
|
world->tiles = PushStructs(world->arena, u8, P_TilesCount);
|
||||||
|
|
||||||
|
TrueRand(StringFromStruct(&world->seed));
|
||||||
|
return world;
|
||||||
|
}
|
||||||
|
|
||||||
|
void P_UpdateWorldFromSnapshots(P_World *world, P_SnapshotList snapshots)
|
||||||
|
{
|
||||||
|
b32 tiles_dirty = 0;
|
||||||
|
for (P_SnapshotNode *n = snapshots.first; n; n = n->next)
|
||||||
|
{
|
||||||
|
P_Snapshot *snapshot = &n->snapshot;
|
||||||
|
// FIXME: Process intermediate ticks
|
||||||
|
if (snapshot->tick > world->last_frame->tick)
|
||||||
|
{
|
||||||
|
P_Frame *src_frame = P_FrameFromTick(world, snapshot->src_tick);
|
||||||
|
P_Frame *frame = P_PushFrame(world, src_frame, snapshot->tick);
|
||||||
|
world->seed = snapshot->world_seed;
|
||||||
|
frame->time_ns = snapshot->time_ns;
|
||||||
|
|
||||||
|
if (frame->ents_count == 0)
|
||||||
|
{
|
||||||
|
for (P_DeltaNode *dn = snapshot->first_delta_node; dn; dn = dn->next)
|
||||||
|
{
|
||||||
|
P_Delta *delta = &dn->delta;
|
||||||
|
// FIXME: Bounds check tile deltas
|
||||||
|
if (0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
//- Reset
|
||||||
|
else if (delta->kind == P_DeltaKind_Reset)
|
||||||
|
{
|
||||||
|
// FIXME: Free list entities
|
||||||
|
frame->ents_count = 0;
|
||||||
|
frame->first_ent = 0;
|
||||||
|
frame->last_ent = 0;
|
||||||
|
ZeroStructs(world->tiles, P_TilesCount);
|
||||||
|
ZeroStructs(frame->ent_bins, frame->ent_bins_count);
|
||||||
|
tiles_dirty = 1;
|
||||||
|
}
|
||||||
|
//- Raw ent
|
||||||
|
else if (delta->kind == P_DeltaKind_RawEnt)
|
||||||
|
{
|
||||||
|
P_Ent tmp_ent = delta->ent;
|
||||||
|
P_EntListNode tmp_ent_node = Zi;
|
||||||
|
tmp_ent_node.ent = tmp_ent;
|
||||||
|
P_EntList ent_list = Zi;
|
||||||
|
ent_list.first = &tmp_ent_node;
|
||||||
|
ent_list.last = &tmp_ent_node;
|
||||||
|
P_SpawnEntsFromList(frame, ent_list);
|
||||||
|
}
|
||||||
|
//- Raw tiles
|
||||||
|
else if (delta->kind == P_DeltaKind_RawTiles)
|
||||||
|
{
|
||||||
|
Rng2I32 range = delta->tile_range;
|
||||||
|
for (i32 tile_y = range.p0.y; tile_y < range.p1.y; ++tile_y)
|
||||||
|
{
|
||||||
|
i32 src_tile_y = tile_y - range.p0.y;
|
||||||
|
for (i32 tile_x = range.p0.x; tile_x < range.p1.x; ++tile_x)
|
||||||
|
{
|
||||||
|
i32 src_tile_x = tile_x - range.p0.x;
|
||||||
|
Vec2 src_tile_pos = VEC2(src_tile_x, src_tile_y);
|
||||||
|
i32 src_tile_idx = P_TileIdxFromTilePos(src_tile_pos);
|
||||||
|
u8 src_tile = delta->raw_tiles[src_tile_idx];
|
||||||
|
|
||||||
|
Vec2 tile_pos = VEC2(tile_x, tile_y);
|
||||||
|
i32 tile_idx = P_TileIdxFromTilePos(tile_pos);
|
||||||
|
world->tiles[tile_idx] = src_tile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tiles_dirty = 1;
|
||||||
|
}
|
||||||
|
//- Tile range
|
||||||
|
else if (delta->kind == P_DeltaKind_Tile)
|
||||||
|
{
|
||||||
|
P_TileKind tile = delta->tile_kind;
|
||||||
|
Rng2I32 range = delta->tile_range;
|
||||||
|
for (i32 tile_y = range.p0.y; tile_y < range.p1.y; ++tile_y)
|
||||||
|
{
|
||||||
|
for (i32 tile_x = range.p0.x; tile_x < range.p1.x; ++tile_x)
|
||||||
|
{
|
||||||
|
Vec2 tile_pos = VEC2(tile_x, tile_y);
|
||||||
|
i32 tile_idx = P_TileIdxFromTilePos(tile_pos);
|
||||||
|
world->tiles[tile_idx] = (u8)tile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tiles_dirty = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// FIXME: Real prune
|
||||||
|
// for (P_Ent *ent = P_FirstEnt(frame); !P_IsEntNil(ent); ent = P_NextEnt(ent))
|
||||||
|
// {
|
||||||
|
// ent->exists = 0;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Rehash statics
|
||||||
|
// if (tiles_dirty)
|
||||||
|
// {
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
void P_SpawnEntsFromList(P_Frame *frame, P_EntList ents)
|
||||||
|
{
|
||||||
|
P_World *world = frame->world;
|
||||||
|
for (P_EntListNode *n = ents.first; n; n = n->next)
|
||||||
|
{
|
||||||
|
P_Ent *src = &n->ent;
|
||||||
|
P_Key key = src->key;
|
||||||
|
if (!P_IsKeyNil(src->key))
|
||||||
|
{
|
||||||
|
P_EntBin *bin = &frame->ent_bins[key.v % frame->ent_bins_count];
|
||||||
|
P_Ent *dst = bin->first;
|
||||||
|
for (; dst; dst = dst->next_in_bin)
|
||||||
|
{
|
||||||
|
if (dst->key.v == key.v)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!dst)
|
||||||
|
{
|
||||||
|
// FIXME: Use free list
|
||||||
|
dst = PushStructNoZero(world->arena, P_Ent);
|
||||||
|
DllQueuePush(frame->first_ent, frame->last_ent, dst);
|
||||||
|
DllQueuePushNP(bin->first, bin->last, dst, next_in_bin, prev_in_bin);
|
||||||
|
}
|
||||||
|
P_Ent *old_next = dst->next;
|
||||||
|
P_Ent *old_prev = dst->prev;
|
||||||
|
P_Ent *old_next_in_bin = dst->next_in_bin;
|
||||||
|
P_Ent *old_prev_in_bin = dst->prev_in_bin;
|
||||||
|
{
|
||||||
|
*dst = *src;
|
||||||
|
}
|
||||||
|
dst->next = old_next;
|
||||||
|
dst->prev = old_prev;
|
||||||
|
dst->next_in_bin = old_next_in_bin;
|
||||||
|
dst->prev_in_bin = old_prev_in_bin;
|
||||||
|
++frame->ents_count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
P_Frame *P_FrameFromTick(P_World *world, i64 tick)
|
||||||
|
{
|
||||||
|
P_Frame *result = &P_NilFrame;
|
||||||
|
if (world->frame_bins_count > 0)
|
||||||
|
{
|
||||||
|
u64 hash = MixU64(tick);
|
||||||
|
P_FrameBin *bin = &world->frame_bins[hash % world->frame_bins_count];
|
||||||
|
for (P_Frame *frame = bin->first; frame; frame = frame->next_in_bin)
|
||||||
|
{
|
||||||
|
if (frame->tick == tick)
|
||||||
|
{
|
||||||
|
result = frame;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void P_ClearFrames(P_World *world, i64 tick_min, i64 tick_max)
|
||||||
|
{
|
||||||
|
// TODO: Fast path for when range encompasses all frames in the world
|
||||||
|
// TODO: Don't need linear search
|
||||||
|
P_Frame *frame = world->first_frame;
|
||||||
|
while (!P_IsFrameNil(frame))
|
||||||
|
{
|
||||||
|
P_Frame *next_frame = frame->next;
|
||||||
|
if (frame->tick >= tick_min && frame->tick <= tick_max)
|
||||||
|
{
|
||||||
|
// FIXME: Freelist ents
|
||||||
|
|
||||||
|
// FIXME: Freelist frame
|
||||||
|
|
||||||
|
u64 hash = MixU64(frame->tick);
|
||||||
|
P_FrameBin *bin = &world->frame_bins[hash % world->frame_bins_count];
|
||||||
|
DllQueueRemoveNPZ(&P_NilFrame, world->first_frame, world->last_frame, frame, next, prev);
|
||||||
|
DllQueueRemoveNPZ(0, bin->first, bin->last, frame, next_in_bin, prev_in_bin);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
frame = next_frame;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
P_Frame *P_PushFrame(P_World *world, P_Frame *src_frame, i64 tick)
|
||||||
|
{
|
||||||
|
Assert(!(src_frame->world == world && tick <= src_frame->tick)); // Can't read from tick that is being overwritten by new tick
|
||||||
|
P_ClearFrames(world, tick, I64Max);
|
||||||
|
|
||||||
|
P_Frame *frame = PushStruct(world->frames_arena, P_Frame);
|
||||||
|
{
|
||||||
|
// FIXME: Pull from freelist
|
||||||
|
|
||||||
|
frame->world = world;
|
||||||
|
frame->tick = tick;
|
||||||
|
frame->time_ns = src_frame->time_ns;
|
||||||
|
|
||||||
|
frame->ent_bins_count = Kibi(16);
|
||||||
|
frame->ent_bins = PushStructs(world->frames_arena, P_EntBin, frame->ent_bins_count);
|
||||||
|
|
||||||
|
u64 hash = MixU64(tick);
|
||||||
|
P_FrameBin *bin = &world->frame_bins[hash % world->frame_bins_count];
|
||||||
|
|
||||||
|
DllQueuePushNPZ(&P_NilFrame, world->first_frame, world->last_frame, frame, next, prev);
|
||||||
|
DllQueuePushNPZ(0, bin->first, bin->last, frame, next_in_bin, prev_in_bin);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (P_Ent *src = P_FirstEnt(src_frame); !P_IsEntNil(src); src = P_NextEnt(src))
|
||||||
|
{
|
||||||
|
// FIXME: Pull from freelist
|
||||||
|
P_Ent *dst = PushStruct(world->frames_arena, P_Ent);
|
||||||
|
*dst = *src;
|
||||||
|
P_EntBin *bin = &frame->ent_bins[src->key.v % frame->ent_bins_count];
|
||||||
|
DllQueuePush(frame->first_ent, frame->last_ent, dst);
|
||||||
|
DllQueuePushNP(bin->first, bin->last, dst, next_in_bin, prev_in_bin);
|
||||||
|
++frame->ents_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//~ Step
|
||||||
|
|
||||||
|
P_Frame *P_StepWorld(P_World *world, P_Frame *prev_frame, P_CmdList cmds)
|
||||||
|
{
|
||||||
|
P_Frame *result = &P_NilFrame;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|||||||
105
src/pp/pp.h
105
src/pp/pp.h
@ -52,7 +52,6 @@ Struct(P_Ent)
|
|||||||
//- Persistent data
|
//- Persistent data
|
||||||
|
|
||||||
P_Key key;
|
P_Key key;
|
||||||
b32 valid;
|
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Build data
|
//- Build data
|
||||||
@ -62,7 +61,7 @@ Struct(P_Ent)
|
|||||||
b32 is_player;
|
b32 is_player;
|
||||||
f32 health;
|
f32 health;
|
||||||
|
|
||||||
Xform last_xf;
|
Xform prev_xf;
|
||||||
Xform xf;
|
Xform xf;
|
||||||
|
|
||||||
Vec2 move;
|
Vec2 move;
|
||||||
@ -112,9 +111,22 @@ Struct(P_EntBin)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ World types
|
//~ World types
|
||||||
|
|
||||||
Struct(P_World)
|
Struct(P_Frame)
|
||||||
{
|
{
|
||||||
u64 seed;
|
//////////////////////////////
|
||||||
|
//- Internal world state
|
||||||
|
|
||||||
|
struct P_World *world;
|
||||||
|
|
||||||
|
P_Frame *next;
|
||||||
|
P_Frame *prev;
|
||||||
|
|
||||||
|
P_Frame *next_in_bin;
|
||||||
|
P_Frame *prev_in_bin;
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- Frame state
|
||||||
|
|
||||||
i64 tick;
|
i64 tick;
|
||||||
i64 time_ns;
|
i64 time_ns;
|
||||||
|
|
||||||
@ -124,6 +136,28 @@ Struct(P_World)
|
|||||||
|
|
||||||
i64 ent_bins_count;
|
i64 ent_bins_count;
|
||||||
P_EntBin *ent_bins;
|
P_EntBin *ent_bins;
|
||||||
|
};
|
||||||
|
|
||||||
|
Struct(P_FrameBin)
|
||||||
|
{
|
||||||
|
P_Frame *first;
|
||||||
|
P_Frame *last;
|
||||||
|
};
|
||||||
|
|
||||||
|
Struct(P_World)
|
||||||
|
{
|
||||||
|
Arena *arena;
|
||||||
|
Arena *frames_arena;
|
||||||
|
Arena *statics_arena;
|
||||||
|
|
||||||
|
u64 seed;
|
||||||
|
// P_Ent *first_free_ent;
|
||||||
|
|
||||||
|
P_Frame *first_frame;
|
||||||
|
P_Frame *last_frame;
|
||||||
|
i64 frame_bins_count;
|
||||||
|
P_FrameBin *frame_bins;
|
||||||
|
// P_Frame *first_free_frame;
|
||||||
|
|
||||||
u8 *tiles;
|
u8 *tiles;
|
||||||
};
|
};
|
||||||
@ -155,7 +189,9 @@ Struct(P_DeltaNode)
|
|||||||
|
|
||||||
Struct(P_Snapshot)
|
Struct(P_Snapshot)
|
||||||
{
|
{
|
||||||
u64 seed;
|
u64 world_seed;
|
||||||
|
// i64 src_world_tick;
|
||||||
|
i64 src_tick;
|
||||||
i64 tick;
|
i64 tick;
|
||||||
i64 time_ns;
|
i64 time_ns;
|
||||||
|
|
||||||
@ -170,6 +206,13 @@ Struct(P_SnapshotNode)
|
|||||||
P_Snapshot snapshot;
|
P_Snapshot snapshot;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Struct(P_SnapshotList)
|
||||||
|
{
|
||||||
|
i64 count;
|
||||||
|
P_SnapshotNode *first;
|
||||||
|
P_SnapshotNode *last;
|
||||||
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Collision types
|
//~ Collision types
|
||||||
|
|
||||||
@ -306,6 +349,7 @@ Enum(P_CmdKind)
|
|||||||
|
|
||||||
Struct(P_Cmd)
|
Struct(P_Cmd)
|
||||||
{
|
{
|
||||||
|
i64 tick;
|
||||||
P_CmdKind kind;
|
P_CmdKind kind;
|
||||||
|
|
||||||
// Delta
|
// Delta
|
||||||
@ -325,20 +369,25 @@ Struct(P_CmdNode)
|
|||||||
P_Cmd cmd;
|
P_Cmd cmd;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Struct(P_CmdList)
|
||||||
|
{
|
||||||
|
i64 count;
|
||||||
|
P_CmdNode *first;
|
||||||
|
P_CmdNode *last;
|
||||||
|
};
|
||||||
|
|
||||||
Struct(P_InputState)
|
Struct(P_InputState)
|
||||||
{
|
{
|
||||||
Arena *arena;
|
Arena *arena;
|
||||||
P_CmdNode *first_cmd_node;
|
|
||||||
P_CmdNode *last_cmd_node;
|
P_CmdList cmds;
|
||||||
u64 cmds_count;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(P_OutputState)
|
Struct(P_OutputState)
|
||||||
{
|
{
|
||||||
Arena *arena;
|
Arena *arena;
|
||||||
P_SnapshotNode *first_snapshot_node;
|
|
||||||
P_SnapshotNode *last_snapshot_node;
|
P_SnapshotList snapshots;
|
||||||
u64 snapshots_count;
|
|
||||||
|
|
||||||
P_DebugDrawNode *first_debug_draw_node;
|
P_DebugDrawNode *first_debug_draw_node;
|
||||||
P_DebugDrawNode *last_debug_draw_node;
|
P_DebugDrawNode *last_debug_draw_node;
|
||||||
@ -363,6 +412,7 @@ Struct(P_Ctx)
|
|||||||
|
|
||||||
Struct(P_ThreadLocalCtx)
|
Struct(P_ThreadLocalCtx)
|
||||||
{
|
{
|
||||||
|
// TODO: Move this to world frame
|
||||||
Arena *debug_arena;
|
Arena *debug_arena;
|
||||||
b32 debug_draw_enabled;
|
b32 debug_draw_enabled;
|
||||||
P_DebugDrawNode *first_debug_draw_node;
|
P_DebugDrawNode *first_debug_draw_node;
|
||||||
@ -373,6 +423,9 @@ Struct(P_ThreadLocalCtx)
|
|||||||
extern P_Ctx P;
|
extern P_Ctx P;
|
||||||
extern ThreadLocal P_ThreadLocalCtx P_tl;
|
extern ThreadLocal P_ThreadLocalCtx P_tl;
|
||||||
|
|
||||||
|
extern Readonly P_Ent P_NilEnt;
|
||||||
|
extern Readonly P_Frame P_NilFrame;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Bootstrap
|
//~ Bootstrap
|
||||||
|
|
||||||
@ -383,11 +436,12 @@ void P_Bootstrap(void);
|
|||||||
|
|
||||||
b32 P_IsKeyNil(P_Key key);
|
b32 P_IsKeyNil(P_Key key);
|
||||||
b32 P_IsEntNil(P_Ent *ent);
|
b32 P_IsEntNil(P_Ent *ent);
|
||||||
b32 P_MatchKey(P_Key a, P_Key b);
|
b32 P_IsFrameNil(P_Frame *frame);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Key helpers
|
//~ Key helpers
|
||||||
|
|
||||||
|
b32 P_MatchKey(P_Key a, P_Key b);
|
||||||
P_Key P_RandKey(void);
|
P_Key P_RandKey(void);
|
||||||
|
|
||||||
#define P_FmtKey(key) FmtHandle((key).v)
|
#define P_FmtKey(key) FmtHandle((key).v)
|
||||||
@ -397,11 +451,6 @@ P_Key P_RandKey(void);
|
|||||||
|
|
||||||
String P_NameFromTileKind(P_TileKind kind);
|
String P_NameFromTileKind(P_TileKind kind);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
//~ Delta helpers
|
|
||||||
|
|
||||||
void P_UpdateWorldFromDelta(Arena *arena, P_World *world, P_Delta *delta);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Shape helpers
|
//~ Shape helpers
|
||||||
|
|
||||||
@ -431,20 +480,18 @@ Vec2 P_EdgePointFromShape(P_Shape shape, Vec2 dir);
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Lookup helpers
|
//~ Lookup helpers
|
||||||
|
|
||||||
P_Ent *P_EntFromKeyEx(P_World *world, P_Key key, i64 tick);
|
P_Ent *P_EntFromKey(P_Frame *frame, P_Key key);
|
||||||
P_Ent *P_EntFromKey(P_World *world, P_Key key);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Iteration helpers
|
//~ Iteration helpers
|
||||||
|
|
||||||
P_Ent *P_FirstEnt(P_World *world);
|
P_Ent *P_FirstEnt(P_Frame *frame);
|
||||||
P_Ent *P_NextEnt(P_Ent *e);
|
P_Ent *P_NextEnt(P_Ent *e);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ List helpers
|
//~ List helpers
|
||||||
|
|
||||||
P_Ent *P_PushTempEnt(Arena *arena, P_EntList *list);
|
P_Ent *P_PushTempEnt(Arena *arena, P_EntList *list);
|
||||||
void P_SpawnEntsFromList(Arena *arena, P_World *world, P_EntList ents);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Debug draw
|
//~ Debug draw
|
||||||
@ -453,3 +500,19 @@ void P_DebugDrawPoint(Vec2 p, Vec4 srgb);
|
|||||||
void P_DebugDrawLine(Vec2 p0, Vec2 p1, Vec4 srgb);
|
void P_DebugDrawLine(Vec2 p0, Vec2 p1, Vec4 srgb);
|
||||||
void P_DebugDrawRect(Rng2 rect, Vec4 srgb);
|
void P_DebugDrawRect(Rng2 rect, Vec4 srgb);
|
||||||
void P_DebugDrawShape(P_Shape shape, Vec4 srgb);
|
void P_DebugDrawShape(P_Shape shape, Vec4 srgb);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//~ World
|
||||||
|
|
||||||
|
P_World *P_AcquireWorld(void);
|
||||||
|
void P_UpdateWorldFromSnapshots(P_World *world, P_SnapshotList snapshots);
|
||||||
|
void P_SpawnEntsFromList(P_Frame *frame, P_EntList ents);
|
||||||
|
|
||||||
|
P_Frame *P_FrameFromTick(P_World *world, i64 tick);
|
||||||
|
void P_ClearFrames(P_World *world, i64 tick_min, i64 tick_max);
|
||||||
|
P_Frame *P_PushFrame(P_World *world, P_Frame *src_frame, i64 tick);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//~ Step
|
||||||
|
|
||||||
|
P_Frame *P_StepWorld(P_World *world, P_Frame *prev_frame, P_CmdList cmds);
|
||||||
|
|||||||
@ -24,13 +24,11 @@ void S_TickForever(WaveLaneCtx *lane)
|
|||||||
Arena *frame_arena = AcquireArena(Gibi(64));
|
Arena *frame_arena = AcquireArena(Gibi(64));
|
||||||
P_tl.debug_arena = AcquireArena(Gibi(64));
|
P_tl.debug_arena = AcquireArena(Gibi(64));
|
||||||
|
|
||||||
Arena *world_arena = AcquireArena(Gibi(64));
|
P_World *world = P_AcquireWorld();
|
||||||
P_World *world = 0;
|
|
||||||
|
|
||||||
// TODO: Real per-client deltas
|
// TODO: Real per-client deltas
|
||||||
b32 has_sent_initial_tick = 0;
|
b32 has_sent_initial_tick = 0;
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Sim loop
|
//- Sim loop
|
||||||
|
|
||||||
@ -39,65 +37,69 @@ void S_TickForever(WaveLaneCtx *lane)
|
|||||||
{
|
{
|
||||||
shutdown = Atomic32Fetch(&S.shutdown);
|
shutdown = Atomic32Fetch(&S.shutdown);
|
||||||
P_tl.debug_draw_enabled = TweakBool("Simulation debug draw", 1);
|
P_tl.debug_draw_enabled = TweakBool("Simulation debug draw", 1);
|
||||||
|
|
||||||
ResetArena(frame_arena);
|
ResetArena(frame_arena);
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Swap
|
//- Swap
|
||||||
|
|
||||||
{
|
// {
|
||||||
b32 swapin = IsSwappedIn();
|
// b32 swapin = IsSwappedIn();
|
||||||
b32 swapout = shutdown && IsSwappingOut();
|
// b32 swapout = shutdown && IsSwappingOut();
|
||||||
|
|
||||||
//- Swap in
|
// //- Swap in
|
||||||
if (!world)
|
// if (!world)
|
||||||
{
|
// {
|
||||||
String packed = Zi;
|
// String packed = Zi;
|
||||||
if (swapin)
|
// if (swapin)
|
||||||
{
|
// {
|
||||||
packed = SwappedStateFromName(frame_arena, Lit("pp_sim.swp"));
|
// packed = SwappedStateFromName(frame_arena, Lit("pp_sim.swp"));
|
||||||
}
|
// }
|
||||||
P_UnpackedWorld unpacked = P_UnpackWorld(frame_arena, packed);
|
// P_UnpackedWorld unpacked = P_UnpackWorld(frame_arena, packed);
|
||||||
|
|
||||||
ResetArena(world_arena);
|
// ResetArena(world_arena);
|
||||||
world = PushStruct(world_arena, P_World);
|
// world = PushStruct(world_arena, P_World);
|
||||||
world->seed = unpacked.seed;
|
// world->seed = unpacked.seed;
|
||||||
world->tick = unpacked.tick;
|
// world_frame->tick = unpacked.tick;
|
||||||
world->time_ns = unpacked.time_ns;
|
// world_frame->time_ns = unpacked.time_ns;
|
||||||
if (world->seed == 0)
|
// if (world->seed == 0)
|
||||||
{
|
// {
|
||||||
TrueRand(StringFromStruct(&world->seed));
|
// TrueRand(StringFromStruct(&world->seed));
|
||||||
}
|
// }
|
||||||
|
|
||||||
world->ent_bins_count = Kibi(16);
|
// world_frame->ent_bins_count = Kibi(16);
|
||||||
world->ent_bins = PushStructs(world_arena, P_EntBin, world->ent_bins_count);
|
// world_frame->ent_bins = PushStructs(world_arena, P_EntBin, world_frame->ent_bins_count);
|
||||||
|
|
||||||
// Copy tiles
|
// // Copy tiles
|
||||||
world->tiles = PushStructsNoZero(world_arena, u8, P_TilesCount);
|
// world->tiles = PushStructsNoZero(world_arena, u8, P_TilesCount);
|
||||||
CopyStructs(world->tiles, unpacked.tiles, P_TilesCount);
|
// CopyStructs(world->tiles, unpacked.tiles, P_TilesCount);
|
||||||
|
|
||||||
// Copy ents
|
// // Copy ents
|
||||||
P_SpawnEntsFromList(world_arena, world, unpacked.ents);
|
// P_SpawnEntsFromList(world_arena, world, unpacked.ents);
|
||||||
}
|
// }
|
||||||
|
|
||||||
//- Swap out
|
// //- Swap out
|
||||||
if (swapout)
|
// if (swapout)
|
||||||
{
|
// {
|
||||||
String packed = P_PackWorld(frame_arena, world);
|
// String packed = P_PackWorld(frame_arena, world);
|
||||||
WriteSwappedState(Lit("pp_sim.swp"), packed);
|
// WriteSwappedState(Lit("pp_sim.swp"), packed);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Begin sim frame
|
//- Begin sim frame
|
||||||
|
|
||||||
|
P_Frame *prev_world_frame = world->last_frame;
|
||||||
|
P_Frame *world_frame = P_PushFrame(world, prev_world_frame, prev_world_frame->tick + 1);
|
||||||
|
|
||||||
|
// FIXME: Copy frame
|
||||||
|
|
||||||
|
|
||||||
i64 frame_begin_ns = TimeNs();
|
i64 frame_begin_ns = TimeNs();
|
||||||
i64 sim_dt_ns = NsFromSeconds(1) / SIM_TICKS_PER_SECOND;
|
i64 sim_dt_ns = NsFromSeconds(1) / SIM_TICKS_PER_SECOND;
|
||||||
f64 sim_dt = SecondsFromNs(sim_dt_ns);
|
f64 sim_dt = SecondsFromNs(sim_dt_ns);
|
||||||
world->tick += 1;
|
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Pop sim commands
|
//- Pop commands
|
||||||
|
|
||||||
P_InputState *input = 0;
|
P_InputState *input = 0;
|
||||||
LockTicketMutex(&P.sim_input_back_tm);
|
LockTicketMutex(&P.sim_input_back_tm);
|
||||||
@ -114,9 +116,9 @@ void S_TickForever(WaveLaneCtx *lane)
|
|||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Update double-buffered entity data
|
//- Update double-buffered entity data
|
||||||
|
|
||||||
for (P_Ent *ent = P_FirstEnt(world); ent->valid; ent = P_NextEnt(ent))
|
for (P_Ent *ent = P_FirstEnt(world_frame); !P_IsEntNil(ent); ent = P_NextEnt(ent))
|
||||||
{
|
{
|
||||||
ent->last_xf = ent->xf;
|
ent->prev_xf = ent->xf;
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
@ -125,7 +127,7 @@ void S_TickForever(WaveLaneCtx *lane)
|
|||||||
// FIXME: Only accept save command from local user
|
// FIXME: Only accept save command from local user
|
||||||
|
|
||||||
b32 should_save = 0;
|
b32 should_save = 0;
|
||||||
for (P_CmdNode *cmd_node = input->first_cmd_node; cmd_node; cmd_node = cmd_node->next)
|
for (P_CmdNode *cmd_node = input->cmds.first; cmd_node; cmd_node = cmd_node->next)
|
||||||
{
|
{
|
||||||
P_Cmd *cmd = &cmd_node->cmd;
|
P_Cmd *cmd = &cmd_node->cmd;
|
||||||
if (cmd->kind == P_CmdKind_Save)
|
if (cmd->kind == P_CmdKind_Save)
|
||||||
@ -145,9 +147,11 @@ void S_TickForever(WaveLaneCtx *lane)
|
|||||||
|
|
||||||
// FIXME: Only accept world deltas from users that can edit
|
// FIXME: Only accept world deltas from users that can edit
|
||||||
|
|
||||||
|
// FIXME: Only apply relevant cmds based on tick
|
||||||
|
|
||||||
i64 applied_user_deltas_count = 0;
|
i64 applied_user_deltas_count = 0;
|
||||||
P_Delta **applied_user_deltas = PushStructsNoZero(frame_arena, P_Delta *, input->cmds_count);
|
P_Delta **applied_user_deltas = PushStructsNoZero(frame_arena, P_Delta *, input->cmds.count);
|
||||||
for (P_CmdNode *cmd_node = input->first_cmd_node; cmd_node; cmd_node = cmd_node->next)
|
for (P_CmdNode *cmd_node = input->cmds.first; cmd_node; cmd_node = cmd_node->next)
|
||||||
{
|
{
|
||||||
P_Cmd *cmd = &cmd_node->cmd;
|
P_Cmd *cmd = &cmd_node->cmd;
|
||||||
if (cmd->kind == P_CmdKind_Delta)
|
if (cmd->kind == P_CmdKind_Delta)
|
||||||
@ -176,7 +180,20 @@ void S_TickForever(WaveLaneCtx *lane)
|
|||||||
}
|
}
|
||||||
if (allow)
|
if (allow)
|
||||||
{
|
{
|
||||||
P_UpdateWorldFromDelta(world_arena, world, delta);
|
P_DeltaNode tmp_delta_node = Zi;
|
||||||
|
tmp_delta_node.delta = *delta;
|
||||||
|
|
||||||
|
P_SnapshotNode tmp_snapshot_node = Zi;
|
||||||
|
tmp_snapshot_node.snapshot.deltas_count = 1;
|
||||||
|
tmp_snapshot_node.snapshot.first_delta_node = &tmp_delta_node;
|
||||||
|
tmp_snapshot_node.snapshot.last_delta_node = &tmp_delta_node;
|
||||||
|
|
||||||
|
P_SnapshotList tmp_snapshot_list = Zi;
|
||||||
|
tmp_snapshot_list.count = 1;
|
||||||
|
tmp_snapshot_list.first = &tmp_snapshot_node;
|
||||||
|
tmp_snapshot_list.last = &tmp_snapshot_node;
|
||||||
|
|
||||||
|
P_UpdateWorldFromSnapshots(world, tmp_snapshot_list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -184,18 +201,20 @@ void S_TickForever(WaveLaneCtx *lane)
|
|||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Update ent controls
|
//- Update ent controls
|
||||||
|
|
||||||
for (P_Ent *ent = P_FirstEnt(world); ent->valid; ent = P_NextEnt(ent))
|
// FIXME: Only apply relevant cmds based on tick
|
||||||
|
|
||||||
|
for (P_Ent *ent = P_FirstEnt(world_frame); !P_IsEntNil(ent); ent = P_NextEnt(ent))
|
||||||
{
|
{
|
||||||
ent->fire_presses = 0;
|
ent->fire_presses = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (P_CmdNode *cmd_node = input->first_cmd_node; cmd_node; cmd_node = cmd_node->next)
|
for (P_CmdNode *cmd_node = input->cmds.first; cmd_node; cmd_node = cmd_node->next)
|
||||||
{
|
{
|
||||||
P_Cmd cmd = cmd_node->cmd;
|
P_Cmd cmd = cmd_node->cmd;
|
||||||
if (cmd.kind == P_CmdKind_Control)
|
if (cmd.kind == P_CmdKind_Control)
|
||||||
{
|
{
|
||||||
P_Ent *target = P_EntFromKey(world, cmd.target);
|
P_Ent *target = P_EntFromKey(world_frame, cmd.target);
|
||||||
if (target->valid)
|
if (!P_IsEntNil(target))
|
||||||
{
|
{
|
||||||
target->move = ClampVec2Len(cmd.move, 1);
|
target->move = ClampVec2Len(cmd.move, 1);
|
||||||
target->look = cmd.look;
|
target->look = cmd.look;
|
||||||
@ -212,7 +231,7 @@ void S_TickForever(WaveLaneCtx *lane)
|
|||||||
// //////////////////////////////
|
// //////////////////////////////
|
||||||
// //- Push bullets
|
// //- Push bullets
|
||||||
|
|
||||||
// for (P_Ent *ent = P_FirstEnt(world); ent->valid; ent = P_NextEnt(ent))
|
// for (P_Ent *ent = P_FirstEnt(world_frame); !P_IsEntNil(ent); ent = P_NextEnt(ent))
|
||||||
// {
|
// {
|
||||||
// if (ent->fire_held)
|
// if (ent->fire_held)
|
||||||
// {
|
// {
|
||||||
@ -227,7 +246,7 @@ void S_TickForever(WaveLaneCtx *lane)
|
|||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Integrate control forces
|
//- Integrate control forces
|
||||||
|
|
||||||
for (P_Ent *ent = P_FirstEnt(world); ent->valid; ent = P_NextEnt(ent))
|
for (P_Ent *ent = P_FirstEnt(world_frame); !P_IsEntNil(ent); ent = P_NextEnt(ent))
|
||||||
{
|
{
|
||||||
// Xform xf = ent->xf;
|
// Xform xf = ent->xf;
|
||||||
// Xform desired_xf = xf;
|
// Xform desired_xf = xf;
|
||||||
@ -300,10 +319,10 @@ void S_TickForever(WaveLaneCtx *lane)
|
|||||||
constraints = PushStructs(frame_arena, P_Constraint, max_constraints);
|
constraints = PushStructs(frame_arena, P_Constraint, max_constraints);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (P_Ent *ent0 = P_FirstEnt(world); ent0->valid; ent0 = P_NextEnt(ent0))
|
for (P_Ent *ent0 = P_FirstEnt(world_frame); !P_IsEntNil(ent0); ent0 = P_NextEnt(ent0))
|
||||||
{
|
{
|
||||||
P_Shape shape0 = P_WorldShapeFromEnt(ent0);
|
P_Shape shape0 = P_WorldShapeFromEnt(ent0);
|
||||||
for (P_Ent *ent1 = P_FirstEnt(world); ent1->valid; ent1 = P_NextEnt(ent1))
|
for (P_Ent *ent1 = P_FirstEnt(world_frame); !P_IsEntNil(ent1); ent1 = P_NextEnt(ent1))
|
||||||
{
|
{
|
||||||
if (ent1 > ent0)
|
if (ent1 > ent0)
|
||||||
{
|
{
|
||||||
@ -338,7 +357,7 @@ void S_TickForever(WaveLaneCtx *lane)
|
|||||||
}
|
}
|
||||||
if (constraint)
|
if (constraint)
|
||||||
{
|
{
|
||||||
constraint->last_touched_tick = world->tick;
|
constraint->last_touched_tick = world_frame->tick;
|
||||||
constraint->normal = collision.collision_normal;
|
constraint->normal = collision.collision_normal;
|
||||||
// constraint->friction = SqrtF32(ent0->friction * ent1->friction);
|
// constraint->friction = SqrtF32(ent0->friction * ent1->friction);
|
||||||
constraint->friction = 0;
|
constraint->friction = 0;
|
||||||
@ -416,13 +435,13 @@ void S_TickForever(WaveLaneCtx *lane)
|
|||||||
|
|
||||||
// // Debug draw
|
// // Debug draw
|
||||||
// {
|
// {
|
||||||
// // P_Ent *ent0 = P_EntFromKey(world, constraint->ent0);
|
// // P_Ent *ent0 = P_EntFromKey(world_frame, constraint->ent0);
|
||||||
// // P_Ent *ent1 = P_EntFromKey(world, constraint->ent1);
|
// // P_Ent *ent1 = P_EntFromKey(world_frame, constraint->ent1);
|
||||||
// Vec2 normal = constraint->normal;
|
// Vec2 normal = constraint->normal;
|
||||||
// Vec2 center0 = Zi;
|
// Vec2 center0 = Zi;
|
||||||
// Vec2 center1 = Zi;
|
// Vec2 center1 = Zi;
|
||||||
// if (ent0->valid) center0 = P_WorldShapeFromEnt(ent0).center_of_mass;
|
// if (!P_IsEntNil(ent0)) center0 = P_WorldShapeFromEnt(ent0).center_of_mass;
|
||||||
// if (ent1->valid) center1 = P_WorldShapeFromEnt(ent1).center_of_mass;
|
// if (!P_IsEntNil(ent1)) center1 = P_WorldShapeFromEnt(ent1).center_of_mass;
|
||||||
// Vec2 p0 = AddVec2(center0, vcp0);
|
// Vec2 p0 = AddVec2(center0, vcp0);
|
||||||
// Vec2 p1 = AddVec2(center1, vcp1);
|
// Vec2 p1 = AddVec2(center1, vcp1);
|
||||||
// P_DebugDrawPoint(p0, Color_Cyan);
|
// P_DebugDrawPoint(p0, Color_Cyan);
|
||||||
@ -457,15 +476,15 @@ void S_TickForever(WaveLaneCtx *lane)
|
|||||||
// constraints = PushStructs(frame_arena, P_Constraint, max_constraints);
|
// constraints = PushStructs(frame_arena, P_Constraint, max_constraints);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// for (P_Ent *ent = P_FirstEnt(world); ent->valid; ent = P_NextEnt(ent))
|
// for (P_Ent *ent = P_FirstEnt(world_frame); !P_IsEntNil(ent); ent = P_NextEnt(ent))
|
||||||
// {
|
// {
|
||||||
// if (ent->is_player)
|
// if (ent->is_player)
|
||||||
// {
|
// {
|
||||||
// Xform last_xf = ent->last_xf;
|
// Xform prev_xf = ent->prev_xf;
|
||||||
// Xform xf = ent->xf;
|
// Xform xf = ent->xf;
|
||||||
|
|
||||||
// P_Shape local_shape = P_LocalShapeFromEnt(ent);
|
// P_Shape local_shape = P_LocalShapeFromEnt(ent);
|
||||||
// P_Shape last_world_shape = P_MulXformShape(last_xf, local_shape);
|
// P_Shape last_world_shape = P_MulXformShape(prev_xf, local_shape);
|
||||||
// P_Shape shape0 = P_WorldShapeFromEnt(ent);
|
// P_Shape shape0 = P_WorldShapeFromEnt(ent);
|
||||||
|
|
||||||
// // TODO: Real constraint data
|
// // TODO: Real constraint data
|
||||||
@ -514,7 +533,7 @@ void S_TickForever(WaveLaneCtx *lane)
|
|||||||
// }
|
// }
|
||||||
// if (constraint)
|
// if (constraint)
|
||||||
// {
|
// {
|
||||||
// constraint->last_touched_tick = world->tick;
|
// constraint->last_touched_tick = world_frame->tick;
|
||||||
// constraint->normal = collision.collision_normal;
|
// constraint->normal = collision.collision_normal;
|
||||||
|
|
||||||
// // TODO: Real masses
|
// // TODO: Real masses
|
||||||
@ -589,13 +608,13 @@ void S_TickForever(WaveLaneCtx *lane)
|
|||||||
|
|
||||||
// // Debug draw
|
// // Debug draw
|
||||||
// {
|
// {
|
||||||
// P_Ent *ent0 = P_EntFromKey(world, constraint->ent0);
|
// P_Ent *ent0 = P_EntFromKey(world_frame, constraint->ent0);
|
||||||
// P_Ent *ent1 = P_EntFromKey(world, constraint->ent1);
|
// P_Ent *ent1 = P_EntFromKey(world_frame, constraint->ent1);
|
||||||
// Vec2 normal = constraint->normal;
|
// Vec2 normal = constraint->normal;
|
||||||
// Vec2 center0 = Zi;
|
// Vec2 center0 = Zi;
|
||||||
// Vec2 center1 = Zi;
|
// Vec2 center1 = Zi;
|
||||||
// if (ent0->valid) center0 = P_WorldShapeFromEnt(ent0).center_of_mass;
|
// if (!P_IsEntNil(ent0)) center0 = P_WorldShapeFromEnt(ent0).center_of_mass;
|
||||||
// if (ent1->valid) center1 = P_WorldShapeFromEnt(ent1).center_of_mass;
|
// if (!P_IsEntNil(ent1)) center1 = P_WorldShapeFromEnt(ent1).center_of_mass;
|
||||||
// Vec2 p0 = AddVec2(center0, vcp0);
|
// Vec2 p0 = AddVec2(center0, vcp0);
|
||||||
// Vec2 p1 = AddVec2(center1, vcp1);
|
// Vec2 p1 = AddVec2(center1, vcp1);
|
||||||
// P_DebugDrawPoint(p0, Color_Cyan);
|
// P_DebugDrawPoint(p0, Color_Cyan);
|
||||||
@ -616,9 +635,11 @@ void S_TickForever(WaveLaneCtx *lane)
|
|||||||
{
|
{
|
||||||
P_Constraint *constraint = &constraints[constraint_idx];
|
P_Constraint *constraint = &constraints[constraint_idx];
|
||||||
b32 prune = 1;
|
b32 prune = 1;
|
||||||
if (constraint->last_touched_tick == world->tick)
|
if (constraint->last_touched_tick == world_frame->tick)
|
||||||
{
|
{
|
||||||
if (P_EntFromKey(world, constraint->ent0)->valid || P_EntFromKey(world, constraint->ent1)->valid)
|
P_Ent *ent0 = P_EntFromKey(world_frame, constraint->ent0);
|
||||||
|
P_Ent *ent1 = P_EntFromKey(world_frame, constraint->ent1);
|
||||||
|
if (!P_IsEntNil(ent0) && !P_IsEntNil(ent1))
|
||||||
{
|
{
|
||||||
prune = 0;
|
prune = 0;
|
||||||
}
|
}
|
||||||
@ -691,8 +712,8 @@ void S_TickForever(WaveLaneCtx *lane)
|
|||||||
{
|
{
|
||||||
P_Constraint *constraint = &constraints[constraint_idx];
|
P_Constraint *constraint = &constraints[constraint_idx];
|
||||||
|
|
||||||
P_Ent *ent0 = P_EntFromKey(world, constraint->ent0);
|
P_Ent *ent0 = P_EntFromKey(world_frame, constraint->ent0);
|
||||||
P_Ent *ent1 = P_EntFromKey(world, constraint->ent1);
|
P_Ent *ent1 = P_EntFromKey(world_frame, constraint->ent1);
|
||||||
|
|
||||||
Vec2 v0 = ent0->solved_v;
|
Vec2 v0 = ent0->solved_v;
|
||||||
Vec2 v1 = ent1->solved_v;
|
Vec2 v1 = ent1->solved_v;
|
||||||
@ -716,12 +737,12 @@ void S_TickForever(WaveLaneCtx *lane)
|
|||||||
w1 += WedgeVec2(vcp1, impulse) * constraint->inv_i1;
|
w1 += WedgeVec2(vcp1, impulse) * constraint->inv_i1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ent0->valid)
|
if (!P_IsEntNil(ent0))
|
||||||
{
|
{
|
||||||
ent0->solved_v = v0;
|
ent0->solved_v = v0;
|
||||||
ent0->solved_w = w0;
|
ent0->solved_w = w0;
|
||||||
}
|
}
|
||||||
if (ent1->valid)
|
if (!P_IsEntNil(ent1))
|
||||||
{
|
{
|
||||||
ent1->solved_v = v1;
|
ent1->solved_v = v1;
|
||||||
ent1->solved_w = w1;
|
ent1->solved_w = w1;
|
||||||
@ -735,8 +756,8 @@ void S_TickForever(WaveLaneCtx *lane)
|
|||||||
{
|
{
|
||||||
P_Constraint *constraint = &constraints[constraint_idx];
|
P_Constraint *constraint = &constraints[constraint_idx];
|
||||||
|
|
||||||
P_Ent *ent0 = P_EntFromKey(world, constraint->ent0);
|
P_Ent *ent0 = P_EntFromKey(world_frame, constraint->ent0);
|
||||||
P_Ent *ent1 = P_EntFromKey(world, constraint->ent1);
|
P_Ent *ent1 = P_EntFromKey(world_frame, constraint->ent1);
|
||||||
|
|
||||||
f32 inv_m0 = constraint->inv_m0;
|
f32 inv_m0 = constraint->inv_m0;
|
||||||
f32 inv_m1 = constraint->inv_m1;
|
f32 inv_m1 = constraint->inv_m1;
|
||||||
@ -749,11 +770,11 @@ void S_TickForever(WaveLaneCtx *lane)
|
|||||||
|
|
||||||
Vec2 center0 = constraint->static_center0;
|
Vec2 center0 = constraint->static_center0;
|
||||||
Vec2 center1 = constraint->static_center1;
|
Vec2 center1 = constraint->static_center1;
|
||||||
if (ent0->valid)
|
if (!P_IsEntNil(ent0))
|
||||||
{
|
{
|
||||||
center0 = P_WorldShapeFromEnt(ent0).center_of_mass;
|
center0 = P_WorldShapeFromEnt(ent0).center_of_mass;
|
||||||
}
|
}
|
||||||
if (ent1->valid)
|
if (!P_IsEntNil(ent1))
|
||||||
{
|
{
|
||||||
center1 = P_WorldShapeFromEnt(ent1).center_of_mass;
|
center1 = P_WorldShapeFromEnt(ent1).center_of_mass;
|
||||||
}
|
}
|
||||||
@ -844,12 +865,12 @@ void S_TickForever(WaveLaneCtx *lane)
|
|||||||
w1 += WedgeVec2(vcp1, impulse) * inv_i1;
|
w1 += WedgeVec2(vcp1, impulse) * inv_i1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ent0->valid)
|
if (!P_IsEntNil(ent0))
|
||||||
{
|
{
|
||||||
ent0->solved_v = v0;
|
ent0->solved_v = v0;
|
||||||
ent0->solved_w = w0;
|
ent0->solved_w = w0;
|
||||||
}
|
}
|
||||||
if (ent1->valid)
|
if (!P_IsEntNil(ent1))
|
||||||
{
|
{
|
||||||
ent1->solved_v = v1;
|
ent1->solved_v = v1;
|
||||||
ent1->solved_w = w1;
|
ent1->solved_w = w1;
|
||||||
@ -859,7 +880,7 @@ void S_TickForever(WaveLaneCtx *lane)
|
|||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Integrate velocities
|
//- Integrate velocities
|
||||||
|
|
||||||
for (P_Ent *ent = P_FirstEnt(world); ent->valid; ent = P_NextEnt(ent))
|
for (P_Ent *ent = P_FirstEnt(world_frame); !P_IsEntNil(ent); ent = P_NextEnt(ent))
|
||||||
{
|
{
|
||||||
Xform xf = ent->xf;
|
Xform xf = ent->xf;
|
||||||
xf.og = AddVec2(xf.og, MulVec2(ent->solved_v, solver_dt));
|
xf.og = AddVec2(xf.og, MulVec2(ent->solved_v, solver_dt));
|
||||||
@ -884,7 +905,7 @@ void S_TickForever(WaveLaneCtx *lane)
|
|||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Move bullets
|
//- Move bullets
|
||||||
|
|
||||||
for (P_Ent *bullet = P_FirstEnt(world); bullet->valid; bullet = P_NextEnt(bullet))
|
for (P_Ent *bullet = P_FirstEnt(world_frame); !P_IsEntNil(bullet); bullet = P_NextEnt(bullet))
|
||||||
{
|
{
|
||||||
if (bullet->is_bullet)
|
if (bullet->is_bullet)
|
||||||
{
|
{
|
||||||
@ -903,12 +924,12 @@ void S_TickForever(WaveLaneCtx *lane)
|
|||||||
|
|
||||||
{
|
{
|
||||||
P_EntList bullets_to_spawn = Zi;
|
P_EntList bullets_to_spawn = Zi;
|
||||||
for (P_Ent *firer = P_FirstEnt(world); firer->valid; firer = P_NextEnt(firer))
|
for (P_Ent *firer = P_FirstEnt(world_frame); !P_IsEntNil(firer); firer = P_NextEnt(firer))
|
||||||
{
|
{
|
||||||
if (firer->fire_held)
|
if (firer->fire_held)
|
||||||
// if (firer->fire_presses)
|
// if (firer->fire_presses)
|
||||||
{
|
{
|
||||||
// i64 fire_delta_ns = world->time_ns - firer->last_fire_ns;
|
// i64 fire_delta_ns = world_frame->time_ns - firer->last_fire_ns;
|
||||||
|
|
||||||
// i64 single_bullet_delta_ns = NsFromSeconds(1) / firer->fire_rate;
|
// i64 single_bullet_delta_ns = NsFromSeconds(1) / firer->fire_rate;
|
||||||
|
|
||||||
@ -920,7 +941,7 @@ void S_TickForever(WaveLaneCtx *lane)
|
|||||||
f32 spread = Tau * 0.01;
|
f32 spread = Tau * 0.01;
|
||||||
f32 tweak_speed = TweakFloat("Bullet speed", 100, 1, 100);
|
f32 tweak_speed = TweakFloat("Bullet speed", 100, 1, 100);
|
||||||
|
|
||||||
b32 can_fire = (firer->last_fire_ns + NsFromSeconds(1.0 / fire_rate)) <= world->time_ns;
|
b32 can_fire = (firer->last_fire_ns + NsFromSeconds(1.0 / fire_rate)) <= world_frame->time_ns;
|
||||||
if (can_fire)
|
if (can_fire)
|
||||||
{
|
{
|
||||||
i64 tick_bullets_count = bullets_per_fire;
|
i64 tick_bullets_count = bullets_per_fire;
|
||||||
@ -955,11 +976,11 @@ void S_TickForever(WaveLaneCtx *lane)
|
|||||||
bullet->bullet_firer = firer->key;
|
bullet->bullet_firer = firer->key;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
firer->last_fire_ns = world->time_ns;
|
firer->last_fire_ns = world_frame->time_ns;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
P_SpawnEntsFromList(world_arena, world, bullets_to_spawn);
|
P_SpawnEntsFromList(world_frame, bullets_to_spawn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -970,7 +991,7 @@ void S_TickForever(WaveLaneCtx *lane)
|
|||||||
|
|
||||||
// TODO: Separate 'hits' from bullets, so that bullets can have multiple hits
|
// TODO: Separate 'hits' from bullets, so that bullets can have multiple hits
|
||||||
|
|
||||||
for (P_Ent *bullet = P_FirstEnt(world); bullet->valid; bullet = P_NextEnt(bullet))
|
for (P_Ent *bullet = P_FirstEnt(world_frame); !P_IsEntNil(bullet); bullet = P_NextEnt(bullet))
|
||||||
{
|
{
|
||||||
if (bullet->is_bullet)
|
if (bullet->is_bullet)
|
||||||
{
|
{
|
||||||
@ -984,7 +1005,7 @@ void S_TickForever(WaveLaneCtx *lane)
|
|||||||
P_RaycastResult victim_raycast = Zi;
|
P_RaycastResult victim_raycast = Zi;
|
||||||
{
|
{
|
||||||
f32 closest_len_sq = Inf;
|
f32 closest_len_sq = Inf;
|
||||||
for (P_Ent *victim = P_FirstEnt(world); victim->valid; victim = P_NextEnt(victim))
|
for (P_Ent *victim = P_FirstEnt(world_frame); !P_IsEntNil(victim); victim = P_NextEnt(victim))
|
||||||
{
|
{
|
||||||
if (victim->is_player && !P_MatchKey(victim->key, bullet->bullet_firer))
|
if (victim->is_player && !P_MatchKey(victim->key, bullet->bullet_firer))
|
||||||
{
|
{
|
||||||
@ -1013,7 +1034,7 @@ void S_TickForever(WaveLaneCtx *lane)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (closest_victim->valid)
|
if (!P_IsEntNil(closest_victim))
|
||||||
{
|
{
|
||||||
bullet->has_hit = 1;
|
bullet->has_hit = 1;
|
||||||
bullet->hit_entry = victim_raycast.p;
|
bullet->hit_entry = victim_raycast.p;
|
||||||
@ -1064,12 +1085,12 @@ void S_TickForever(WaveLaneCtx *lane)
|
|||||||
// P_Bullet *bullet = &bullets[bullet_idx];
|
// P_Bullet *bullet = &bullets[bullet_idx];
|
||||||
|
|
||||||
// // Raycast
|
// // Raycast
|
||||||
// for (P_Ent *ent = P_FirstEnt(world); ent->valid; ent = P_NextEnt(ent))
|
// for (P_Ent *ent = P_FirstEnt(world_frame); !P_IsEntNil(ent); ent = P_NextEnt(ent))
|
||||||
// {
|
// {
|
||||||
// Xform xf = ent->xf;
|
// Xform xf = ent->xf;
|
||||||
// P_Shape world_shape = P_MulXformShape(xf, ent->local_shape);
|
// P_Shape world_shape = P_MulXformShape(xf, ent->local_shape);
|
||||||
|
|
||||||
// if (ent == P_FirstEnt(world))
|
// if (ent == P_FirstEnt(world_frame))
|
||||||
// {
|
// {
|
||||||
// bullet->start = AddVec2(world_shape.centroid, Vec2WithLen(ent->look, world_shape.radius));
|
// bullet->start = AddVec2(world_shape.centroid, Vec2WithLen(ent->look, world_shape.radius));
|
||||||
// bullet->dir = NormVec2(ent->look);
|
// bullet->dir = NormVec2(ent->look);
|
||||||
@ -1123,12 +1144,12 @@ void S_TickForever(WaveLaneCtx *lane)
|
|||||||
// // P_Bullet *bullet = &bullets[bullet_idx];
|
// // P_Bullet *bullet = &bullets[bullet_idx];
|
||||||
|
|
||||||
// // // Raycast
|
// // // Raycast
|
||||||
// // for (P_Ent *ent = P_FirstEnt(world); ent->valid; ent = P_NextEnt(ent))
|
// // for (P_Ent *ent = P_FirstEnt(world_frame); !P_IsEntNil(ent); ent = P_NextEnt(ent))
|
||||||
// // {
|
// // {
|
||||||
// // Xform xf = ent->xf;
|
// // Xform xf = ent->xf;
|
||||||
// // P_Shape world_shape = P_MulXformShape(xf, ent->local_shape);
|
// // P_Shape world_shape = P_MulXformShape(xf, ent->local_shape);
|
||||||
|
|
||||||
// // if (ent == P_FirstEnt(world))
|
// // if (ent == P_FirstEnt(world_frame))
|
||||||
// // {
|
// // {
|
||||||
// // bullet->start = AddVec2(world_shape.centroid, Vec2WithLen(ent->look, world_shape.radius));
|
// // bullet->start = AddVec2(world_shape.centroid, Vec2WithLen(ent->look, world_shape.radius));
|
||||||
// // bullet->dir = NormVec2(ent->look);
|
// // bullet->dir = NormVec2(ent->look);
|
||||||
@ -1164,7 +1185,7 @@ void S_TickForever(WaveLaneCtx *lane)
|
|||||||
|
|
||||||
if (P_tl.debug_draw_enabled)
|
if (P_tl.debug_draw_enabled)
|
||||||
{
|
{
|
||||||
for (P_Ent *ent = P_FirstEnt(world); ent->valid; ent = P_NextEnt(ent))
|
for (P_Ent *ent = P_FirstEnt(world_frame); !P_IsEntNil(ent); ent = P_NextEnt(ent))
|
||||||
{
|
{
|
||||||
P_Shape world_shape = P_WorldShapeFromEnt(ent);
|
P_Shape world_shape = P_WorldShapeFromEnt(ent);
|
||||||
|
|
||||||
@ -1209,12 +1230,12 @@ void S_TickForever(WaveLaneCtx *lane)
|
|||||||
P_OutputState *output = &P.sim_output_states[P.sim_output_back_idx];
|
P_OutputState *output = &P.sim_output_states[P.sim_output_back_idx];
|
||||||
P_SnapshotNode *snapshot_node = PushStruct(output->arena, P_SnapshotNode);
|
P_SnapshotNode *snapshot_node = PushStruct(output->arena, P_SnapshotNode);
|
||||||
P_Snapshot *snapshot = &snapshot_node->snapshot;
|
P_Snapshot *snapshot = &snapshot_node->snapshot;
|
||||||
SllQueuePush(output->first_snapshot_node, output->last_snapshot_node, snapshot_node);
|
SllQueuePush(output->snapshots.first, output->snapshots.last, snapshot_node);
|
||||||
++output->snapshots_count;
|
++output->snapshots.count;
|
||||||
|
|
||||||
snapshot->seed = world->seed;
|
snapshot->world_seed = world->seed;
|
||||||
snapshot->tick = world->tick;
|
snapshot->tick = world_frame->tick;
|
||||||
snapshot->time_ns = world->time_ns;
|
snapshot->time_ns = world_frame->time_ns;
|
||||||
|
|
||||||
// Forward user edit deltas
|
// Forward user edit deltas
|
||||||
for (i64 applied_user_delta_idx = 0; applied_user_delta_idx < applied_user_deltas_count; ++applied_user_delta_idx)
|
for (i64 applied_user_delta_idx = 0; applied_user_delta_idx < applied_user_deltas_count; ++applied_user_delta_idx)
|
||||||
@ -1248,7 +1269,7 @@ void S_TickForever(WaveLaneCtx *lane)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Push raw entity deltas
|
// Push raw entity deltas
|
||||||
for (P_Ent *ent = P_FirstEnt(world); ent->valid; ent = P_NextEnt(ent))
|
for (P_Ent *ent = P_FirstEnt(world_frame); !P_IsEntNil(ent); ent = P_NextEnt(ent))
|
||||||
{
|
{
|
||||||
P_Delta *delta = 0;
|
P_Delta *delta = 0;
|
||||||
{
|
{
|
||||||
@ -1287,8 +1308,8 @@ void S_TickForever(WaveLaneCtx *lane)
|
|||||||
|
|
||||||
{
|
{
|
||||||
i64 ents_to_prune_count = 0;
|
i64 ents_to_prune_count = 0;
|
||||||
P_Ent **ents_to_prune = PushStructsNoZero(frame_arena, P_Ent *, world->ents_count);
|
P_Ent **ents_to_prune = PushStructsNoZero(frame_arena, P_Ent *, world_frame->ents_count);
|
||||||
for (P_Ent *ent = P_FirstEnt(world); ent->valid; ent = P_NextEnt(ent))
|
for (P_Ent *ent = P_FirstEnt(world_frame); !P_IsEntNil(ent); ent = P_NextEnt(ent))
|
||||||
{
|
{
|
||||||
if (ent->exists <= 0)
|
if (ent->exists <= 0)
|
||||||
{
|
{
|
||||||
@ -1302,10 +1323,10 @@ void S_TickForever(WaveLaneCtx *lane)
|
|||||||
// FIXME: Add to freelist
|
// FIXME: Add to freelist
|
||||||
// FIXME: Ensure sure prunes are received by user
|
// FIXME: Ensure sure prunes are received by user
|
||||||
P_Ent *ent = ents_to_prune[prune_idx];
|
P_Ent *ent = ents_to_prune[prune_idx];
|
||||||
P_EntBin *bin = &world->ent_bins[ent->key.v % world->ent_bins_count];
|
P_EntBin *bin = &world_frame->ent_bins[ent->key.v % world_frame->ent_bins_count];
|
||||||
DllQueueRemoveNP(bin->first, bin->last, ent, next_in_bin, prev_in_bin);
|
DllQueueRemoveNP(bin->first, bin->last, ent, next_in_bin, prev_in_bin);
|
||||||
DllQueueRemove(world->first_ent, world->last_ent, ent);
|
DllQueueRemove(world_frame->first_ent, world_frame->last_ent, ent);
|
||||||
world->ents_count -= 1;
|
world_frame->ents_count -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1321,7 +1342,7 @@ void S_TickForever(WaveLaneCtx *lane)
|
|||||||
}
|
}
|
||||||
|
|
||||||
i64 frame_end_ns = TimeNs();
|
i64 frame_end_ns = TimeNs();
|
||||||
world->time_ns += sim_dt_ns;
|
world_frame->time_ns += sim_dt_ns;
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Sleep
|
//- Sleep
|
||||||
|
|||||||
@ -6,19 +6,20 @@ String P_PackWorld(Arena *arena, P_World *src_world)
|
|||||||
String result = Zi;
|
String result = Zi;
|
||||||
result.text = ArenaNext(arena, u8);
|
result.text = ArenaNext(arena, u8);
|
||||||
TempArena scratch = BeginScratch(arena);
|
TempArena scratch = BeginScratch(arena);
|
||||||
|
P_Frame *src_frame = src_world->last_frame;
|
||||||
|
|
||||||
result.len += StringF(arena, "version: %F\n", FmtUint(P_Tv_Latest)).len;
|
result.len += StringF(arena, "version: %F\n", FmtUint(P_Tv_Latest)).len;
|
||||||
|
|
||||||
result.len += StringF(arena, "\n").len;
|
result.len += StringF(arena, "\n").len;
|
||||||
result.len += StringF(arena, "seed: 0x%F\n", FmtHex(src_world->seed)).len;
|
result.len += StringF(arena, "seed: 0x%F\n", FmtHex(src_world->seed)).len;
|
||||||
result.len += StringF(arena, "tick: %F\n", FmtSint(src_world->tick)).len;
|
result.len += StringF(arena, "tick: %F\n", FmtSint(src_frame->tick)).len;
|
||||||
result.len += StringF(arena, "time: %F\n", FmtSint(src_world->time_ns)).len;
|
result.len += StringF(arena, "time: %F\n", FmtSint(src_frame->time_ns)).len;
|
||||||
|
|
||||||
// Pack entities
|
// Pack entities
|
||||||
// FIXME: Precision
|
// FIXME: Precision
|
||||||
result.len += PushString(arena, Lit("\nentities:\n")).len;
|
result.len += PushString(arena, Lit("\nentities:\n")).len;
|
||||||
result.len += PushString(arena, Lit("{\n")).len;
|
result.len += PushString(arena, Lit("{\n")).len;
|
||||||
for (P_Ent *ent = P_FirstEnt(src_world); ent->valid; ent = P_NextEnt(ent))
|
for (P_Ent *ent = P_FirstEnt(src_frame); !P_IsEntNil(ent); ent = P_NextEnt(ent))
|
||||||
{
|
{
|
||||||
// TODO: Pack bullets
|
// TODO: Pack bullets
|
||||||
if (!ent->is_bullet)
|
if (!ent->is_bullet)
|
||||||
|
|||||||
@ -43,11 +43,12 @@ V_Cmd *V_PushVisCmd(String name)
|
|||||||
|
|
||||||
P_Cmd *V_PushSimCmd(P_CmdKind kind)
|
P_Cmd *V_PushSimCmd(P_CmdKind kind)
|
||||||
{
|
{
|
||||||
V_Frame *frame = V_CurrentFrame();
|
// FIXME: Free list
|
||||||
P_CmdNode *n = PushStruct(frame->arena, P_CmdNode);
|
Arena *perm = PermArena();
|
||||||
|
P_CmdNode *n = PushStruct(perm, P_CmdNode);
|
||||||
n->cmd.kind = kind;
|
n->cmd.kind = kind;
|
||||||
SllQueuePush(frame->first_sim_cmd_node, frame->last_sim_cmd_node, n);
|
SllQueuePush(V.sim_cmds.first, V.sim_cmds.last, n);
|
||||||
++frame->sim_cmds_count;
|
++V.sim_cmds.count;
|
||||||
return &n->cmd;
|
return &n->cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -340,11 +341,9 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
P_DebugDrawNode *first_sim_debug_draw_node = 0;
|
P_DebugDrawNode *first_sim_debug_draw_node = 0;
|
||||||
P_DebugDrawNode *last_sim_debug_draw_node = 0;
|
P_DebugDrawNode *last_sim_debug_draw_node = 0;
|
||||||
|
|
||||||
Arena *world_arena = AcquireArena(Gibi(64));
|
P_World *sim_world = P_AcquireWorld();
|
||||||
P_World *world = PushStruct(world_arena, P_World);
|
P_World *predict_world = P_AcquireWorld();
|
||||||
world->ent_bins_count = Kibi(16);
|
P_World *blend_world = P_AcquireWorld();
|
||||||
world->ent_bins = PushStructs(world_arena, P_EntBin, world->ent_bins_count);
|
|
||||||
world->tiles = PushStructs(world_arena, u8, P_TilesCount);
|
|
||||||
|
|
||||||
Vec2I32 tiles_dims = VEC2I32(P_TilesPitch, P_TilesPitch);
|
Vec2I32 tiles_dims = VEC2I32(P_TilesPitch, P_TilesPitch);
|
||||||
Vec2I32 cells_dims = VEC2I32(V_CellsPerMeter * P_WorldPitch, V_CellsPerMeter * P_WorldPitch);
|
Vec2I32 cells_dims = VEC2I32(V_CellsPerMeter * P_WorldPitch, V_CellsPerMeter * P_WorldPitch);
|
||||||
@ -471,7 +470,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
u64 hotkey_hash = HashFnv64(Fnv64Basis, StringFromStruct(&hotkey));
|
u64 hotkey_hash = HashString(StringFromStruct(&hotkey));
|
||||||
V_ShortcutBin *bin = &shortcut_bins[hotkey_hash % shortcut_bins_count];
|
V_ShortcutBin *bin = &shortcut_bins[hotkey_hash % shortcut_bins_count];
|
||||||
V_Shortcut *shortcut = PushStruct(perm, V_Shortcut);
|
V_Shortcut *shortcut = PushStruct(perm, V_Shortcut);
|
||||||
shortcut->hotkey_hash = hotkey_hash;
|
shortcut->hotkey_hash = hotkey_hash;
|
||||||
@ -632,54 +631,77 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
frame->ui_dims.y = MaxF32(frame->ui_dims.y, 64);
|
frame->ui_dims.y = MaxF32(frame->ui_dims.y, 64);
|
||||||
frame->draw_dims = frame->ui_dims;
|
frame->draw_dims = frame->ui_dims;
|
||||||
|
|
||||||
//////////////////////////////
|
// //////////////////////////////
|
||||||
//- Pop sim output
|
// //- Pop sim output
|
||||||
|
|
||||||
|
// P_OutputState *sim_output = 0;
|
||||||
|
// LockTicketMutex(&P.sim_output_back_tm);
|
||||||
|
// {
|
||||||
|
// sim_output = &P.sim_output_states[P.sim_output_back_idx];
|
||||||
|
// ++P.sim_output_back_idx;
|
||||||
|
// if (P.sim_output_back_idx >= countof(P.sim_output_states))
|
||||||
|
// {
|
||||||
|
// P.sim_output_back_idx = 0;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// UnlockTicketMutex(&P.sim_output_back_tm);
|
||||||
|
|
||||||
|
// //////////////////////////////
|
||||||
|
// //- Apply sim snapshots
|
||||||
|
|
||||||
|
// // FIXME: Only apply latest snapshot
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// // FIXME: Real ping
|
||||||
|
// i64 ping_ns = NsFromSeconds(0.250);
|
||||||
|
|
||||||
|
// // TODO: Remove this (testing)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// // b32 received_unseen_tick = 0;
|
||||||
|
// // b32 tiles_dirty = 0;
|
||||||
|
// // b32 should_clear_particles = 0;
|
||||||
|
// // for (P_SnapshotNode *n = sim_output->first_snapshot_node; n; n = n->next)
|
||||||
|
// // {
|
||||||
|
// // P_Snapshot *snapshot = &n->snapshot;
|
||||||
|
// // if (snapshot->tick > world->tick)
|
||||||
|
// // {
|
||||||
|
// // world->seed = snapshot->seed;
|
||||||
|
// // world->tick = snapshot->tick;
|
||||||
|
// // world->time_ns = snapshot->time_ns;
|
||||||
|
// // for (P_DeltaNode *dn = snapshot->first_delta_node; dn; dn = dn->next)
|
||||||
|
// // {
|
||||||
|
// // P_Delta *delta = &dn->delta;
|
||||||
|
// // if (delta->kind == P_DeltaKind_Reset)
|
||||||
|
// // {
|
||||||
|
// // tiles_dirty = 1;
|
||||||
|
// // should_clear_particles = 1;
|
||||||
|
// // }
|
||||||
|
// // if (delta->kind == P_DeltaKind_RawTiles || delta->kind == P_DeltaKind_Tile)
|
||||||
|
// // {
|
||||||
|
// // tiles_dirty = 1;
|
||||||
|
// // }
|
||||||
|
// // P_UpdateWorldFromDelta(world, delta);
|
||||||
|
// // }
|
||||||
|
// // received_unseen_tick = 1;
|
||||||
|
// // }
|
||||||
|
// // }
|
||||||
|
|
||||||
|
|
||||||
|
// {
|
||||||
|
// P_SnapshotList sim_snapshots = sim_output->snapshots;
|
||||||
|
// P_UpdateWorldFromSnapshots(sim_world, sim_snapshots);
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
P_OutputState *sim_output = 0;
|
|
||||||
LockTicketMutex(&P.sim_output_back_tm);
|
|
||||||
{
|
|
||||||
sim_output = &P.sim_output_states[P.sim_output_back_idx];
|
|
||||||
++P.sim_output_back_idx;
|
|
||||||
if (P.sim_output_back_idx >= countof(P.sim_output_states))
|
|
||||||
{
|
|
||||||
P.sim_output_back_idx = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
UnlockTicketMutex(&P.sim_output_back_tm);
|
|
||||||
|
|
||||||
//////////////////////////////
|
|
||||||
//- Apply sim snapshots
|
|
||||||
|
|
||||||
// FIXME: Only apply latest snapshot
|
|
||||||
|
|
||||||
b32 received_unseen_tick = 0;
|
|
||||||
b32 tiles_dirty = 0;
|
|
||||||
b32 should_clear_particles = 0;
|
|
||||||
for (P_SnapshotNode *n = sim_output->first_snapshot_node; n; n = n->next)
|
|
||||||
{
|
|
||||||
P_Snapshot *snapshot = &n->snapshot;
|
|
||||||
if (snapshot->tick > world->tick)
|
|
||||||
{
|
|
||||||
world->seed = snapshot->seed;
|
|
||||||
world->tick = snapshot->tick;
|
|
||||||
world->time_ns = snapshot->time_ns;
|
|
||||||
for (P_DeltaNode *dn = snapshot->first_delta_node; dn; dn = dn->next)
|
|
||||||
{
|
|
||||||
P_Delta *delta = &dn->delta;
|
|
||||||
if (delta->kind == P_DeltaKind_Reset)
|
|
||||||
{
|
|
||||||
tiles_dirty = 1;
|
|
||||||
should_clear_particles = 1;
|
|
||||||
}
|
|
||||||
if (delta->kind == P_DeltaKind_RawTiles || delta->kind == P_DeltaKind_Tile)
|
|
||||||
{
|
|
||||||
tiles_dirty = 1;
|
|
||||||
}
|
|
||||||
P_UpdateWorldFromDelta(world_arena, world, delta);
|
|
||||||
}
|
|
||||||
received_unseen_tick = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// //////////////////////////////
|
// //////////////////////////////
|
||||||
// //- Update tiles from sim
|
// //- Update tiles from sim
|
||||||
@ -782,7 +804,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
hotkey.shift = frame->held_buttons[Button_Shift];
|
hotkey.shift = frame->held_buttons[Button_Shift];
|
||||||
hotkey.alt = frame->held_buttons[Button_Alt];
|
hotkey.alt = frame->held_buttons[Button_Alt];
|
||||||
{
|
{
|
||||||
u64 hotkey_hash = HashFnv64(Fnv64Basis, StringFromStruct(&hotkey));
|
u64 hotkey_hash = HashString(StringFromStruct(&hotkey));
|
||||||
V_ShortcutBin *bin = &shortcut_bins[hotkey_hash % shortcut_bins_count];
|
V_ShortcutBin *bin = &shortcut_bins[hotkey_hash % shortcut_bins_count];
|
||||||
V_Shortcut *shortcut = bin->first;
|
V_Shortcut *shortcut = bin->first;
|
||||||
for (; shortcut; shortcut = shortcut->next_in_bin)
|
for (; shortcut; shortcut = shortcut->next_in_bin)
|
||||||
@ -848,7 +870,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
Vec2 look_ratio = Zi;
|
Vec2 look_ratio = Zi;
|
||||||
look_ratio.y = 0.25;
|
look_ratio.y = 0.25;
|
||||||
look_ratio.x = look_ratio.y / (16.0 / 9.0);
|
look_ratio.x = look_ratio.y / (16.0 / 9.0);
|
||||||
P_Ent *player = P_EntFromKey(world, V.player_key);
|
P_Ent *player = P_EntFromKey(blend_world->last_frame, V.player_key);
|
||||||
target_camera_pos = P_WorldShapeFromEnt(player).centroid;
|
target_camera_pos = P_WorldShapeFromEnt(player).centroid;
|
||||||
target_camera_pos = AddVec2(target_camera_pos, MulVec2Vec2(player->look, look_ratio));
|
target_camera_pos = AddVec2(target_camera_pos, MulVec2Vec2(player->look, look_ratio));
|
||||||
target_camera_zoom = 1;
|
target_camera_zoom = 1;
|
||||||
@ -1001,12 +1023,12 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Query entities
|
//- Query entities
|
||||||
|
|
||||||
P_Ent *player = P_EntFromKey(world, V.player_key);
|
P_Ent *player = P_EntFromKey(blend_world->last_frame, V.player_key);
|
||||||
P_Ent *hovered_ent = &P_NilEnt;
|
P_Ent *hovered_ent = &P_NilEnt;
|
||||||
{
|
{
|
||||||
// TODO: Real world query
|
// TODO: Real world query
|
||||||
P_Shape cursor_shape = P_ShapeFromDesc(.count = 1, .points = { frame->world_cursor });
|
P_Shape cursor_shape = P_ShapeFromDesc(.count = 1, .points = { frame->world_cursor });
|
||||||
for (P_Ent *ent = P_FirstEnt(world); ent->valid; ent = P_NextEnt(ent))
|
for (P_Ent *ent = P_FirstEnt(blend_world->last_frame); !P_IsEntNil(ent); ent = P_NextEnt(ent))
|
||||||
{
|
{
|
||||||
P_Shape ent_shape = P_WorldShapeFromEnt(ent);
|
P_Shape ent_shape = P_WorldShapeFromEnt(ent);
|
||||||
b32 is_hovered = P_CollisionResultFromShapes(ent_shape, cursor_shape).collision_points_count > 0;
|
b32 is_hovered = P_CollisionResultFromShapes(ent_shape, cursor_shape).collision_points_count > 0;
|
||||||
@ -2212,8 +2234,8 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
{
|
{
|
||||||
UI_BuildSpacer(UI_PIX(padding, 1), Axis_Y);
|
UI_BuildSpacer(UI_PIX(padding, 1), Axis_Y);
|
||||||
{
|
{
|
||||||
UI_BuildLabelF("World seed: 0x%F", FmtHex(world->seed));
|
UI_BuildLabelF("World seed: 0x%F", FmtHex(blend_world->seed));
|
||||||
UI_BuildLabelF("Entities count: %F", FmtSint(world->ents_count));
|
UI_BuildLabelF("Entities count: %F", FmtSint(blend_world->last_frame->ents_count));
|
||||||
}
|
}
|
||||||
UI_BuildSpacer(UI_PIX(padding, 1), Axis_Y);
|
UI_BuildSpacer(UI_PIX(padding, 1), Axis_Y);
|
||||||
{
|
{
|
||||||
@ -2535,7 +2557,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
|
|
||||||
case V_CmdKind_delete:
|
case V_CmdKind_delete:
|
||||||
{
|
{
|
||||||
if (hovered_ent->valid)
|
if (!P_IsEntNil(hovered_ent))
|
||||||
{
|
{
|
||||||
P_Cmd *cmd = V_PushSimCmd(P_CmdKind_Delta);
|
P_Cmd *cmd = V_PushSimCmd(P_CmdKind_Delta);
|
||||||
cmd->delta.kind = P_DeltaKind_RawEnt;
|
cmd->delta.kind = P_DeltaKind_RawEnt;
|
||||||
@ -2553,10 +2575,10 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case V_CmdKind_clear_particles:
|
// case V_CmdKind_clear_particles:
|
||||||
{
|
// {
|
||||||
should_clear_particles = 1;
|
// should_clear_particles = 1;
|
||||||
} break;
|
// } break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2605,23 +2627,189 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
cmd->fire_presses = frame->fire_presses;
|
cmd->fire_presses = frame->fire_presses;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- Pop sim output
|
||||||
|
|
||||||
|
P_OutputState *sim_output = 0;
|
||||||
|
LockTicketMutex(&P.sim_output_back_tm);
|
||||||
|
{
|
||||||
|
sim_output = &P.sim_output_states[P.sim_output_back_idx];
|
||||||
|
++P.sim_output_back_idx;
|
||||||
|
if (P.sim_output_back_idx >= countof(P.sim_output_states))
|
||||||
|
{
|
||||||
|
P.sim_output_back_idx = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UnlockTicketMutex(&P.sim_output_back_tm);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- Apply sim snapshots
|
||||||
|
|
||||||
|
// FIXME: Only apply latest snapshot
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// FIXME: Real ping
|
||||||
|
i64 ping_ns = NsFromSeconds(0.250);
|
||||||
|
|
||||||
|
// TODO: Remove this (testing)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// b32 received_unseen_tick = 0;
|
||||||
|
// b32 tiles_dirty = 0;
|
||||||
|
// b32 should_clear_particles = 0;
|
||||||
|
// for (P_SnapshotNode *n = sim_output->first_snapshot_node; n; n = n->next)
|
||||||
|
// {
|
||||||
|
// P_Snapshot *snapshot = &n->snapshot;
|
||||||
|
// if (snapshot->tick > world->tick)
|
||||||
|
// {
|
||||||
|
// world->seed = snapshot->seed;
|
||||||
|
// world->tick = snapshot->tick;
|
||||||
|
// world->time_ns = snapshot->time_ns;
|
||||||
|
// for (P_DeltaNode *dn = snapshot->first_delta_node; dn; dn = dn->next)
|
||||||
|
// {
|
||||||
|
// P_Delta *delta = &dn->delta;
|
||||||
|
// if (delta->kind == P_DeltaKind_Reset)
|
||||||
|
// {
|
||||||
|
// tiles_dirty = 1;
|
||||||
|
// should_clear_particles = 1;
|
||||||
|
// }
|
||||||
|
// if (delta->kind == P_DeltaKind_RawTiles || delta->kind == P_DeltaKind_Tile)
|
||||||
|
// {
|
||||||
|
// tiles_dirty = 1;
|
||||||
|
// }
|
||||||
|
// P_UpdateWorldFromDelta(world, delta);
|
||||||
|
// }
|
||||||
|
// received_unseen_tick = 1;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// Apply snapshots to sim world
|
||||||
|
{
|
||||||
|
P_SnapshotList sim_snapshots = sim_output->snapshots;
|
||||||
|
P_UpdateWorldFromSnapshots(sim_world, sim_snapshots);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Submit sim commands
|
//- Submit sim commands
|
||||||
|
|
||||||
|
i64 predict_to = sim_world->last_frame->tick + 10;
|
||||||
|
|
||||||
LockTicketMutex(&P.sim_input_back_tm);
|
LockTicketMutex(&P.sim_input_back_tm);
|
||||||
{
|
{
|
||||||
P_InputState *v2s = &P.sim_input_states[P.sim_input_back_idx];
|
P_InputState *v2s = &P.sim_input_states[P.sim_input_back_idx];
|
||||||
for (P_CmdNode *src = frame->first_sim_cmd_node; src; src = src->next)
|
for (P_CmdNode *src = V.sim_cmds.first; src; src = src->next)
|
||||||
{
|
{
|
||||||
P_CmdNode *cmd_node = PushStruct(v2s->arena, P_CmdNode);
|
P_CmdNode *cmd_node = PushStruct(v2s->arena, P_CmdNode);
|
||||||
cmd_node->cmd = src->cmd;
|
cmd_node->cmd = src->cmd;
|
||||||
SllQueuePush(v2s->first_cmd_node, v2s->last_cmd_node, cmd_node);
|
cmd_node->cmd.tick = predict_to;
|
||||||
++v2s->cmds_count;
|
SllQueuePush(v2s->cmds.first, v2s->cmds.last, cmd_node);
|
||||||
|
++v2s->cmds.count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UnlockTicketMutex(&P.sim_input_back_tm);
|
UnlockTicketMutex(&P.sim_input_back_tm);
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- Predict
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: Only predict when new sim snapshot is received
|
||||||
|
|
||||||
|
// Predict
|
||||||
|
P_Frame *predict_frame = 0;
|
||||||
|
{
|
||||||
|
// i64 step_count = predict_to - sim_world->last_frame->tick;
|
||||||
|
|
||||||
|
// // TODO: Preserve constraints?
|
||||||
|
|
||||||
|
// P_ClearFrames(predict_world, I64Min, I64Max);
|
||||||
|
// P_Frame *base_predict_frame = P_PushFrame(predict_world, sim_world->last_frame, sim_world->last_frame->tick);
|
||||||
|
// P_Frame *prev_predict_frame = base_predict_frame;
|
||||||
|
// for (i64 step_idx = 0; step_idx < step_count; ++step_idx)
|
||||||
|
// {
|
||||||
|
// // P_CmdList step_cmds = V_StepCmdsFromTick(prev_predict_frame->tick + 1);
|
||||||
|
|
||||||
|
// P_CmdList step_cmds = Zi;
|
||||||
|
// for (P_CmdNode *src = V.sim_cmds.first; src; src = src->next)
|
||||||
|
// {
|
||||||
|
// P_CmdNode *n = PushStructNoZero(frame->arena, P_CmdNode);
|
||||||
|
// *n = *src;
|
||||||
|
// SllQueuePush(step_cmds.first, step_cmds.last, n);
|
||||||
|
// ++step_cmds.count;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// P_Frame *stepped = P_StepWorld(predict_world, prev_predict_frame, step_cmds);
|
||||||
|
// prev_predict_frame = stepped;
|
||||||
|
// }
|
||||||
|
|
||||||
|
predict_frame = sim_world->last_frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- Update blended world
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: Remove this
|
||||||
|
P_Frame *blend_frame = 0;
|
||||||
|
{
|
||||||
|
// P_ResetWorldFromFrame(blended_world, predict_world->last_frame);
|
||||||
|
// P_Frame *blend_frame = blended_world->last_frame;
|
||||||
|
blend_frame = predict_frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// FIXME: Compare tile hashes
|
||||||
|
b32 tiles_dirty = 0;
|
||||||
|
b32 should_clear_particles = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// {
|
||||||
|
// i64 delay_ns = NsFromSeconds(100);
|
||||||
|
|
||||||
|
// P_Frame *right_frame = &P_NilFrame;
|
||||||
|
// P_Frame *left_frame = &P_NilFrame;
|
||||||
|
|
||||||
|
// for (P_Frame *tmp =
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// P_Frame *right_frame = predict_world->last_frame;
|
||||||
|
// P_Frame *left_frame = predict_world->left_frame;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -2636,7 +2824,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
for (P_Ent *bullet = P_FirstEnt(world); bullet->valid; bullet = P_NextEnt(bullet))
|
for (P_Ent *bullet = P_FirstEnt(blend_frame); !P_IsEntNil(bullet); bullet = P_NextEnt(bullet))
|
||||||
{
|
{
|
||||||
if (bullet->is_bullet)
|
if (bullet->is_bullet)
|
||||||
{
|
{
|
||||||
@ -2816,7 +3004,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
|
|
||||||
if (0)
|
if (0)
|
||||||
{
|
{
|
||||||
for (P_Ent *bullet = P_FirstEnt(world); bullet->valid; bullet = P_NextEnt(bullet))
|
for (P_Ent *bullet = P_FirstEnt(blend_frame); !P_IsEntNil(bullet); bullet = P_NextEnt(bullet))
|
||||||
{
|
{
|
||||||
if (bullet->is_bullet && bullet->has_hit)
|
if (bullet->is_bullet && bullet->has_hit)
|
||||||
{
|
{
|
||||||
@ -2893,7 +3081,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
|
|
||||||
|
|
||||||
// {
|
// {
|
||||||
// for (P_Ent *firer = P_FirstEnt(world); firer->valid; firer = P_NextEnt(firer))
|
// for (P_Ent *firer = P_FirstEnt(blend_frame); firer->valid; firer = P_NextEnt(firer))
|
||||||
// {
|
// {
|
||||||
// if (firer->fire_held)
|
// if (firer->fire_held)
|
||||||
// {
|
// {
|
||||||
@ -2908,7 +3096,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
// P_RaycastResult victim_raycast = Zi;
|
// P_RaycastResult victim_raycast = Zi;
|
||||||
// {
|
// {
|
||||||
// f32 closest_len_sq = Inf;
|
// f32 closest_len_sq = Inf;
|
||||||
// for (P_Ent *victim = P_FirstEnt(world); victim->valid; victim = P_NextEnt(victim))
|
// for (P_Ent *victim = P_FirstEnt(blend_frame); victim->valid; victim = P_NextEnt(victim))
|
||||||
// {
|
// {
|
||||||
// if (victim != firer)
|
// if (victim != firer)
|
||||||
// {
|
// {
|
||||||
@ -2979,7 +3167,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
|
|
||||||
|
|
||||||
// // for (P_QueryResult query = P_FirstRaycast(wrold, ray_start, ray_dir); query.
|
// // for (P_QueryResult query = P_FirstRaycast(wrold, ray_start, ray_dir); query.
|
||||||
// // P_RaycastWorldResult hits = P_RaycastWorld(world, ray_start, ray_dir)
|
// // P_RaycastWorldResult hits = P_RaycastWorld(blend_frame, ray_start, ray_dir)
|
||||||
// // {
|
// // {
|
||||||
// // }
|
// // }
|
||||||
// }
|
// }
|
||||||
@ -3018,91 +3206,91 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Debug draw
|
//- Debug draw
|
||||||
|
|
||||||
{
|
// {
|
||||||
// Copy debug draw data from sim
|
// // Copy debug draw data from sim
|
||||||
if (received_unseen_tick)
|
// if (received_unseen_tick)
|
||||||
{
|
// {
|
||||||
ResetArena(sim_debug_arena);
|
// ResetArena(sim_debug_arena);
|
||||||
first_sim_debug_draw_node = 0;
|
// first_sim_debug_draw_node = 0;
|
||||||
last_sim_debug_draw_node = 0;
|
// last_sim_debug_draw_node = 0;
|
||||||
{
|
// {
|
||||||
i64 dst_idx = 0;
|
// i64 dst_idx = 0;
|
||||||
P_DebugDrawNode *dst_nodes = PushStructsNoZero(sim_debug_arena, P_DebugDrawNode, sim_output->debug_draw_nodes_count);
|
// P_DebugDrawNode *dst_nodes = PushStructsNoZero(sim_debug_arena, P_DebugDrawNode, sim_output->debug_draw_nodes_count);
|
||||||
for (P_DebugDrawNode *src = sim_output->first_debug_draw_node; src; src = src->next)
|
// for (P_DebugDrawNode *src = sim_output->first_debug_draw_node; src; src = src->next)
|
||||||
{
|
// {
|
||||||
P_DebugDrawNode *dst = &dst_nodes[dst_idx];
|
// P_DebugDrawNode *dst = &dst_nodes[dst_idx];
|
||||||
*dst = *src;
|
// *dst = *src;
|
||||||
dst_idx += 1;
|
// dst_idx += 1;
|
||||||
SllQueuePush(first_sim_debug_draw_node, last_sim_debug_draw_node, dst);
|
// SllQueuePush(first_sim_debug_draw_node, last_sim_debug_draw_node, dst);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Merge vis debug draws with sim debug draws
|
// // Merge vis debug draws with sim debug draws
|
||||||
P_DebugDrawNode *first_debug_draw_node = first_sim_debug_draw_node;
|
// P_DebugDrawNode *first_debug_draw_node = first_sim_debug_draw_node;
|
||||||
P_DebugDrawNode *last_debug_draw_node = last_sim_debug_draw_node;
|
// P_DebugDrawNode *last_debug_draw_node = last_sim_debug_draw_node;
|
||||||
if (P_tl.first_debug_draw_node)
|
// if (P_tl.first_debug_draw_node)
|
||||||
{
|
// {
|
||||||
if (last_debug_draw_node)
|
// if (last_debug_draw_node)
|
||||||
{
|
// {
|
||||||
last_debug_draw_node->next = P_tl.first_debug_draw_node;
|
// last_debug_draw_node->next = P_tl.first_debug_draw_node;
|
||||||
}
|
// }
|
||||||
else
|
// else
|
||||||
{
|
// {
|
||||||
first_debug_draw_node = P_tl.first_debug_draw_node;
|
// first_debug_draw_node = P_tl.first_debug_draw_node;
|
||||||
}
|
// }
|
||||||
last_debug_draw_node = P_tl.last_debug_draw_node;
|
// last_debug_draw_node = P_tl.last_debug_draw_node;
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Push draws
|
// // Push draws
|
||||||
for (P_DebugDrawNode *n = first_debug_draw_node; n; n = n->next)
|
// for (P_DebugDrawNode *n = first_debug_draw_node; n; n = n->next)
|
||||||
{
|
// {
|
||||||
Vec4 color = Vec4FromU32(n->srgb32);
|
// Vec4 color = Vec4FromU32(n->srgb32);
|
||||||
i32 detail = 24;
|
// i32 detail = 24;
|
||||||
f32 radius = 5;
|
// f32 radius = 5;
|
||||||
switch(n->kind)
|
// switch(n->kind)
|
||||||
{
|
// {
|
||||||
case P_DebugDrawKind_Point:
|
// case P_DebugDrawKind_Point:
|
||||||
{
|
// {
|
||||||
Vec2 ui_p = MulXformV2(frame->xf.world_to_ui, n->point.p);
|
// Vec2 ui_p = MulXformV2(frame->xf.world_to_ui, n->point.p);
|
||||||
V_DrawPoint(ui_p, color);
|
// V_DrawPoint(ui_p, color);
|
||||||
} break;
|
// } break;
|
||||||
|
|
||||||
case P_DebugDrawKind_Line:
|
// case P_DebugDrawKind_Line:
|
||||||
{
|
// {
|
||||||
Vec2 ui_p0 = MulXformV2(frame->xf.world_to_ui, n->line.p0);
|
// Vec2 ui_p0 = MulXformV2(frame->xf.world_to_ui, n->line.p0);
|
||||||
Vec2 ui_p1 = MulXformV2(frame->xf.world_to_ui, n->line.p1);
|
// Vec2 ui_p1 = MulXformV2(frame->xf.world_to_ui, n->line.p1);
|
||||||
V_DrawLine(ui_p0, ui_p1, color);
|
// V_DrawLine(ui_p0, ui_p1, color);
|
||||||
} break;
|
// } break;
|
||||||
|
|
||||||
case P_DebugDrawKind_Rect:
|
// case P_DebugDrawKind_Rect:
|
||||||
{
|
// {
|
||||||
Rng2 ui_rect = Zi;
|
// Rng2 ui_rect = Zi;
|
||||||
ui_rect.p0 = MulXformV2(frame->xf.world_to_ui, n->rect.p0);
|
// ui_rect.p0 = MulXformV2(frame->xf.world_to_ui, n->rect.p0);
|
||||||
ui_rect.p1 = MulXformV2(frame->xf.world_to_ui, n->rect.p1);
|
// ui_rect.p1 = MulXformV2(frame->xf.world_to_ui, n->rect.p1);
|
||||||
V_DrawRect(ui_rect, color, V_DrawFlag_Line);
|
// V_DrawRect(ui_rect, color, V_DrawFlag_Line);
|
||||||
} break;
|
// } break;
|
||||||
|
|
||||||
case P_DebugDrawKind_Shape:
|
// case P_DebugDrawKind_Shape:
|
||||||
{
|
// {
|
||||||
P_Shape ui_shape = P_MulXformShape(frame->xf.world_to_ui, n->shape);
|
// P_Shape ui_shape = P_MulXformShape(frame->xf.world_to_ui, n->shape);
|
||||||
V_DrawShape(ui_shape, color, detail, V_DrawFlag_Line);
|
// V_DrawShape(ui_shape, color, detail, V_DrawFlag_Line);
|
||||||
} break;
|
// } break;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Reset vis debug draws
|
// // Reset vis debug draws
|
||||||
ResetArena(P_tl.debug_arena);
|
// ResetArena(P_tl.debug_arena);
|
||||||
P_tl.first_debug_draw_node = 0;
|
// P_tl.first_debug_draw_node = 0;
|
||||||
P_tl.last_debug_draw_node = 0;
|
// P_tl.last_debug_draw_node = 0;
|
||||||
P_tl.debug_draw_nodes_count = 0;
|
// P_tl.debug_draw_nodes_count = 0;
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Draw entities
|
//- Draw entities
|
||||||
|
|
||||||
// for (P_Ent *ent = P_FirstEnt(world); ent->valid; ent = P_NextEnt(ent))
|
// for (P_Ent *ent = P_FirstEnt(blend_frame); ent->valid; ent = P_NextEnt(ent))
|
||||||
// {
|
// {
|
||||||
// Xform ent_to_world_xf = ent->xf;
|
// Xform ent_to_world_xf = ent->xf;
|
||||||
// Xform ent_to_draw_xf = MulXform(frame->xf.world_to_draw, ent_to_world_xf);
|
// Xform ent_to_draw_xf = MulXform(frame->xf.world_to_draw, ent_to_world_xf);
|
||||||
@ -3260,7 +3448,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
G_CopyCpuToTexture(
|
G_CopyCpuToTexture(
|
||||||
frame->cl,
|
frame->cl,
|
||||||
gpu_tiles, VEC3I32(0, 0, 0),
|
gpu_tiles, VEC3I32(0, 0, 0),
|
||||||
world->tiles, VEC3I32(tiles_dims.x, tiles_dims.y, 1),
|
blend_world->tiles, VEC3I32(tiles_dims.x, tiles_dims.y, 1),
|
||||||
RNG3I32(VEC3I32(0, 0, 0), VEC3I32(tiles_dims.x, tiles_dims.y, 1))
|
RNG3I32(VEC3I32(0, 0, 0), VEC3I32(tiles_dims.x, tiles_dims.y, 1))
|
||||||
);
|
);
|
||||||
G_DumbMemoryLayoutSync(frame->cl, gpu_tiles, G_Layout_DirectQueue_ShaderRead);
|
G_DumbMemoryLayoutSync(frame->cl, gpu_tiles, G_Layout_DirectQueue_ShaderRead);
|
||||||
@ -3372,28 +3560,28 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Prune ents
|
//- Prune ents
|
||||||
|
|
||||||
{
|
// {
|
||||||
i64 ents_to_prune_count = 0;
|
// i64 ents_to_prune_count = 0;
|
||||||
P_Ent **ents_to_prune = PushStructsNoZero(frame->arena, P_Ent *, world->ents_count);
|
// P_Ent **ents_to_prune = PushStructsNoZero(frame->arena, P_Ent *, world->ents_count);
|
||||||
for (P_Ent *ent = P_FirstEnt(world); ent->valid; ent = P_NextEnt(ent))
|
// for (P_Ent *ent = P_FirstEnt(world); ent->valid; ent = P_NextEnt(ent))
|
||||||
{
|
// {
|
||||||
if (ent->exists <= 0)
|
// if (ent->exists <= 0)
|
||||||
{
|
// {
|
||||||
ents_to_prune[ents_to_prune_count] = ent;
|
// ents_to_prune[ents_to_prune_count] = ent;
|
||||||
ents_to_prune_count += 1;
|
// ents_to_prune_count += 1;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
for (i64 prune_idx = 0; prune_idx < ents_to_prune_count; ++prune_idx)
|
// for (i64 prune_idx = 0; prune_idx < ents_to_prune_count; ++prune_idx)
|
||||||
{
|
// {
|
||||||
// FIXME: Add to free list
|
// // FIXME: Add to free list
|
||||||
P_Ent *ent = ents_to_prune[prune_idx];
|
// P_Ent *ent = ents_to_prune[prune_idx];
|
||||||
P_EntBin *bin = &world->ent_bins[ent->key.v % world->ent_bins_count];
|
// P_EntBin *bin = &world->ent_bins[ent->key.v % world->ent_bins_count];
|
||||||
DllQueueRemoveNP(bin->first, bin->last, ent, next_in_bin, prev_in_bin);
|
// DllQueueRemoveNP(bin->first, bin->last, ent, next_in_bin, prev_in_bin);
|
||||||
DllQueueRemove(world->first_ent, world->last_ent, ent);
|
// DllQueueRemove(world->first_ent, world->last_ent, ent);
|
||||||
world->ents_count -= 1;
|
// world->ents_count -= 1;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- End frame
|
//- End frame
|
||||||
|
|||||||
@ -260,7 +260,7 @@ Struct(V_Frame)
|
|||||||
Rng2 draw_selection;
|
Rng2 draw_selection;
|
||||||
Rng2 world_selection;
|
Rng2 world_selection;
|
||||||
|
|
||||||
// Commands
|
// Vis commands
|
||||||
i64 cmds_count;
|
i64 cmds_count;
|
||||||
V_CmdNode *first_cmd_node;
|
V_CmdNode *first_cmd_node;
|
||||||
V_CmdNode *last_cmd_node;
|
V_CmdNode *last_cmd_node;
|
||||||
@ -271,11 +271,6 @@ Struct(V_Frame)
|
|||||||
f32 fire_held;
|
f32 fire_held;
|
||||||
f32 fire_presses;
|
f32 fire_presses;
|
||||||
|
|
||||||
// Sim cmds
|
|
||||||
u64 sim_cmds_count;
|
|
||||||
P_CmdNode *first_sim_cmd_node;
|
|
||||||
P_CmdNode *last_sim_cmd_node;
|
|
||||||
|
|
||||||
// Emitters
|
// Emitters
|
||||||
i64 emitters_count;
|
i64 emitters_count;
|
||||||
V_EmitterNode *first_emitter_node;
|
V_EmitterNode *first_emitter_node;
|
||||||
@ -291,6 +286,9 @@ Struct(V_Ctx)
|
|||||||
V_Panel *root_panel;
|
V_Panel *root_panel;
|
||||||
V_Window *dragging_window;
|
V_Window *dragging_window;
|
||||||
|
|
||||||
|
// Sim commands
|
||||||
|
P_CmdList sim_cmds;
|
||||||
|
|
||||||
// Atomic monotonically increasing allocation counter sequence for GPU particle ring buffer
|
// Atomic monotonically increasing allocation counter sequence for GPU particle ring buffer
|
||||||
u32 particle_seq;
|
u32 particle_seq;
|
||||||
|
|
||||||
|
|||||||
@ -94,7 +94,7 @@ TAR_Archive TAR_ArchiveFromString(Arena *arena, String data, String prefix)
|
|||||||
archive.lookup = InitDict(arena, (u64)((f64)num_files * TAR_ArchiveLookupTableCapacityFactor));
|
archive.lookup = InitDict(arena, (u64)((f64)num_files * TAR_ArchiveLookupTableCapacityFactor));
|
||||||
for (TAR_Entry *entry = archive.head; entry; entry = entry->next)
|
for (TAR_Entry *entry = archive.head; entry; entry = entry->next)
|
||||||
{
|
{
|
||||||
u64 hash = HashFnv64(Fnv64Basis, entry->file_name);
|
u64 hash = HashString(entry->file_name);
|
||||||
SetDictValue(arena, archive.lookup, hash, (u64)entry);
|
SetDictValue(arena, archive.lookup, hash, (u64)entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,7 +113,7 @@ TAR_Archive TAR_ArchiveFromString(Arena *arena, String data, String prefix)
|
|||||||
{
|
{
|
||||||
if (parent_dir_name.text[parent_dir_name.len - 1] == '/')
|
if (parent_dir_name.text[parent_dir_name.len - 1] == '/')
|
||||||
{
|
{
|
||||||
u64 hash = HashFnv64(Fnv64Basis, parent_dir_name);
|
u64 hash = HashString(parent_dir_name);
|
||||||
parent_entry = (TAR_Entry *)DictValueFromHash(archive.lookup, hash);
|
parent_entry = (TAR_Entry *)DictValueFromHash(archive.lookup, hash);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -133,7 +133,7 @@ TAR_Archive TAR_ArchiveFromString(Arena *arena, String data, String prefix)
|
|||||||
Readonly Global TAR_Entry g_nil_tar_entry = ZI;
|
Readonly Global TAR_Entry g_nil_tar_entry = ZI;
|
||||||
TAR_Entry *TAR_EntryFromName(TAR_Archive *archive, String name)
|
TAR_Entry *TAR_EntryFromName(TAR_Archive *archive, String name)
|
||||||
{
|
{
|
||||||
u64 hash = HashFnv64(Fnv64Basis, name);
|
u64 hash = HashString(name);
|
||||||
TAR_Entry *lookup = (TAR_Entry *)DictValueFromHash(archive->lookup, hash);
|
TAR_Entry *lookup = (TAR_Entry *)DictValueFromHash(archive->lookup, hash);
|
||||||
return lookup ? lookup : &g_nil_tar_entry;
|
return lookup ? lookup : &g_nil_tar_entry;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,7 +24,7 @@ UI_Key UI_KeyFromString(String str)
|
|||||||
{
|
{
|
||||||
u64 top_tag = UI_Top(Tag);
|
u64 top_tag = UI_Top(Tag);
|
||||||
UI_Key key = Zi;
|
UI_Key key = Zi;
|
||||||
key.v = HashFnv64(top_tag, str);
|
key.v = HashStringEx(top_tag, str);
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -340,7 +340,7 @@ void UI_PushDefaults(void)
|
|||||||
case UI_StyleKind_FontSize: { desc.style.FontSize = 16.0f; } break;
|
case UI_StyleKind_FontSize: { desc.style.FontSize = 16.0f; } break;
|
||||||
case UI_StyleKind_Tint: { desc.style.Tint = Color_White; } break;
|
case UI_StyleKind_Tint: { desc.style.Tint = Color_White; } break;
|
||||||
case UI_StyleKind_TextColor: { desc.style.TextColor = Color_White; } break;
|
case UI_StyleKind_TextColor: { desc.style.TextColor = Color_White; } break;
|
||||||
case UI_StyleKind_Tag: { desc.style.Tag = HashFnv64(Fnv64Basis, Lit("root")); } break;
|
case UI_StyleKind_Tag: { desc.style.Tag = HashString(Lit("root")); } break;
|
||||||
case UI_StyleKind_DebugColor: { desc.style.DebugColor = Rgba(1, 0, 1, 0.5); } break;
|
case UI_StyleKind_DebugColor: { desc.style.DebugColor = Rgba(1, 0, 1, 0.5); } break;
|
||||||
case UI_StyleKind_InvisibleDebugColor: { desc.style.InvisibleDebugColor = Rgba(0, 1, 1, 0.25); } break;
|
case UI_StyleKind_InvisibleDebugColor: { desc.style.InvisibleDebugColor = Rgba(0, 1, 1, 0.25); } break;
|
||||||
case UI_StyleKind_BackgroundTextureSliceUv: { desc.style.BackgroundTextureSliceUv = RNG2(VEC2(0, 0), VEC2(1, 1)); } break;
|
case UI_StyleKind_BackgroundTextureSliceUv: { desc.style.BackgroundTextureSliceUv = RNG2(VEC2(0, 0), VEC2(1, 1)); } break;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user