00:38 < bridge> i think its time for uniting cyberpunk and ddnet 😴 00:51 < bridge> no 02:58 < bridge> Missed opportunity for \#10000 the problem of death 03:03 < bridge> thx 08:24 < bridge> https://docs.fabric.io/android/crashlytics/custom-web-hooks.html?web%20hooks#custom-web-hooks 09:57 < bridge> :owo: 10:24 < bridge> building llvm 20.1.2 10:25 < bridge> https://cdn.discordapp.com/attachments/293493549758939136/1356907286848737423/image.png?ex=67ee45e3&is=67ecf463&hm=baffe359984e68821f2bd0147760e474ac3134ffbb03d780973d996b90964fb7& 10:41 < bridge> https://cdn.discordapp.com/attachments/293493549758939136/1356911337787228221/vAuOow0.png?ex=67ee49a9&is=67ecf829&hm=dd2e3845d8d219464337117f20cbe1928d46efa0d938d7ebc9472e8de96e5562& 10:41 < bridge> firefox 10:54 < bridge> firefok 11:28 < bridge> class CGameContext 11:28 < bridge> Size: 361480 bytes, alignment 8 bytes 11:28 < bridge> ok 11:28 < bridge> many cases 11:28 < bridge> we have a class that is 361kb in size 11:29 < bridge> im trying to reorder some fields 11:29 < bridge> to reduce size 11:29 < bridge> we should adopt a style of not mixing fields and function declarations 11:29 < bridge> first fields at top 11:29 < bridge> then functions 11:30 < bridge> That seems less readable. I always group variables and functions that belong together. Also, I think private variables/functions should be at the bottom. 11:30 < bridge> did you check CGameClient 11:31 < bridge> how so? 11:31 < bridge> How do you know what a bunch of variables and functions belong together if you sort them? 11:31 < bridge> https://cdn.discordapp.com/attachments/293493549758939136/1356923998084268032/image.png?ex=67ee5573&is=67ed03f3&hm=5039498d2bbaeb09767da3d52949f252a7dac995a291d74dcdcca1720934100e& 11:31 < bridge> but since c++ doesnt reorder fields like rust we need this 11:31 < bridge> to reduce sizes 11:31 < bridge> comments 11:31 < bridge> is there a compilation flag or attribute we could use to allow the compiler to reorder the fields ? 11:32 < bridge> because i prefer readability over some bytes 11:32 < bridge> not that i know 11:32 < bridge> Yeah why does the size matter xd 11:32 < bridge> its the pain of using c++ 11:32 < bridge> less size more cache friendly? xd 11:32 < bridge> arent u the max fps guy 11:33 < bridge> I doubt we have a bottleneck here 11:33 < bridge> i guess i wont do this then 11:33 < bridge> There are other parts we can optimize first 11:33 < bridge> I don't think the ordering is the main thing causing the size 11:33 < bridge> It's just that big 11:33 < bridge> well ordering matters 11:33 < bridge> cproj i reduced from 136 to 128 11:33 < bridge> just changing order 11:33 < bridge> but for the big ones yeah 11:33 < bridge> they have big arrays in them 11:33 < bridge> its normal 11:34 < bridge> We use lots of static sized arrays 11:34 < bridge> I don't want to comment 20 variables and functions with the same comment though, I'd rather put one comment on top. Or group those vars and functions in a separate class. 11:34 < bridge> everyday i hate more c++ and its limitations 11:34 < bridge> u have to choose readbility or perf 11:35 < bridge> xD 11:35 < bridge> :nouis: 11:35 < bridge> That rust can reorder is defs cool 11:35 < bridge> 10/10 give you that 11:35 < bridge> can you try with `__attribute__((packed))` to see if there's any noticeable difference ? 11:35 < bridge> and since the visibility qualifier is "public:" and nota prefix like in rust 11:35 < bridge> if u want to order fields with different visibility u need to put public protected again in many places 11:35 < bridge> it sucks hardcore 11:35 < bridge> but compatibility when you dump struct/class to file is lost 11:36 < bridge> You use serde for that anyway 11:36 < bridge> google also threw me that https://manpages.ubuntu.com/manpages/bionic/man1/clang-reorder-fields-10.1.html 11:36 < bridge> for cproj it also reduces it to 128 but packed is less perf 11:37 < bridge> Size: 361480 bytes, alignment 8 bytes for cgamecontext 11:37 < bridge> no change i guess 11:38 < bridge> u shouldnt dump to a file as is anyway 11:38 < bridge> I thought if the alignment is 8 bytes then it won't waste more than 8 bytes between fields? so that's basically nothing? 11:38 < bridge> isnt a cache line 64 bytes in most cpus 11:38 < bridge> if so in that case it matters a lot 11:39 < bridge> what? 11:39 < bridge> if a struct goes from 72 to 64 11:39 < bridge> but that's not what determines the struct packing? 11:39 < bridge> by ordering fields 11:39 < bridge> ? 11:39 < bridge> if u have a int and a long then u have 4 bytes of padding 11:39 < bridge> after the int 11:40 < bridge> if u have int long int 11:40 < bridge> u waste 8 bytes 11:40 < bridge> long int int 11:40 < bridge> nothing wasted 11:40 < bridge> well yes but that's not the same issue as CGameConext and other classes being hundreds of kilobytes 11:40 < bridge> it's a micro optimization then 11:40 < bridge> yeah im not talking about the big ones 11:40 < bridge> its ok if u dont care i wont do it 11:40 < bridge> xd 11:40 < bridge> You can defs loose between a u32 to u64 member 11:40 < bridge> 11:40 < bridge> but u32 and u32 should still pack fine 11:40 < bridge> anyway readbility matters more and perf probs not a gain 11:41 < bridge> that's fine I just wanted to make sure you weren't trying to reduce the size meaningfully with struct reordering, because that's not why they're big 11:41 < bridge> if you can do it for free then that's good 11:41 < bridge> i know cgame is big cuz static arrays which we abuse a lot 11:41 < bridge> but well since there is just 1 context and we not allocating deallocating it a lot should be fine tm i guess 11:41 < bridge> but for entities i thought it might matter more 11:42 < bridge> which is why i looked into cproj first 11:42 < bridge> https://cdn.discordapp.com/attachments/293493549758939136/1356926722104230050/image.png?ex=67ee57fd&is=67ed067d&hm=ba87fbd4c6352d9c6a4f7da13f7cd217669a89d7d2a2b988565eafe6a37fa657& 11:42 < bridge> You happy now @ryozuki ? 11:42 < bridge> xd 11:42 < bridge> packed is less perfomant 11:42 < bridge> I just slammed a `#pragma pack(1)` in system.h 11:43 < bridge> hi cbat 11:43 < bridge> it does, but the entities are stored in a linked list and alloced individually so you're fighting the wrong battle 11:43 < bridge> ah i see 11:43 < bridge> I have to intervene, there is more to it, this pragma doesn't work on all OS or does it? 11:43 < bridge> linked lists my beloved 11:43 < bridge> can we use a generational arena? 11:43 < bridge> xd 11:43 < bridge> ^ but look how few bytes that make 11:43 < bridge> yeah cuz arrays 11:44 < bridge> We won't use it, don't worry 11:44 < bridge> misaligned memory accesses are slower 11:44 < bridge> and in rust they are ub 11:44 < bridge> i guess in C maybe too idk 11:44 < bridge> I discussed with teero, in my opinion the best option in while also maintaining physics update order is a dynamic array swapback cursor list 11:44 < bridge> ok lot of fancy words 11:44 < bridge> let me search 11:45 < bridge> but a generational arena is a dynamic array too 11:45 < bridge> u just can remove elements 11:45 < bridge> by keeping a generation on each index 11:45 < bridge> I had to use `#pragma pack(push, 1)` and then `#pragma pack(pop)` explicitly, just FYI 11:45 < bridge> swapback array is another method 11:45 < bridge> it's easier, you can just use std::vector without any arenas 11:45 < bridge> a arena is a fancy vector 11:45 < bridge> thats what im saying 11:46 < bridge> https://miro.medium.com/v2/resize:fit:720/format:webp/1*RrVBXPmEwm6eJGCFMSBLlw.gif 11:46 < bridge> That is for temporary alignment changes. 11:46 < bridge> 11:46 < bridge> But anyway, as said it's just to show how much bytes we waste with alignment 11:46 < bridge> We won't use any pragma like that 11:47 < bridge> oh shit 11:47 < bridge> i installed llvm 20 to my llvm 19 folder 11:47 < bridge> i hate my life 11:47 < bridge> I needed this in a project for binary file alignment (over multiple OS) and further more in networking to minimize send bytes 11:47 < bridge> also other compilers might f*ck your alignment 11:48 < bridge> also other compilers might f*ck your alignment (the widespread ones should work tho) 11:57 < bridge> What you not on llvm-21 yet? 😬 11:58 < bridge> xd 12:03 < bridge> It do be UB 12:04 < bridge> That is rather large, what are we even storing in there? 12:05 < bridge> shitloads of arrays 12:05 < bridge> everything 12:07 < bridge> ``` 12:07 < bridge> ield m_aaZoneEnterMsg 12:07 < bridge> Type: char[256][256] 12:07 < bridge> Offset: 82736 bytes 12:07 < bridge> Size: 65536 bytes, alignment 1 byte 12:07 < bridge> 0 is used for switching from or to area without tunings 12:07 < bridge> 12:07 < bridge> // In CGameContext 12:07 < bridge> public: char m_aaZoneEnterMsg[256][256] 12:07 < bridge> ``` 12:07 < bridge> ``` 12:07 < bridge> field m_aaZoneEnterMsg 12:07 < bridge> Type: char[256][256] 12:07 < bridge> Offset: 82736 bytes 12:07 < bridge> Size: 65536 bytes, alignment 1 byte 12:07 < bridge> 0 is used for switching from or to area without tunings 12:07 < bridge> 12:07 < bridge> // In CGameContext 12:07 < bridge> public: char m_aaZoneEnterMsg[256][256] 12:07 < bridge> ``` 12:07 < bridge> what is this 12:07 < bridge> Is padding guaranteed to be zeroed (in the map format)? CSpeedupTile and CDoorTile have 1 and 2 unused padding bytes respectively 12:07 < bridge> why its this way xd 12:07 < bridge> is u use memzero yes otherwise its undefined 12:07 < bridge> if u* 12:07 < bridge> for every tune zone you can set an enter and a leave message 12:07 < bridge> why is this an array?! 12:08 < bridge> like who does 256 tune zone messages, I did like 20 in this one map 12:08 < bridge> I assume we do a memzero when allocating tiles, so technically we could reclaim those padding bytes and use them for something else 12:09 < bridge> ``` 12:09 < bridge> char m_aaZoneEnterMsg[NUM_TUNEZONES][256]; // 0 is used for switching from or to area without tunings 12:09 < bridge> char m_aaZoneLeaveMsg[NUM_TUNEZONES][256]; 12:09 < bridge> ``` 12:09 < bridge> I mean if ever there was a good reason to heap allocate strings there it is. We rarely ever use zone enter messages, for like 99.99% of maps that struct is completely empty and never accessed πŸ˜„ 12:10 < bridge> its not just 12 12:10 < bridge> 1 12:10 < bridge> its 2 12:10 < bridge> ok guys dont do this, ill change it 12:10 < bridge> so i can have a pr 12:11 < bridge> I mean if ever there was a good reason to heap allocate strings there it is. We rarely ever use zone enter messages, for like 99.99% of maps that array is completely empty and never accessed πŸ˜„ 12:11 < bridge> Hm, guaranteed idk, we can however go through all maps and check. 12:13 < bridge> If you need a testmap with a lot of enter and leave messages, take a look at `KingsLeap` in map testing 12:13 < bridge> I guess an array of `std::string`s would be fine, they'd even have SSO 13:06 < bridge> Hi 13:06 < bridge> hi 13:07 < bridge> @astramast: 13:07 < bridge> @astramast 13:13 < bridge> mast means "pole" in german, so an astra mast is a pole to the starts, so a space evelator, nice @astramast 13:26 < bridge> A mast is also a pole in English 13:26 < bridge> Or at least that's like the main part of a mast 13:27 < bridge> something something contour integral around western europe 13:29 < bridge> @soulyvevo can you create the snowflakes sprites for your proposed change to freeze lasers? Also I need a 4th sprite for the background. That background should match all snowflakes, we already have a snowflake in `extras.png` Lastly snowflakes are always hexagons and never octagons πŸ™ˆ 13:30 < bridge> maybe I just need the background πŸ€” 13:30 < bridge> It's because i can bring you to heaven 😏 13:31 < bridge> Then you need to die for my sins first 13:31 < bridge> https://tenor.com/view/disintegrate-gif-22469816 13:44 < bridge> @learath2 can integers from GetInteger be negative? 13:44 < bridge> ah nvm there is a check 13:54 < bridge> ty works, reminds me of the game about jumping 13:56 < bridge> @jupeyy_keks class CGameContext 13:56 < bridge> Size: 230456 bytes, alignment 8 bytes 13:56 < bridge> with my pr 13:56 < bridge> you mean the game this map is inspired by about jumping called JumpKing? never heard of it /s 13:56 < bridge> xd 13:58 < bridge> neat, is cgamecontext not on the heap? 13:58 < bridge> uh idk 13:58 < bridge> the created object of it ofc 13:59 < bridge> you can static cast any object into size_t? 13:59 < bridge> its an int 14:00 < bridge> oh, let me keep thinking 14:00 < bridge> did you check skipping a tune zone? 14:01 < bridge> i didnt rly change the code at all 14:01 < bridge> nevermind found the resize 14:01 < bridge> logic wise 14:01 < bridge> the resize probably never happens anyway 14:01 < bridge> its just a safeguard 14:02 < bridge> because i init the vectors with a resize to num tunezones 14:02 < bridge> hm 14:02 < bridge> yeah I've seen that, is that necessary or what benefit do you see in that? 14:02 < bridge> hm i think its more predicatable 14:02 < bridge> othwise 99.7% of the maps will initialize 256 empty strings πŸ˜„ 14:02 < bridge> but is oninit called more than once? 14:03 < bridge> a string is a ptr and 2 ints 14:03 < bridge> and a empty string should not allocate at all 14:03 < bridge> i guess i can remove it but i doubt it matters much 14:03 < bridge> actually il lchange this to a reset 14:03 < bridge> to make sure its cleaned 14:04 < bridge> if for some reason context is inited again 14:05 < bridge> waiting for the refresh then, also wanted to add that it's a full refresh and not only a resize 14:05 < bridge> pushed 14:06 < bridge> > IGameServer *CreateGameServer() { return new CGameContext; } 14:07 < bridge> @essigautomat https://github.com/ddnet/ddnet/pull/10003#discussion_r2024688675 14:07 < bridge> where do u mean by here 14:07 < bridge> @ryozuki u never initialize your vectors 14:07 < bridge> u dont need a cast to compare to zero 14:07 < bridge> ah you do 14:07 < bridge> it works tho 14:07 < bridge> but why do you include array? 14:08 < bridge> clangd? 14:08 < bridge> ehm 14:08 < bridge> I mean that line: `if(m_TuneZoneOld >= 0 && static_cast(m_TuneZone) < GameServer()->m_vZoneEnterMsg.size() && !GameServer()->m_vZoneLeaveMsg[m_TuneZoneOld].empty())` 14:08 < bridge> vscode likes to include everything 14:08 < bridge> you wrote one time `m_TuneZone` instead of `m_TuneZoneOld` 14:08 < bridge> @ryozuki do you think a vector is really better? 14:08 < bridge> 14:08 < bridge> an array of 256 and u8 directly makes sure the index is always in bound 14:08 < bridge> oh 14:08 < bridge> a typo 14:08 < bridge> copy pasting xd 14:09 < bridge> yes :owo: 14:09 < bridge> nice catch 14:09 < bridge> i love git commit --amend 14:11 < bridge> idk, i think its fine to not waste memory since tune zones are rarely used anyway 14:11 < bridge> i think it's better to waste memory than overcomplicate code 14:11 < bridge> :justatest: 14:11 < bridge> @learath2 whats ur opinion on this matter sir 14:11 < bridge> I don't think that code is overcomplicated like this xD 14:11 < bridge> Is it really overvomplicated tho? 14:12 < bridge> Is it really overcomplicated tho? 14:12 < bridge> it's much harder to read, you cannot assume the index (if u8) is not out of bounds 14:12 < bridge> the added benefit is u can have tune zone msgs larger than 256 14:12 < bridge> actually not 14:12 < bridge> abuf is 256 still 14:13 < bridge> ah no 14:13 < bridge> i removed abuf 14:13 < bridge> yeah u can have bigger xd 14:13 < bridge> omg i hate my c++ 14:13 < bridge> :monkalaugh: 14:13 < bridge> https://cdn.discordapp.com/attachments/293493549758939136/1356964751498022912/image.png?ex=67ee7b67&is=67ed29e7&hm=564b445d3632b91fa8ed31e237b209a01b1a0f24be5319456b606c433aea9aec& 14:13 < bridge> ok no 14:13 < bridge> github likes to hide code in git diffs 14:13 < bridge> yeah but we don't have tune_zones over u8 14:13 < bridge> the std::string can also be used with an array 14:13 < bridge> that is independent 14:13 < bridge> this is not true for linebraked strings ... wtf 14:14 < bridge> yeah just realized 14:14 < bridge> using std::string makes the code less complicated there xD 14:14 < bridge> imho yeah xd 14:14 < bridge> no str copy 14:15 < bridge> does std::string have a split function we could use there? 14:15 < bridge> certainly 14:15 < bridge> anyway i have no strong opinion on this matter, feel free to decide and merge or close 14:16 < bridge> https://en.cppreference.com/w/cpp/string/basic_string/getline 14:17 < bridge> Please open an issue before pr!!! 14:17 < bridge> I suggest actually fixing the linebreak issue now, since it wasn't one before 14:17 < bridge> What is this Ryozuki 14:17 < bridge> this is a refactoring, as I mentioned these should be excluded from issue creation 14:18 < bridge> https://cdn.discordapp.com/attachments/293493549758939136/1356966094677479506/image.png?ex=67ee7ca8&is=67ed2b28&hm=748da5c407ece9b1630728c7a6d8b1f1b792ce80103b782db5e5f7e69f0313e9& 14:18 < bridge> should work tm 14:19 < bridge> @jupeyy_keks is this clean 14:19 < bridge> let me test 14:19 < bridge> works 14:20 < bridge> honestly i forgot how the cpp streams work xD 14:20 < bridge> pushed 14:20 < bridge> also do we have a limit for server tuning lengths in maps? 14:20 < bridge> idk 14:20 < bridge> found the same solution on stack overflow for this 14:21 < bridge> some of the cpp apis manages to be so counter intuitive 14:22 < bridge> which is what u used kek 14:22 < bridge> i* 14:22 < bridge> my keyboard is crazy 14:23 < bridge> does getline return the full string if no linebreak is found? 14:23 < bridge> @ryozuki now you got the heinrich ban hammer on the vec approach anyway 14:23 < bridge> 🫠 14:23 < bridge> xdd 14:23 < bridge> i leave it for a day for more opinions 14:23 < bridge> then if not ill change 14:24 < bridge> > Extracts characters from is and stores them into str until the delimitation character delim is found (or the newline character, '\n', for (2)). 14:24 < bridge> okay 14:24 < bridge> or eof 14:27 < bridge> Which part of it do you require an opinion on? Not wasting memory is good. Wasting memory is bad 14:28 < bridge> Yup, what did I expect from a guy who banned me because of an emote 14:28 < bridge> https://cdn.discordapp.com/attachments/293493549758939136/1356968556218028122/image.png?ex=67ee7ef3&is=67ed2d73&hm=2a2333be0c9349a3a647831b3d5f9cbd3fa5e400a2fd07b76989da83380196e8& 14:28 < bridge> I'd have used an array of `std::string`s though not a vec, they are small enough 14:29 < bridge> How should I read that? 14:29 < bridge> I need an "approve that code is working and to my standards, but I don't know if the concept is the right one to use"-button 14:29 < bridge> I didn't follow 14:29 < bridge> Or if you want to avoid the modernity and embrace teeworlds, a CHeap of CStrings? πŸ˜„ 14:29 < bridge> Use a dynamic arena ryo 14:30 < bridge> All I wrote in the "less toxicity in the repo" post is 14:30 < bridge> - 10/10 approve 14:30 < bridge> dynamic bulk arena 14:30 < bridge> Oh is that PR relevant, lemme check 14:30 < bridge> #9999 14:30 < bridge> https://github.com/ddnet/ddnet/pull/9999 14:31 < bridge> Ok was just a april pr i see 14:31 < bridge> and heinrich didnt get it xD 14:31 < bridge> Like it's just one comment removing profanity, but even if it wasn't an april fools joke, well 14:31 < bridge> can I not comment on this? xd 14:31 < bridge> dunno how it's related to your comment tho 14:31 < bridge> no it was an april fools joke, maybe I deserve an outtime for this one .. xD 14:31 < bridge> You wasted the holy number 9999 for aprils fools joke 14:31 < bridge> It seems you did comment. I don't follow 14:31 < bridge> How dare you 14:31 < bridge> I just simply commented "10/10 approve" as a positive thing 14:31 < bridge> and removed xd 14:32 < bridge> Yes XD brilliant, the stars aligned 14:32 < bridge> I still see your comment fwiw 14:32 < bridge> me too 14:32 < bridge> I am very confused xD 14:32 < bridge> eh? 14:32 < bridge> I am very very confused 14:32 < bridge> same as you guys 14:33 < bridge> https://github.com/ddnet/ddnet/pull/9999#issuecomment-2770312616 14:33 < bridge> didn't check my github yet, but this message just arrived now 14:33 < bridge> 3 hours before 14:33 < bridge> idfk dude 14:34 < bridge> This one is even more infuriating: 14:34 < bridge> > Nice to see you're working on yourself πŸ˜‰ 14:34 < bridge> Thanks I guess? xDD 14:34 < bridge> Or perhaps I'm a huge retard and the whole repo's name is "remove comment"? 14:34 < bridge> if that's the case, then I got april fooled idk :greenthing: 14:35 < bridge> Chairn defs nailed it 14:35 < bridge> The only comment that made the joke better 14:35 < bridge> The name of the pr was "remove comment" 14:35 < bridge> Bro i wanna kms I really thought heinrich removed my comment XD 14:35 < bridge> cuz it was the repo's name 14:35 < bridge> and not an action from github 14:35 < bridge> πŸ˜„ 14:36 < bridge> fuck man 14:36 < bridge> xD 14:36 < bridge> you got april fooled too 14:36 < bridge> I was like: why the fuck 14:36 < bridge> technologies are hard 14:36 < bridge> I bet he changed the name of the post's header 14:37 < bridge> My eye is extremely itchy, but itching it makes it itch more 14:37 < bridge> wash it with water 14:37 < bridge> heinrich renamed the PR, so that it doesn't appear in the git history 14:37 < bridge> no fucking way 14:37 < bridge> which is understandable 14:38 < bridge> he wins 14:38 < bridge> got fooled even if I didn't want to 14:38 < bridge> get fooled :nouis: 14:38 < bridge> :nouis: 14:40 < bridge> your pipeline failed btw πŸ™ˆ 15:06 < bridge> oh 15:10 < bridge> why not use std::map? 15:11 < bridge> right now if you have only msg for zone 255 itll have size 255 even though only 1 item 15:11 < bridge> right now if you have only msg for zone 255 itll resize to 255 even though only 1 item 15:11 < bridge> @ryozuki 15:14 < bridge> std::map is logarithmic in access time 15:14 < bridge> std::map is logarithmic in access time, to be pedantic 15:15 < bridge> Yeah if you truly want that space saved too an associative container is the way to go since the array is sparse. But usually people will use the tune zones in order 15:15 < bridge> but pr reduces size 15:15 < bridge> cuz hash? 15:15 < bridge> I would just use a normal array 15:15 < bridge> yes, but this one is about tune_zone_enter and tune_zone_leave, this is not guaranteed to be in order! 15:15 < bridge> if at all use unordered_map 15:15 < bridge> which is a hashmap 15:16 < bridge> unordered_map yea 15:16 < bridge> But I'd say if 256 is your upper limit for indices, using a static sized array is often a nice way to go 15:16 < bridge> Cuz it's ordered and an ordered map is usually implemented as a tree and tree access is log 15:16 < bridge> actually no idea why, could be hash, could be binary tree 15:17 < bridge> std::map is red-black tree usually 15:17 < bridge> i miss rust 15:17 < bridge> isnt unordered_map slow 15:17 < bridge> cuz std 15:17 < bridge> no 15:17 < bridge> it is 15:17 < bridge> std good πŸ‘ 15:17 < bridge> no lol 15:17 < bridge> the standard library's maps are, indeed, inherently slow. Google's Chandler Carruth explains this in his CppCon 2014 talk; in a nutshell: 15:17 < bridge> std::map maintains its data's sort order, leading to a tree-based implementation; and trees are slow: non-contiguous with a lot of pointer chain chasing. 15:17 < bridge> std::unoredered_map is not as-bad, but it's still cache-unfriendly because it uses linked lists as buckets. 15:17 < bridge> It is slower than it can be because of the standards de-facto requirement that the hashmap is implemented with closed addressing 15:18 < bridge> yeah cuz the standard 15:18 < bridge> no way around it 15:18 < bridge> But this is just over over over optimizing πŸ˜„ 15:18 < bridge> open addressing is faster 15:18 < bridge> the problem with unordered_map is that you might not save lot more RAM in the end for 256 maximum 15:18 < bridge> i dunno what the default bucket size is 15:18 < bridge> std::unordered_map is constant or linear in the worst case 15:18 < bridge> But probably not like 1 xd 15:18 < bridge> Something that isn't even a huge issue to begin with. I would just put it in an array and call it a day 15:19 < bridge> perfect hashing 15:19 < bridge> lets over over optimize 15:19 < bridge> for fun 15:19 < bridge> and no profit 15:19 < bridge> that is for initalizing it 15:19 < bridge> you initalize once in this case and then its o(1) for unordered map 15:20 < bridge> i meant that the std impl is inherently slow 15:20 < bridge> compared to state of the art 15:20 < bridge> dont think its an issue when it runs only once 15:20 < bridge> rust uses hashmap with quadratic probing and simd lookup 15:20 < bridge> rust :cammostripes: 15:20 < bridge> c++ :cammostripes: 15:21 < bridge> Not quite O(1), it degenerates to O(n), but it is on the average O(1) 15:21 < bridge> what is the default hashing algo for std 15:22 < bridge> good hashing algo for sure 15:22 < bridge> c++ πŸ’ͺ 15:23 < bridge> like c++ regex, which is slower than starting php 15:23 < bridge> Anyway, a sparse data structure might not even help here since as jupman noted the default buckets can be too large or the hash space can be too large. Which for 256 elements is probably the case 15:24 < bridge> no map has 256 tune msgs 15:24 < bridge> https://cdn.discordapp.com/attachments/293493549758939136/1356982515654459544/ORL3Z.png?ex=67ee8bf3&is=67ed3a73&hm=b72f22cffb398a2f9355302455f7df4b0454206fbd64884102854f079b361551& 15:24 < bridge> If you really want to turbooptimize this for some reason, you need to make sure to design your own sparse datastructure, maybe a btree could work 15:24 < bridge> But that's logn, not o1 15:24 < bridge> But that's logn, not constant 15:24 < bridge> Well it tested it, seems like it allocs 2 buckets only 15:24 < bridge> https://cpp.sh/?source=%2F%2F+Example+program%0A%23include+%3Ciostream%3E%0A%23include+%3Cstring%3E%0A%0Aint+main()%0A%7B%0A++std%3A%3Astring+name%3B%0A++std%3A%3Acout+%3C%3C+%22What+is+your+name%3F+%22%3B%0A++getline+(std%3A%3Acin%2C+name)%3B%0A++std%3A%3Acout+%3C%3C+%22Hello%2C+%22+%3C%3C+name+%3C%3C+%22!%5Cn%22%3B%0A%7D 15:24 < bridge> Re2 beats rust regex, wow, c++ best 15:25 < bridge> I assume it switches it's internal algorithm quite often 15:25 < bridge> oh 15:25 < bridge> that didnt work 15:25 < bridge> https://cpp.sh/?source=%2F%2F+Example+program%0A%23include+%3Ciostream%3E%0A%23include+%3Cstring%3E%0A%23include+%3Cunordered_map%3E%0A%0Aint+main()%0A%7B%0A++std%3A%3Aunordered_map%3Cunsigned+char%2C+std%3A%3Astring%3E+name%3B%0A++name.insert(%7B0%2C+%22%22%7D)%3B%0A++name.insert(%7B255%2C+%22%22%7D)%3B%0A++%0A++std%3A%3Acout+%3C%3C+%22Hello%2C+%22+%3C%3C+name.bucket_count()+%3C%3C+%22!%5Cn%22%3B%0A++for+(int+i+%3D+0%3B+i+%3C+name.bucket_count 15:25 < bridge> not in many cases 15:25 < bridge> now 15:25 < bridge> c 15:25 < bridge> c++ always on top 15:25 < bridge> btw the image is 8y old 15:25 < bridge> 3 15:25 < bridge> * 15:25 < bridge> 3y 15:26 < bridge> rust definetly slower in these 3 years 15:26 < bridge> isnt it impl defined 15:26 < bridge> yes, but i only care about linux perf ofc 15:26 < bridge> which this tool probs uses 15:26 < bridge> well linux has 2 compilers 15:26 < bridge> gcc and llvm 15:26 < bridge> i assume if u compile with clang u rarely use the clang cpp runtime 15:26 < bridge> but yeah if you want to test 15:27 < bridge> go ahead 15:27 < bridge> xd 15:27 < bridge> i wonder the lib std from llvm is faster 15:27 < bridge> afaik it's often equal, sometimes slower 15:27 < bridge> But things change 15:28 < bridge> especially since android does not really support gcc anymore 15:28 < bridge> google pushes 15:30 < bridge> where u have that from btw? 15:30 < bridge> so 15:30 < bridge> ah too bad 15:32 < bridge> @ryozuki i think for hashmaps it was even worse or not? 15:32 < bridge> the cpp std one is rather slow. 15:32 < bridge> 15:32 < bridge> 15:32 < bridge> But let's face it, u rarely notice a diff in real world anyway xdd 15:40 < bridge> Look at this non scientific benchmark: 15:40 < bridge> ``` 15:40 < bridge> ctf1, move_box Vec: 15:40 < bridge> 7.049902133 s - pos: vec2_base { x: 640.00037, y: 433.02246 }, vel: vec2_base { x: 320.0, y: -0.0 } 15:40 < bridge> 141845.94071442267 call/s 15:40 < bridge> 6.935108404 s - pos: vec2_base { x: 640.00037, y: 433.02246 }, vel: vec2_base { x: 320.0, y: -0.0 } 15:40 < bridge> 144193.8527483182 call/s 15:40 < bridge> 6.815435359 s - pos: vec2_base { x: 640.00037, y: 433.02246 }, vel: vec2_base { x: 320.0, y: -0.0 } 15:40 < bridge> 146725.76986288454 call/s 15:40 < bridge> 15:40 < bridge> ctf1, move_box FxHashMap: 15:40 < bridge> 12.252110956 s - pos: vec2_base { x: 640.00037, y: 433.02246 }, vel: vec2_base { x: 320.0, y: -0.0 } 15:40 < bridge> 81618.58830622886 call/s 15:40 < bridge> 11.270511348 s - pos: vec2_base { x: 640.00037, y: 433.02246 }, vel: vec2_base { x: 320.0, y: -0.0 } 15:40 < bridge> 88727.11886115569 call/s 15:40 < bridge> 11.329539075 s - pos: vec2_base { x: 640.00037, y: 433.02246 }, vel: vec2_base { x: 320.0, y: -0.0 } 15:40 < bridge> 88264.84408413588 call/s 15:40 < bridge> 15:40 < bridge> ctf1, move_box std HashMap: 15:40 < bridge> 34.203735266 s - pos: vec2_base { x: 640.00037, y: 433.02246 }, vel: vec2_base { x: 320.0, y: -0.0 } 15:40 < bridge> 29236.57291296028 call/s 15:40 < bridge> 33.750160829 s - pos: vec2_base { x: 640.00037, y: 433.02246 }, vel: vec2_base { x: 320.0, y: -0.0 } 15:41 < bridge> 29629.488436118645 call/s 15:41 < bridge> ``` 15:41 < bridge> 15:41 < bridge> 15:41 < bridge> The hash function is what makes it super slow xdd 15:41 < bridge> 15:41 < bridge> I changed the map game layer tiles from vec to hashmap. 15:41 < bridge> 15:41 < bridge> The FxHashMap is not even 2x slower. 15:44 < bridge> blazingly slow? :troll: 15:44 < bridge> only trust benchmarks 15:46 < bridge> https://cdn.discordapp.com/attachments/293493549758939136/1356988268620550205/image.png?ex=67ee914e&is=67ed3fce&hm=90204456e87bf9cfb8f75d36c5170cff48ff8534f793cb10396575c5bdfdd8fe& 15:49 < bridge> I always wondered if ddnet would benefit from a quad tree, as we can optimize out so many collision checks 15:49 < bridge> yeah 15:49 < bridge> we already talked about that lot of times 15:49 < bridge> quad tree is probs too slow 15:49 < bridge> I know 15:49 < bridge> we cant change physics too 15:49 < bridge> but spatial hashing 15:50 < bridge> i used a spatial hashing in the vanilla impl of ddnet-rs and it easily beats all other implementations for many tees 15:50 < bridge> well i used a optimized form of spatial hasing i'd say 15:50 < bridge> the definition sounds more generalized 15:52 < bridge> 64-tee benchmark: 15:52 < bridge> vanilla 15:52 < bridge> ``` 15:52 < bridge> 32534 t/s 15:52 < bridge> 33871 t/s 15:52 < bridge> ``` 15:52 < bridge> 15:52 < bridge> twgame: 15:52 < bridge> ``` 15:52 < bridge> 9725 t/s 15:52 < bridge> 10219 t/s 15:52 < bridge> ``` 15:52 < bridge> 15:52 < bridge> 512-tee benchmark: 15:52 < bridge> vanilla 15:52 < bridge> ``` 15:52 < bridge> 3766 t/s 15:52 < bridge> 3771 t/s 15:52 < bridge> ``` 15:52 < bridge> 15:52 < bridge> twgame: 15:52 < bridge> ``` 15:52 < bridge> 346 t/s 15:52 < bridge> 299 t/s 15:53 < bridge> ``` 15:53 < bridge> on a 9950x3d, which i'll not be able to reproduce anymore 15:53 < bridge> 😬 15:53 < bridge> what is t 15:53 < bridge> tick? 15:53 < bridge> yeah 15:53 < bridge> _random_ input 16:18 < bridge> who has access to master server bans? heinrich only? 16:19 < bridge> Legacy masger only heinrich, the httpmaster any ddnet admin 16:19 < bridge> Legacy master only heinrich, the httpmaster any ddnet admin 16:22 < bridge> for httpmaster i can open ticket for report server? 16:22 < bridge> Yep an admin-mail ticket would be appropriate 16:24 < bridge> can you give me info, after you got an admin answer? 16:26 < bridge> I think not, the problem has already been resolved, after talking to the server administrator, they stole the map and made the same server name (some schoolboy) :nouis: 16:37 < bridge> <_qey> Been there… 16:38 < bridge> <_qey> Was there ever a DDNet version 18091? 16:38 < bridge> <_qey> On a legit official client? 16:39 < bridge> <_qey> Also 14062? 16:41 < bridge> <_qey> 18091 translates to 18.9.1? 14062 to 14.6.2? 16:41 < furo> 18091 is 18.9.1, yes. 16:44 < bridge> <_qey> Though they usually close the server within a week or two due to lack of player activity. 16:44 < bridge> @jupeyy_keks before we discuss much on github, want to do it quickly here? 16:45 < bridge> You have few minutes then my package arrives 16:46 < bridge> I answered: 16:46 < bridge> > This is just Step one, next step would be to add functions taking LayerType as an argument and generalizing over all of this layer checks. Also, these bools are exclusive, you can't have a tileLayer, which is a switch AND a tune layer for example. 16:46 < bridge> & 16:46 < bridge> > Additionally in cases like LayerType <= LAYER_FRONT i collabs 3 times duplicated code to 1 16:46 < bridge> In the mock I made I had like 8 functions, and 2 with switch cases for LayerType, the rest was generalized out 16:47 < bridge> I am ok with collapsing the if stuff 16:47 < bridge> it's more about readability 16:47 < bridge> Reminder to check performance in release mode, evaluating the performance difference in debug build is not meaningful. The FPS in both screenshots look pretty low to me 16:48 < bridge> This was build in release mode 16:48 < bridge> the debug console works in release mode. 16:48 < bridge> How many FPS do you have on a small/empty map? 16:49 < bridge> I capped my game to 990, so I guess about 2K? 16:49 < bridge> Honestly 20 more fps for that change is defs not true 16:49 < bridge> What should be so much faster? 16:49 < bridge> I never claimed that 16:49 < bridge> > I checked if this impacts performance, and I can't tell if it does or not, which is good. 16:49 < bridge> Ok 16:49 < bridge> @jupeyy_keks package arriving??? 16:49 < bridge> Got baited 16:49 < bridge> Yes 16:49 < bridge> when 16:50 < bridge> I dunno, probs next 10-15mins 16:50 < bridge> it only gives an estimate 16:50 < bridge> cam? 16:50 < bridge> `Configure->Release` FYI 16:50 < bridge> https://cdn.discordapp.com/attachments/293493549758939136/1357004215108505761/Unbenannt.PNG?ex=67eea028&is=67ed4ea8&hm=356707753e462e9bb964f40e08aa972156650e9941ad2e13eb4cf3bd7d2132b6& 16:50 < bridge> I dunno how I should hold the cam with only 2 hands, which i need to build @teero777 soz xD 16:50 < bridge> use headlight 16:50 < bridge> leak address i come over and hold 16:50 < bridge> Alr 16:50 < bridge> Fly over 16:51 < bridge> @jupeyy_keks 16:51 < bridge> https://cdn.discordapp.com/attachments/293493549758939136/1357004404007370904/iu.png?ex=67eea055&is=67ed4ed5&hm=48e826d9ae4ae3c1366f284ee114b9905538f95f26d51679485699614ebc4da6& 16:51 < bridge> ok ok, i'll quickly search smth xDD 16:52 < bridge> 4900 - 5xxx .... can't tell 16:54 < bridge> So rendering on this map is just very slow in general 16:54 < bridge> this is an extreme case, yes 16:54 < bridge> With my PR 16:54 < bridge> https://cdn.discordapp.com/attachments/293493549758939136/1357005357087723732/screenshot_2025-04-02_16-53-26.png?ex=67eea139&is=67ed4fb9&hm=00552dafb0a960ccbac453170060b2e300b88bee43a642ee3c14b82b4835c5f6& 16:55 < bridge> Wihtout my PR 16:55 < bridge> https://cdn.discordapp.com/attachments/293493549758939136/1357005405498118415/screenshot_2025-04-02_16-54-03.png?ex=67eea144&is=67ed4fc4&hm=0b58c1b677dec1c442a76f430f13eeb4e3b676d0fe7cc59b09aafc44dcab6c1e& 16:55 < bridge> this looks bad, but there is no difference, like my FPS is heavily impacted by other things and flying around like crazy 16:55 < bridge> <_qey> I have 67 fps! 16:56 < bridge> <_qey> Never crossed my mind DDNet could run at 5k fps, lol. 16:56 < bridge> easily with a last gen graphics card on a 2K monitor 16:58 < bridge> I don't know how to do proper fps benchmarking for ddnet 17:00 < bridge> outlining a function shouldnt affect performance at all 17:02 < bridge> only outlining it, no, optimizing it might 17:02 < bridge> doesnt look like much changed 17:02 < bridge> might be slightly faster as it can early exit and needs like 7 comparisons less on average, witch is nothing on 3.7GHz 17:03 < bridge> and then cache effects and measurement is in the mud anyway 17:03 < bridge> this will be rearanged to an if else chain 17:03 < bridge> https://cdn.discordapp.com/attachments/293493549758939136/1357007504978215023/image.png?ex=67eea339&is=67ed51b9&hm=5cbeb70bc686d9a05365b601b5ac7538acea727b0fef6c77cfda04788d55ef32& 17:03 < bridge> given compilesr are smart 17:03 < bridge> well im also basing my "not much has changed" on the benchmark you did, so a bit circular assumptions lmao 17:03 < bridge> I did anyways, why not 17:04 < bridge> why not :) 17:04 < bridge> nothing has changed in terms of FPS 17:04 < bridge> ik 17:04 < bridge> Like how should I know if I have an fps on average more or not? xD 17:04 < bridge> <_qey> I wonder how everyone’s day going while I’m compiling the server build? 17:10 < bridge> troll pr, troll comment πŸ˜„ 17:10 < bridge> it felt like a linus torvalds moment, kinda 17:13 < bridge> @ryozuki i will add `icmp` instruction to my compiler backend and will try to use it in my language 17:13 < bridge> is it time or throughput ? why are some cases highlighted and others aren't ? 17:15 < bridge> nice 17:16 < bridge> @teero777 discord too buggy. Doesn't see my camera 17:16 < bridge> doesnt load 17:23 < bridge> https://call.element.io/room/#/jupstarbuild?password=y9B3WMnToUCsIK6Og3y2TA&roomId=%21KTrwlQsuOmfuZSVEpe%3Acall.ems.host 17:23 < bridge> @teero777 go 17:23 < bridge> jez oder nie 17:50 < bridge> Hey guys, where are skins like `horsouly` `4kultrahdskin` etc coming from? 17:50 < bridge> Hellou :3 17:51 < bridge> we blame @soulyvevo for that 17:51 < bridge> im gonna punch you 17:51 < bridge> yes please 17:51 < bridge> hehe, where are those downloaded from? 17:51 < bridge> 😳 17:52 < bridge> those skins were in the database as a part of april fools joke, skins already got removed from the database and arent visible on the website 17:53 < bridge> but due to how skin downloading works it will take some time till those skins will be completely gone 17:53 < bridge> can we add them if i make them saddo? 17:53 < bridge> yes 17:53 < bridge> ahhh crap 17:53 < bridge> that's why I couldn't find them 17:53 < bridge> but they still have to be somewhere 17:53 < bridge> like I cannot download what's not there 17:54 < bridge> like if `https://skins.ddnet.org/skin/community/yomaheart_yomasoul.png` does not exist then how the hell I am able to have it ingame 17:55 < bridge> because you have it as a file locally 17:55 < bridge> its probably still in your downloadedskins folder 17:55 < bridge> $config 17:55 < bridge> This command was not found. 17:55 < bridge> $config_dir 17:55 < bridge> This command was not found. 17:55 < bridge> $configdir 17:55 < bridge> :c 17:55 < bridge> poor patiga 17:55 < bridge> xD 17:55 < bridge> removing skins from the database doesnt remove it from that directory 17:56 < bridge> anyway if you want to check out all of those skins there you go 17:56 < bridge> https://cdn.discordapp.com/attachments/293493549758939136/1357020876369039461/4kultrahdskin.png?ex=67eeafad&is=67ed5e2d&hm=0d40895ffcfdac31edcb5980075720e560130d36e79261e71635e7f39439c5c6& 17:56 < bridge> https://cdn.discordapp.com/attachments/293493549758939136/1357020876830281728/me_when_fine_shyt.png?ex=67eeafad&is=67ed5e2d&hm=92b660683011a00446500c9347a62fba372f2fd787e64c7b9aff21b483657315& 17:56 < bridge> https://cdn.discordapp.com/attachments/293493549758939136/1357020877174079728/nahbruhnowayhellnah.png?ex=67eeafad&is=67ed5e2d&hm=95473d67a471d2eebbd06bc73fd77a6c8d706a85be4bb0f5e69a49e72a61c029& 17:56 < bridge> https://cdn.discordapp.com/attachments/293493549758939136/1357020877526405160/ilovesellingcopper.png?ex=67eeafad&is=67ed5e2d&hm=0b3e2c2125aec842d61b3d2414034260b868f7d93ef47af43789c4b75f513369& 17:56 < bridge> https://cdn.discordapp.com/attachments/293493549758939136/1357020877887373493/horsouly.png?ex=67eeafad&is=67ed5e2d&hm=6892571661f02ae65c21afdfd3ae680ce1be51f6c192e3ccd2330bd38af1e90c& 17:56 < bridge> https://cdn.discordapp.com/attachments/293493549758939136/1357020878369587331/muchlovefromddnetteam.png?ex=67eeafad&is=67ed5e2d&hm=e613410dc66f7f7da824bdf24237c9f978dc88eeeea8c802b184cfb4f4c2cb37& 17:56 < bridge> https://cdn.discordapp.com/attachments/293493549758939136/1357020879086944527/78fwa9r983.png?ex=67eeafad&is=67ed5e2d&hm=86ddfd709091f4d65dc6cfe3e376043b8e0c8ddb6dc01c9f503df3e13ea215da& 17:56 < bridge> https://cdn.discordapp.com/attachments/293493549758939136/1357020879422357574/yomaheart_yomasoul.png?ex=67eeafad&is=67ed5e2d&hm=8901d2d5db1820675df45a717fce5fe387f89a97e7295d3f36f2a252f4780c2f& 17:56 < bridge> true work of art 17:56 < bridge> ohh, that's interesting, I did not realise I had them there 18:01 < bridge> so i made something like this 18:01 < bridge> https://cdn.discordapp.com/attachments/293493549758939136/1357022204159594546/snowflake_icons.png?ex=67eeb0e9&is=67ed5f69&hm=abe83bb8449fba81fdd5498eacaef5677aaa73abcf1dac96d2a11d2ed37db313& 18:01 < bridge> but im not really sure about it 18:02 < bridge> because it looks weird with that fast changing animation 18:02 < bridge> https://cdn.discordapp.com/attachments/293493549758939136/1357022376088571935/coverage_2025-04-02_17-59-36.mp4?ex=67eeb112&is=67ed5f92&hm=b39f7f7d5a7f7b4bef24b5a01a593d0287030ad1aee09859163e3e5226286495& 18:02 < bridge> I think I wrote above, that we might only need the background for the one existing snowflake πŸ€” 18:03 < bridge> one thing looking weird is the background ofc 18:03 < bridge> ye could be worth checking how it looks with that hexagon shape as bg 18:04 < bridge> I think a single snowflake sprite rotating fast might be enough 18:04 < bridge> how are those outlines even generated in game 18:04 < bridge> it looks so weird lol 18:04 < bridge> usually they are the original sprite, bug bigger and darker color 18:04 < bridge> (it's the otherway round but whatever) 18:04 < bridge> aah i see 18:04 < bridge> usually they are the original sprite, but bigger and darker color 18:05 < bridge> scaling is not the same as adding a pixel on each site, so you'll have issues on any non concarve shape (like a snowflake) 18:05 < bridge> and that's why it needs it's own background sprite 18:07 < bridge> yet another crazy idea, use a distance shader or something ... nah 18:07 < bridge> @essigautomat i tried to make it match that snowflake in extras 18:07 < bridge> https://cdn.discordapp.com/attachments/293493549758939136/1357023709910663199/hexagon.png?ex=67eeb250&is=67ed60d0&hm=4966e4bfa7c1dff40ebc2b856ca7034ee2d652facdf868edb8760c439b0f3a39& 18:08 < bridge> nice :3 18:08 < bridge> the issue i have is that snowflake is kinda big 18:08 < bridge> yes don't worry, I'll have to scale it down 18:08 < bridge> but don't expect immediate results, the door brick isn't even merged yet 😦 18:08 < bridge> aight 18:10 < bridge> i have a few more designs if thats ever needed 18:10 < bridge> https://cdn.discordapp.com/attachments/293493549758939136/1357024385147601097/image.png?ex=67eeb2f1&is=67ed6171&hm=62cf86ee5dc543ec58600573a0b988f8aa5e1104dc16aaca23d2e02933db6885& 18:11 < bridge> generate snowflakes at runtime 18:11 < bridge> because no two snowflakes are the same 18:14 < bridge> hmm 18:16 < bridge> wait yeah why is it animated its probably better without changing 18:35 < bridge> new pc again 18:35 < bridge> https://cdn.discordapp.com/attachments/293493549758939136/1357030585062789160/image.png?ex=67eeb8b7&is=67ed6737&hm=5dfda1bc920b12cd63958ab478b5e064ba67073c28be674456ef9093b126bdfe& 18:35 < bridge> :deen_star: 18:35 < bridge> buy me a new pc :deen_star: 18:36 < bridge> We big frens now 18:50 < bridge> for much money u have? 18:50 < bridge> github just gave me a unicorn page 18:50 < bridge> lol 18:58 < bridge> @robyt3 with your pr i still get loading skins at the start 18:58 < bridge> 18:58 < bridge> ```cpp 18:58 < bridge> // load skins 18:58 < bridge> Refresh([this]() { 18:58 < bridge> GameClient()->m_Menus.RenderLoading(Localize("Loading DDNet Client"), Localize("Loading skin files"), 0); 18:58 < bridge> }); 18:58 < bridge> ``` 18:58 < bridge> 18:58 < bridge> i assume that is this 18:58 < bridge> 18:58 < bridge> i dont think any skins should be loaded by default 18:58 < bridge> 18:58 < bridge> with the really slow network drive this still takes a decent chunk of time to load 19:01 < bridge> $0, it will be a birthday gift :kek: 19:01 < bridge> This command was not found. 19:03 < bridge> It only loads the default skin otherwise you wouldn't have a placeholder while other skins load. And the list of skins is loaded so the skins list isn't empty and the client knows if it has to load a skin from skins or downloadedskins. 19:04 < bridge> Also, lazy loading isn't implemented for 0.7 skins and parts 19:05 < bridge> its probably that then 19:05 < bridge> is that on the todo 19:08 < bridge> For the future, I guess, but probably not in that PR, it's already large 19:10 < bridge> 0.7 skins and parts are pretty small so it should be almost negligible. Listing all the files over the network probably already takes some time for you. 19:12 < bridge> im using sshfs 19:12 < bridge> listing files *feels* O(1) regardless of size 19:12 < bridge> loading a file has a large initial delay but is then very fast 19:12 < bridge> so loading lots of small files is very slow 19:22 < bridge> @ryozuki do you know why there're signed and unsigned versions of comparison? https://llvm.org/docs/LangRef.html#icmp-instruction 19:24 < bridge> less than and greater than should be different for signed/unsigned 19:24 < bridge> wait no 19:25 < bridge> are there different instructions for signed/unsigned less/greater than? :thonk: 19:25 < bridge> i know only of `cmp` 19:26 < bridge> ah negative numbers need to be compared differently 19:28 < bridge> arg why am I confusing myself so much :D 19:28 < bridge> ah yes, negative numbers would be greater than positive numbers 19:28 < bridge> because their most significant bit is set in the two's complement 19:31 < bridge> hrmpf ignore everything I said, cmp does math and is smart 19:31 < bridge> (https://www.felixcloutier.com/x86/cmp) 19:31 < bridge> thanks for the refresher 20:18 < bridge> you use cmp for both but check different flags afterwards 20:18 < bridge> ye ye, I got it, thanks :happy: 20:28 < bridge> (btw just looking at the examples below would have told you why) 20:29 < bridge> didn't go that far xd 20:31 < bridge> ((or compiling a very small piece of C to see what changes when you do an unsigned vs signed compare πŸ˜› )) 20:32 < bridge> flags are magic to me 20:35 < bridge> > The terms "above" and "below" are associated with the CF flag and refer to the relationship between two unsigned integer values. The terms "greater" and "less" are associated with the SF and OF flags and refer to the relationship between two signed integer values. 20:35 < bridge> Mhm 21:48 < bridge> nice my fedora broke 21:48 < bridge> rip 22:01 < bridge> my cursor is huge when hovering over chrome 😭 22:05 < bridge> its excited 22:40 < bridge> if the client expects more fields in a netobject than the server is sending, will it just be unable to join? 22:41 < bridge> i still cannot deal with pr & issue number being over 10k xD 22:41 < bridge> looks so verbsoe 22:54 < bridge> It’s over 9000 23:03 < bridge> halo 23:05 < furo> @louis It will drop the message, assuming the fields don't have a default value specified. 23:06 < bridge> hey 23:06 < bridge> ```js 23:06 < bridge> f=a=>{lines=a.split("\n").filter(a=>-1==="/*".indexOf(a.trim()[0])).map(a=>a.trim()).filter(a=>a).filter(a=>!a.toLowerCase().startsWith("function:")),out={param:[],return:[],remark:[],see:[]},head="desc";for(const b of lines){if(b.endsWith(":")){head=b.slice(0,-1).toLowerCase(),head=head.replace("parameters","param"),head.endsWith("s")&&(head=head.slice(0,-1));continue}out[head]=[...(out[head]??[]),b]}out.param=out.param.map(a=>-1===a.index 23:06 < bridge> ``` 23:06 < bridge> average js script 23:06 < bridge> ```js 23:06 < bridge> f(test) 23:06 < bridge> /** 23:06 < bridge> * Compares up to num bytes of two utf8 strings case insensitively. 23:06 < bridge> * 23:06 < bridge> * @param a String to compare. 23:06 < bridge> * @param b String to compare. 23:06 < bridge> * @param num Maximum bytes to compare. 23:06 < bridge> * 23:06 < bridge> * @return `< 0` - String a is less than string b 23:06 < bridge> * @return `0` - String a is equal to string b 23:07 < bridge> * @return `> 0` - String a is greater than string b 23:07 < bridge> */ 23:07 < bridge> ``` 23:07 < bridge> converts old style docs to jsdoc 23:07 < bridge> :) 23:08 < bridge> solly 23:11 < bridge> yes 23:12 < bridge> oh there was a mistake 23:12 < bridge> ```js 23:13 < bridge> f=a=>{lines=a.split("\n").filter(a=>-1==="/*".indexOf(a.trim()[0])).map(a=>a.trim()).filter(a=>a).filter(a=>!a.toLowerCase().startsWith("function:")),out={param:[],return:[],remark:[],see:[]},head="desc";for(const b of lines){if(b.endsWith(":")){head=b.slice(0,-1).toLowerCase(),head=head.replace("parameters","param"),head.endsWith("s")&&(head=head.slice(0,-1));continue}out[head]=[...(out[head]??[]),b]}out.param=out.param.map(a=>-1===a.index 23:13 < bridge> ``` 23:13 < bridge> average js script 23:13 < bridge> another one but its non fatal so to spare chillers chatlog im not going to edit it again 23:14 < bridge> Cute solly Moment 23:15 < bridge> im always cute 23:29 < bridge> `out.desc.at(-1) += ".";` 23:29 < bridge> this is invalid and it took me ages to figure it out 23:39 < bridge> 😳 23:39 < bridge> what the fuck is that 23:54 < bridge> eww frontend