--- Log opened Tue Apr 10 00:00:38 2018 20180410 00:12:21-!- octalot [~steve@213-225-13-31.nat.highway.a1.net] has quit [Ping timeout: 264 seconds] 20180410 00:28:34-!- grzywacz [~karol@89-70-226-147.dynamic.chello.pl] has quit [Ping timeout: 264 seconds] 20180410 01:08:28< irker617> wesnoth/wesnoth:master Jyrki Vesterinen 134a51204b Convert README for manual images to Mark AppVeyor: All builds passed 20180410 01:42:11<+discordbot> ohhh kay somehow I managed to fuck up my VS .. 20180410 01:44:28<+discordbot> How the hell did I revert all my VS15 files to VS 14 files. 20180410 01:44:35<+discordbot> like 20180410 01:44:36<+discordbot> just 20180410 01:44:39<+discordbot> what in hell 20180410 01:46:38<+discordbot> rebuilds 20180410 01:57:22-!- mattsc [~mattsc@wesnoth/developer/mattsc] has joined #wesnoth-dev 20180410 02:06:29-!- stikonas [~gentoo@wesnoth/translator/stikonas] has quit [Remote host closed the connection] 20180410 02:44:10<+discordbot> celmin: is map sort stable? 20180410 02:45:10< celticminstrel> Uh. 20180410 02:45:20< celticminstrel> I have no idea. 20180410 02:45:34< celticminstrel> Oh, wait. 20180410 02:45:47< celticminstrel> Stability is irrelevant when there are no duplicate keys. 20180410 02:45:59< celticminstrel> So your question might make sense to ask of multimap, but not of map. 20180410 02:46:32<+discordbot> "The order of the key-value pairs whose keys compare equivalent is the order of insertion and does not change. (since C++11)" 20180410 02:46:40<+discordbot> that is stable, yes? 20180410 02:47:04< celticminstrel> Where are you seeing this? 20180410 02:47:50<+discordbot> cppppppppreference 20180410 02:47:59< celticminstrel> Just link it... 20180410 02:48:05<+discordbot> http://en.cppreference.com/w/cpp/container/multimap 20180410 02:48:21< celticminstrel> Ah, so you are looking at multimap. 20180410 02:48:56< irker617> wesnoth: Charles Dang wesnoth:master d6ee95c763bb / src/spritesheet_generator.cpp: Spritesheet Generator: simplified sheet height calculation https://github.com/wesnoth/wesnoth/commit/d6ee95c763bbc2b3a3b431c60f8250d562552fce 20180410 02:48:59< irker617> wesnoth: Charles Dang wesnoth:master f9e44ea2821b / src/spritesheet_generator.cpp: Spritesheet Generator: simplified intermediate surface data storage https://github.com/wesnoth/wesnoth/commit/f9e44ea2821b00207ebc078cdf184d4c2bc8e24e 20180410 02:49:07<+discordbot> I had been wondering why my sheet output looked different when the surfaces were sorted by a multimap than by std::sort 20180410 02:49:31<+discordbot> using std::stable_sort makes the order identical 20180410 02:49:32< celticminstrel> It doesn't feel sensible to call that stable or unstable. 20180410 02:49:50< celticminstrel> It's order of insertion when they compare equivalent. 20180410 02:50:01<+discordbot> though for some reason, the bridge sheet was 1.10 MB with std::sort and 1.12 MB with std::stable_sort 20180410 02:50:03<+discordbot> odd 20180410 02:50:04< celticminstrel> That would produce the same order as a stable_sorted vector though. 20180410 02:50:22< celticminstrel> Because the initial order in the vector is order of insertion, and stable_sort does not reorder equivalent values. 20180410 02:59:29<+discordbot> celmin: dost thou know threading? 20180410 02:59:49< celticminstrel> A little, why? 20180410 03:00:18<+discordbot> was wondering if this is totally incorrect: https://pastebin.com/BpjpEaLH 20180410 03:00:54< celticminstrel> Uh. I doubt it? 20180410 03:01:03<+discordbot> because it crashes 20180410 03:01:06<+discordbot> the game 20180410 03:01:14< celticminstrel> Oh, totally incorrect. 20180410 03:01:18< celticminstrel> Then probably. 20180410 03:01:34< celticminstrel> The key issue I can see is that the thread object is local to the for-loop. 20180410 03:02:23< celticminstrel> Oh huh, that actually is an automatic crash unless you've called join or detach on the thread. 20180410 03:02:29< celticminstrel> Which you clearly haven't. 20180410 03:02:42< celticminstrel> And you definitely don't want to call join because that would totally defeat the purpose of using thread.s 20180410 03:03:04< celticminstrel> Probably don't want detach either, I think that means you can no longer track the thread's progress. 20180410 03:04:03< celticminstrel> I think the contents of the thread function is also wrong. 20180410 03:04:26<+discordbot> moved the lock below the image loading 20180410 03:04:27< celticminstrel> In particular, you're blocking the other threads while an io operation is ongoing; I think I'd rather swap the first two lines at a minimum. 20180410 03:04:34< celticminstrel> Yeah that. 20180410 03:05:00< celticminstrel> You could also use the RAII lock, std::lock_guard or something? Rather than calling lock and unlock manually. 20180410 03:05:44< celticminstrel> (It takes the mutex as a parameter IIRC.) 20180410 03:06:44< celticminstrel> Anyway, the other change I'd make is emplacing the threads into a container that's defined outside the loop, and at some point where you need the "surfs" container fully populated, call join() on every thread and then clear the thread container. 20180410 03:07:16< celticminstrel> I'm not sure if that's the best way of doing it, but I think it's probably at least not completely wrong. 20180410 03:07:23<+discordbot> I need it populated right away 20180410 03:07:44< celticminstrel> Then right after the loop you can loop over the threads and join them. 20180410 03:08:22<+discordbot> but why would I join them 20180410 03:08:28<+discordbot> I want the images to load in tandem 20180410 03:08:36<+discordbot> but just be added to the vector one at a time 20180410 03:08:40< celticminstrel> Join really means wait. 20180410 03:09:05<+discordbot> oh, wait 20180410 03:09:06< celticminstrel> When you call join() on a thread, it blocks execution of the current thread until that thread has completed. If that thread has already completed, it returns immediately. 20180410 03:09:25<+discordbot> you're saying hold off on the main thread until all the threads are done? 20180410 03:09:28< celticminstrel> Yes. 20180410 03:09:41< celticminstrel> Once you've joined all the threads, the images are guaranteed to all be loaded. 20180410 03:09:54< celticminstrel> Possibly not in the same order that you queued them though. 20180410 03:10:07<+discordbot> doesn't matter 20180410 03:10:08< celticminstrel> I imagine it also depends on which threads get unblocked for I/O first. 20180410 03:10:10<+discordbot> the vector is then sorted 20180410 03:10:32< celticminstrel> Well it does mean the order of equivalent keys would be unpredictable though. 20180410 03:10:37< celticminstrel> So, just don't rely on it. 20180410 03:12:35<+discordbot> Vultraz, what are you adding threaded loading to? 20180410 03:12:39<+discordbot> so something like this? https://pastebin.com/01jD5rNX 20180410 03:12:47<+discordbot> @shadowm the sheet generator 20180410 03:12:59<+discordbot> Is it complete? Has it been in master for a while? 20180410 03:13:13<+discordbot> I added it like 12 hours ago... 20180410 03:13:22<+discordbot> In master, right? 20180410 03:13:27<+discordbot> yes 20180410 03:13:29<+discordbot> why? 20180410 03:13:50<+discordbot> Just making sure you're not falling into the trap of premature optimization. 20180410 03:14:07<+discordbot> jyrki said this should be threaded 20180410 03:14:35<+discordbot> "Premature optimization is the root of all evil" -- Famous computer scientist, Napoleon Boneparte. 20180410 03:14:57<+discordbot> I wonder why it needs to be threaded. I assume you know the reason. 20180410 03:15:43<+discordbot> the intent was just to thread the image loading 20180410 03:16:44<+discordbot> I know that. 20180410 03:16:47<+discordbot> My question is why. 20180410 03:17:19<+discordbot> it's likely the speed bottleneck 20180410 03:18:09<+discordbot> That's not speculation, right? 20180410 03:18:28<+discordbot> The way you phrased it sounds like speculation but I might be reading it wrong. 20180410 03:19:28<+discordbot> Jyrki didn't state it a certainty, he said it likely. So I'm trying to test the theory. I got the execution time without threads, and wanted to test with threading 20180410 03:19:35<+discordbot> but I can't get it to work 20180410 03:20:18<+discordbot> Sigh. 20180410 03:21:21<+discordbot> What the hell is wrong with testing a theory??? 20180410 03:21:45<+discordbot> What is that overreaction? 20180410 03:23:39<+discordbot> My only problem is that the theory seems to have been conjured out of thin air rather than based upon actual analysis of the execution of the code in question. But that's the way you're presenting it -- I assume he had actual reasons to come up with it that you're not communicating to me. 20180410 03:24:17<+discordbot> He just said "Needs multithreaded image loading." 20180410 03:24:43<+discordbot> So instead of relying on someone else to do this, I figured it's a good basic learning exercise for working with threads 20180410 03:24:49<+discordbot> I've never done threaded programming before 20180410 03:24:53<+discordbot> Right. 20180410 03:25:54<+discordbot> Good luck to you. Just bear this in mind and please do not take it personally: 20180410 03:25:54<+discordbot> https://cdn.discordapp.com/attachments/259976436490829825/433105314217197569/unknown.png 20180410 03:26:44<+discordbot> nods 20180410 03:28:20<+discordbot> celmin: ftr, the code in my last paste doesn't work either. It just hangs. 20180410 03:30:52<+discordbot> @jyrkive perhaps you could weigh in? 20180410 03:31:52<+discordbot> First of all: I don't know if image cache manager is thread-safe and if you can load images in multiple threads that way. 20180410 03:32:05<+discordbot> (Maybe we should rip out the whole image cache manager.) 20180410 03:32:32<+discordbot> the image cache manager uses openmp 20180410 03:32:41<+discordbot> That's not the same thing. 20180410 03:32:50<+discordbot> Using OpenMP, by itself, doesn't guarantee anything. 20180410 03:32:50< celticminstrel> If it hangs, that probably means it's blocked waiting for a lock to unlock? 20180410 03:33:01< celticminstrel> Also don't forget that OpenMP is not used on all platforms. 20180410 03:33:07< celticminstrel> So you can't even rely on it being used. 20180410 03:33:08<+discordbot> OpenMP just allows you to parallelise specific portions of code (loops mainly). 20180410 03:33:28<+discordbot> I only mention it in case it has some bearing on thread safe-ness 20180410 03:33:29<+discordbot> It's not a "instant threads just add water" solution. 20180410 03:33:47< celticminstrel> That paste is indeed what I was getting at, so I'm not sure what the issue is with it now. 20180410 03:33:52<+discordbot> The whole point is that the code using OMP up to now only ever runs in a single-threaded context. 20180410 03:34:21<+discordbot> Regarding the performance advantage: no, I haven't tested it. It wouldn't be that hard to test, though. 20180410 03:34:52<+discordbot> At this point it's indeed just my speculation that threading image loading would significantly speed it up. 20180410 03:35:09<+discordbot> Especially on SSDs, which can perform multiple read operations in parallel. 20180410 03:35:12<+discordbot> (the surface cache would probably need to make use of std::atomic, I'm guessing) 20180410 03:35:25<+discordbot> (Or completely bypassed or removed.) 20180410 03:35:48< irker617> wesnoth/wesnoth:1.14 Jyrki Vesterinen 6ce6c89b70 Convert README for manual images to Mark AppVeyor: All builds passed 20180410 03:35:57< celticminstrel> I imagine it could make a difference on HDDs too? If it can reorder the read operations somehow? I dunno. 20180410 03:35:57<+discordbot> Do you want me to try bypassing it? 20180410 03:36:20<+discordbot> HDDs can reorder reads and writes and operating systems can help with that. 20180410 03:36:21<+discordbot> Yep. https://en.wikipedia.org/wiki/Native_Command_Queuing 20180410 03:37:11< celticminstrel> Because the problem with HDDs is that it needs to wait for the head to get to the proper location before it can read, right? So if it just so happens that it's passing over another section that's been requested, it could pull that in on the way. 20180410 03:37:29<+discordbot> @Vultraz If your code is hanging, the obvious first step is investigating in the debugger. 20180410 03:37:53< celticminstrel> If it's hanging it's probably either on the lock_guard or on the join(). 20180410 03:37:58< celticminstrel> Or both even. 20180410 03:38:37<+discordbot> one debug build on the oven 20180410 03:38:45< celticminstrel> Heh. 20180410 03:39:12<+discordbot> Ah yes, that good old pungent smell of -O0 builds. 20180410 03:39:38<+discordbot> celmin it's a bit more complex than that but basically correct. consider it takes time to step to a new track and an optimization may be possible, or not possible. In the pic, it's out 2 in 1 out 2 but it may be faster to do out 1 out 1 out 1 (the no NCQ photo) 20180410 03:42:30<+discordbot> @jyrkive relatedly, I cleaned up the code you said was superfluous (the height vector) and ugly (the multimap) 20180410 03:42:48<+discordbot> Yeah, I saw that. Thanks. 😃 20180410 03:55:25<+discordbot> oh, nice, there's already a function to just load the image from disk and bypass the surface cache 20180410 03:59:41<+discordbot> Unhandled exception at 0x0F32CAB6 (ucrtbased.dll) in wesnoth.exe: An invalid parameter was passed to a function that considers invalid parameters fatal. 20180410 03:59:43<+discordbot> wha?? 20180410 03:59:53< celticminstrel> Fun! 20180410 04:00:13<+discordbot> (well, that appeared after I continued after an exception) 20180410 04:05:14<+discordbot> well, i switched to load_from_disk and the exception goes away... 20180410 04:05:21<+discordbot> but it still basically gets stuck.. 20180410 04:05:32<+discordbot> Where does it get stuck? 20180410 04:05:37<+discordbot> logging on a release build shows it' waiting for a thread to finish 20180410 04:06:11<+discordbot> So, that suggests that the thread is also stuck. 20180410 04:06:22< celticminstrel> Which would mean it's waiting for a lock to be released. 20180410 04:06:36< celticminstrel> Or else it's still working, but that's less likely I guess. 20180410 04:06:46<+discordbot> With a debugger, you could switch to the worker thread and check what it's doing. 20180410 04:08:34<+discordbot> wait, this is odd..... 20180410 04:08:49<+discordbot> this is the logging I added: cpp // Wait for all loader theads to finish. for(auto& thread : loader_threads) { std::cerr << "checking thread" << std::endl; thread.join(); } std::cerr << "all loader threads done" << std::endl; 20180410 04:08:59<+discordbot> but the latter message gets displayed multiple times 20180410 04:09:26<+discordbot> oh, wait, I see 20180410 04:09:34<+discordbot> I forgot to print when it got to a new directory... 20180410 04:09:57<+discordbot> back to debug build to investigate the thread... 20180410 04:11:42<+discordbot> @jyrkive where can I switch to the worker thread? 20180410 04:13:09<+discordbot> IIRC, there is a "Threads" window at the bottom of the window by default. 20180410 04:13:15<+discordbot> ah, i found a Threads tab.. 20180410 04:13:17<+discordbot> was hidden 20180410 04:13:32<+discordbot> From there, you can just double-click the thread you want. 20180410 04:13:42<+discordbot> but there are no threads listed 😐 20180410 04:14:10<+discordbot> You need to first "break" in the debugger (pause the execution). 20180410 04:14:34<+discordbot> ah 20180410 04:14:38<+discordbot> ok, many threads now 20180410 04:14:53< celticminstrel> Yeah I think the threads tab is hidden by default. 20180410 04:15:18< celticminstrel> And there's no good way to determine which one is the culprit AFAIK so you may just have to check each one in turn to figure out the problem. 20180410 04:15:46<+discordbot> there's an arrow pointing to one.. 20180410 04:15:55<+discordbot> Shouldn't be that hard, the culprit thread is likely waiting for a lock or something. 20180410 04:16:07<+discordbot> The arrow just means the currently selected thread, IIRC. 20180410 04:16:09< celticminstrel> The one with an arrow is probably the thread you broke on. 20180410 04:16:14< celticminstrel> Which could be quite arbitrary. 20180410 04:16:23<+discordbot> https://cdn.discordapp.com/attachments/259976436490829825/433118022375309323/unknown.png 20180410 04:16:25< celticminstrel> Assuming you used the pause button rather than a breakpoint. 20180410 04:16:51< celticminstrel> When you press the pause button you'll be in whatever thread coincidentally happened to be active at that moment. 20180410 04:17:03< celticminstrel> ...mind you, I guess it's possible that that thread will be the culprit... 20180410 04:17:31<+discordbot> Memory allocation in image::locator::init_index()? That's strange. 20180410 04:18:03<+discordbot> If you broke on at the time when the game was already stuck, every operation that only takes finite time should have already completed. 20180410 04:18:11<+discordbot> Including memory allocations. 20180410 04:20:43<+discordbot> looks like the image locator class accesses a global map 20180410 04:21:06<+discordbot> so it is not thread safe 20180410 04:21:16<+discordbot> Indeed, looks like it. 20180410 04:23:26-!- celticminstrel [~celmin@unaffiliated/celticminstrel] has quit [Quit: And lo! The computer falls into a deep sleep, to awake again some other day!] 20180410 04:23:47<+discordbot> @jyrkive commented out init_index's internals, it works now 20180410 04:24:05<+discordbot> @jyrkive total terrain sheet construction time reduced by half. 20180410 04:24:11<+discordbot> Spritesheet generation of 'terrain/' took: 1869ms 20180410 04:24:17<+discordbot> before it was 36somethingsomething 20180410 04:24:50<+discordbot> All right, it confirms my hypothesis. Good. 😃 20180410 04:26:03<+discordbot> though, I'm not sure what contributed more to the increase: skipping the cache, or using the threads 20180410 04:26:29<+discordbot> Most likely the threads. Disk I/O is slow. 20180410 04:29:21<+discordbot> celticminstrel: https://github.com/wesnoth/wesnoth/issues/1736#issuecomment-379970210 20180410 04:29:45<+discordbot> I think I'll next go check why the bug doesn't occur on Windows. 20180410 04:37:05<+discordbot> I should probably make the locator thread safe 20180410 04:37:28<+discordbot> it actually looks rather useful since it automatically splits IPFs from image paths 20180410 04:37:35<+discordbot> but how does one do that... 20180410 04:37:59<+discordbot> What is the global map used for? 20180410 04:38:10<+discordbot> In general, global state is a no-no in thread-safe code. 20180410 04:38:49<+discordbot> it's only used in init_index 20180410 04:38:52<+discordbot> cpp auto i = locator_finder.find(val_); if(i == locator_finder.end()) { index_ = last_index_++; locator_finder.emplace(val_, index_); } else { index_ = i->second; } 20180410 04:39:18<+discordbot> the index is used to fetch elements from the cache 20180410 04:39:25<+discordbot> cpp template bool locator::in_cache(cache_type& cache) const { return index_ < 0 ? false : cache.get_element(index_).loaded; } 20180410 04:39:50<+discordbot> So, a cache of image locators. 20180410 04:40:08<+discordbot> The answer would be decoupling image locators from the image cache manager. 20180410 04:40:22<+discordbot> Caching is the job of the cache manager, not image locators. 20180410 04:40:53<+discordbot> right now the locator is wholly responsible for adding and locating elements in the caches 20180410 04:41:01<+discordbot> >_> 20180410 04:41:27<+discordbot> The whole image cache manager is a pretty bad idea together with hardware rendering. 20180410 04:46:49<+discordbot> sadly, i based my current texture cache on it 😛 20180410 04:47:03<+discordbot> oh well, that was only temporary anyway 20180410 04:51:09<+discordbot> honestly, we can probably just throw out the cache mechanism altogether... 20180410 04:51:15<+discordbot> we really don't need any of these anymore 20180410 04:51:37<+discordbot> cpp { images_.flush(); hexed_images_.flush(); tod_colored_images_.flush(); scaled_to_zoom_.flush(); scaled_to_hex_images_.flush(); brightened_images_.flush(); lit_images_.flush(); lit_scaled_images_.flush(); in_hex_info_.flush(); is_empty_hex_.flush(); mini_terrain_cache.clear(); mini_fogged_terrain_cache.clear(); 20180410 04:51:37<+discordbot> mini_highlighted_terrain_cache.clear(); reversed_images_.clear(); image_existence_map.clear(); precached_dirs.clear(); } 20180410 04:52:01<+discordbot> surfaces, we don't need, hexed, color, scaled, all render time ops... same for brightened, lit... 20180410 04:52:04<+discordbot> minis not needed 20180410 04:52:12<+discordbot> reversed is a coordinate swap 20180410 04:52:29<+discordbot> image existence is a separate mechanism 20180410 05:03:24-!- gallaecio [~quassel@57.99.79.188.dynamic.jazztel.es] has joined #wesnoth-dev 20180410 05:04:51-!- mattsc [~mattsc@wesnoth/developer/mattsc] has quit [Quit: So long and thanks for all the fish.] 20180410 05:06:45<+discordbot> (confirmed the sheets are correct even with threaded loading) 20180410 05:07:31<+discordbot> once I get this image cache stuff sorted, next thing will be to cut the number of sheets generated by about half. 20180410 05:07:58<+discordbot> one sheet per directory is too much! 20180410 05:08:13<+discordbot> especially since sheet 47 is literally 1 image 😂 20180410 05:11:04<+discordbot> all castle images should be in one sheet, for example 20180410 05:11:23-!- zookeeper [~lmsnie@wesnoth/developer/zookeeper] has joined #wesnoth-dev 20180410 05:19:29-!- gallaecio [~quassel@57.99.79.188.dynamic.jazztel.es] has quit [Remote host closed the connection] 20180410 06:00:56< irker617> wesnoth: Charles Dang wesnoth:master 325691107ab5 / src/spritesheet_generator.cpp: Spritesheet Generator: implemented multi-thread image loading https://github.com/wesnoth/wesnoth/commit/325691107ab5f1a2a3221955d6e1397d82d018d6 20180410 06:01:52<+discordbot> I decided to go with a temporary locator object created outside the thread. 20180410 06:02:00<+discordbot> that can be removed once we deal with the issues in image 20180410 06:09:25-!- gallaecio [~quassel@38.red-83-46-126.dynamicip.rima-tde.net] has joined #wesnoth-dev 20180410 06:09:56-!- timotei_ [~timotei@wesnoth/developer/timotei] has joined #wesnoth-dev 20180410 06:21:22-!- zookeeper [~lmsnie@wesnoth/developer/zookeeper] has quit [Ping timeout: 264 seconds] 20180410 08:26:51-!- Ivanovic [~ivanovic@wesnoth/developer/ivanovic] has quit [Quit: Disconnecting from stoned server.] 20180410 08:27:06-!- Ivanovic [~ivanovic@p4FC53504.dip0.t-ipconnect.de] has joined #wesnoth-dev 20180410 08:46:21-!- octalot [~steve@213-225-13-31.nat.highway.a1.net] has joined #wesnoth-dev 20180410 08:50:36-!- grzywacz [~karol@89-70-226-147.dynamic.chello.pl] has joined #wesnoth-dev 20180410 09:01:35-!- irker617 [~irker@uruz.ai0867.net] has quit [Quit: transmission timeout] 20180410 09:36:26-!- irker842 [~irker@uruz.ai0867.net] has joined #wesnoth-dev 20180410 09:36:26< irker842> wesnoth/wesnoth:master Charles Dang f9e44ea282 Spritesheet Generator: simplified interm AppVeyor: All builds passed 20180410 09:51:27-!- vn971 [~vasya@94.158.103.15] has quit [Ping timeout: 240 seconds] 20180410 09:54:16-!- vn971 [~vasya@94.158.103.15] has joined #wesnoth-dev 20180410 10:02:54-!- stikonas [~gentoo@wesnoth/translator/stikonas] has joined #wesnoth-dev 20180410 10:21:20< irker842> wesnoth: Charles Dang wesnoth:master c446e679f0cb / src/image_modifications.cpp: IPFs: simplify ~TC() implementation https://github.com/wesnoth/wesnoth/commit/c446e679f0cb205d47c7a55ceb9f57817321070c 20180410 10:21:23< irker842> wesnoth: Charles Dang wesnoth:master 15fdabbac9a7 / src/ (display.cpp image.cpp image.hpp tests/test_image_modifications.cpp wesnoth.cpp): Removed now-unused storage of team colors in the image namespace https://github.com/wesnoth/wesnoth/commit/15fdabbac9a79de06de87128cdaa93c3edda8e11 20180410 10:29:22-!- stikonas [~gentoo@wesnoth/translator/stikonas] has quit [Remote host closed the connection] 20180410 10:54:00-!- stikonas [~gentoo@wesnoth/translator/stikonas] has joined #wesnoth-dev 20180410 10:58:05-!- stikonas [~gentoo@wesnoth/translator/stikonas] has quit [Remote host closed the connection] 20180410 10:59:21-!- aeth [~Michael@wesnoth/umc-dev/developer/aethaeryn] has quit [Read error: Connection reset by peer] 20180410 11:00:19-!- aeth [~Michael@wesnoth/umc-dev/developer/aethaeryn] has joined #wesnoth-dev 20180410 11:10:26< irker842> wesnoth/wesnoth:master Charles Dang 15fdabbac9 Removed now-unused storage of team color AppVeyor: vs2015/Release Failed 20180410 11:10:27< irker842> Details: https://ci.appveyor.com/project/wesnoth/wesnoth-7lnpw/build/Wesnoth-VS2015-master-2559 20180410 12:07:08< irker842> wesnoth/wesnoth:master Charles Dang 325691107a Spritesheet Generator: implemented multi AppVeyor: All builds passed 20180410 12:50:52<+discordbot> "All castle images should be in one sheet." .. Why? If you're using sheets as I expect, that's horribly inefficient. 20180410 12:58:46<+discordbot> @Vultraz You will get vastly better efficiency if you group sprites which are most-commonly used together. Unit animations, for instance, are an obvious grouping. For maps, it might be best to do a statistical analysis of Mainline to guide grouping. 20180410 12:59:25<+discordbot> I believe the best way to deal with it is runtime analysis. 20180410 13:00:02<+discordbot> I have been thinking about it, and I realized something important: having a spritesheet on disk doesn't mean we have to load all of it to memory. 20180410 13:00:35<+discordbot> We can load the spritesheet file from disk, take out the sprites we believe we need, and discard the rest. 20180410 13:04:03<+discordbot> Well you still want grouping by locality of reference. If you're going to need Elven Fort on snow, you're probably going to want all the corners and sides and probably not going to be interested in Orcish Fort on Swamp. 20180410 13:04:39<+discordbot> Yeah, that kind of grouping would allow us to get away with loading less spritesheets from disk on scenario start. 20180410 13:04:47<+discordbot> I haven't been following the whole discussion thread, but is image load time currently impacting performance or is this a solution in search of a problem? 20180410 13:05:36<+discordbot> Vultraz measured that loading all terrain images from all directories took about 4 seconds. 20180410 13:06:04<+discordbot> (It was with individual small images like we have now, not spritesheets.) 20180410 13:06:11<+discordbot> Which is an invalid test, and you know it. 20180410 13:06:59<+discordbot> I mean, we get performance complaints pretty frequently, I just didn't think image load time was one of them 20180410 13:07:12<+discordbot> The only time we need all the terrain images is in the editor, and those can be lazy-loaded 20180410 13:07:19<+discordbot> Vultraz has been pushing hard for build-time spritesheets, and I want to minimize their downsides. 20180410 13:07:50<+discordbot> If we use build-time spritesheets, then I want to implement "discard unused images when loading a spritesheet" to keep memory usage reasonable. 20180410 13:08:18<+discordbot> (Without them, memory usage won't be a problem because we'll only load the images we need to begin with.) 20180410 13:09:02<+discordbot> WHY are sprite sheets even being considered. "Because Frogato uses them." is not a good reason. Are they required for hardward acceration? 20180410 13:10:01<+discordbot> Spritesheets are needed to keep the number of render passes reasonably low. The current implementation in master, with one render pass per sprite, is horribly inefficient. 20180410 13:10:51<+discordbot> The worst outcome would be if boosting editor load time introduces a sluggishness to the game that was not previously there. 20180410 13:11:01<+discordbot> Sounds like the rendering pipeline is the issue, not image load time. You're working the wrong problem. 20180410 13:12:59<+discordbot> Well, my plan was to implement only runtime spritesheet generation (which would improve mostly the rendering pipeline, and have a smaller [but positive] impact in image load time). 20180410 13:13:36<+discordbot> Vultraz seems to be implementing build-time spritesheet generation alone. 20180410 13:15:52<+discordbot> I won't argue that a Unit Animation sprite sheet should improve performance everywhere. And there may be some load-time improvements if you do a castle-style-on-terrain-style sprite sheet. But doing it for everything seems a bit much. 20180410 13:17:12<+discordbot> Even doing it for everything may well improve load times. Sequential reading from disk is fast, loading dozens of tiny files is slow. 20180410 13:17:29<+discordbot> (Even if we end up discarding 90% of the content in each sprite sheet.) 20180410 13:18:29<+discordbot> Which goes back to my static anaylsis of Mainline. Otherwise your worst-case is probably worse than the present system because you're not only loading everything, but you're waiting for a lot of stuff you're going to discard. 20180410 13:20:02<+discordbot> What's the probability you're going to need a snow-capped mountain with green grass and swamp? 20180410 13:21:38<+discordbot> The idea that runtime spritesheet generation would speed up rendering is very strange to me. Sorry if this is a dumb question. But, if they are all loaded in RAM then having those images in contiguous memory blocks shouldn't matter, am I right? 20180410 13:22:19<+discordbot> Ultimately it goes down to GPUs being parallel hardware. 20180410 13:22:42<+discordbot> And that is what should be driving the task. 20180410 13:22:52<+discordbot> A GPU can run parallel tasks very quickly. For example, rendering a couple thousand triangles. 20180410 13:23:44<+discordbot> Constantly switching between textures forces the GPU to operate serially. It needs to load texture 1, draw two triangles with it, load texture 2, draw two triangles, etc. 20180410 13:24:03<+discordbot> In that kind of workload, it's actually less efficient than the CPU. 20180410 13:25:05<+discordbot> I see. Thanks for that explanation. 20180410 13:27:39<+discordbot> Knowing that, I would think that the GPU might be smart enough to do something like an MRU cache on its own rather than having to handcode it 20180410 13:29:48<+discordbot> They're generally optimized for 3D games with a significantly higher number of triangles per texture. 20180410 13:30:05<+discordbot> It still comes down to locality of reference and you're still going to need an anaysis. And still the on-disk work is likely to lose efficiency unless it, too, has some analysis. 20180410 13:33:54<+discordbot> @Tad Carlucci invalid test? 20180410 13:34:26<+discordbot> I think his point was "the game isn't going to load every single terrain image in practice". 20180410 13:34:58<+discordbot> fair enough 20180410 13:35:03<+discordbot> especially not in this fashion. 20180410 13:38:03-!- Oebele [~quassel@143.177.58.202] has joined #wesnoth-dev 20180410 13:41:07<+discordbot> this reminds me, my rendered text cache uses one texture per rendered text state... 20180410 13:41:38<+discordbot> oh well, we can tackle text last. 20180410 13:42:36<+discordbot> I was planning to initially implement GUI2 rendering with some hacks so that we can get ingame and test rendering there. We can indeed leave fast text rendering for later. 20180410 14:54:17-!- vladimirslavik [vslavik@nat/redhat/x-zisgknrjmbdswmei] has joined #wesnoth-dev 20180410 14:57:34<+discordbot> the drawn shapes caching you added, would that be removed? 20180410 15:08:57-!- irker842 [~irker@uruz.ai0867.net] has quit [Quit: transmission timeout] 20180410 15:42:07<+discordbot> Most likely I'll get rid of the whole concept of canvases. 20180410 15:52:17<+discordbot> What do you mean? 20180410 15:52:32<+discordbot> I thought you were just going to make it so they drew directly on the screen 20180410 15:52:43<+discordbot> Instead of individual textures 20180410 15:54:29<+discordbot> For rendering directly to screen, the "canvas" abstraction in GUI2 is harmful, not helpful. 20180410 15:55:32<+discordbot> I see. 20180410 15:55:46<+discordbot> But what would replace it 20180410 15:55:55<+discordbot> Design-wise. 20180410 15:56:23<+discordbot> I'll need to look closer how canvases are used in practice. 20180410 15:57:42<+discordbot> They’re used as visual state definitions. Each widget keep one per state (focused, disabled, etc) and the active state’s canvas is what is displayed 20180410 15:58:37<+discordbot> That’s really it 20180410 15:59:09<+discordbot> How many widgets even use multiple canvases? 20180410 15:59:23<+discordbot> Buttons obviously, but how many other widgets there are? 20180410 16:01:03<+discordbot> I couldn’t say. Quite a few, probably 20180410 16:03:54-!- vladimirslavik [vslavik@nat/redhat/x-zisgknrjmbdswmei] has quit [Quit: Leaving] 20180410 16:08:47<+discordbot> I wouldn’t mind switching to a more functional drawing system instead of a definition- based one 20180410 16:09:22-!- irker868 [~irker@uruz.ai0867.net] has joined #wesnoth-dev 20180410 16:09:22< irker868> wesnoth: Jyrki Vesterinen wesnoth:master c42401a8deb9 / src/events.cpp: Fix #1736: on GNU/Linux, a hotkey can trigger multiple commands https://github.com/wesnoth/wesnoth/commit/c42401a8deb92acc16039fbeed0acf16287e286c 20180410 16:09:22< irker868> wesnoth: Jyrki Vesterinen wesnoth:master c23fc2b66645 / changelog.md players_changelog.md: Changelog entry for commit c42401a8deb92acc16039fbeed0acf16287e286c https://github.com/wesnoth/wesnoth/commit/c23fc2b66645fe82d290de09a36f6e625747ed69 20180410 16:09:47< irker868> wesnoth: Jyrki Vesterinen wesnoth:1.14 f80bc4262194 / src/events.cpp: Fix #1736: on GNU/Linux, a hotkey can trigger multiple commands https://github.com/wesnoth/wesnoth/commit/f80bc4262194c161c95aa1ffb83ee7f73df4f73d 20180410 16:09:49< irker868> wesnoth: Jyrki Vesterinen wesnoth:1.14 cd4bb21c81d0 / changelog.md players_changelog.md: Changelog entry for commit f80bc4262194c161c95aa1ffb83ee7f73df4f73d https://github.com/wesnoth/wesnoth/commit/cd4bb21c81d013c95df6e3ace8f8c5143e78f716 20180410 16:10:26< irker868> wesnoth/wesnoth:master Charles Dang 15fdabbac9 Removed now-unused storage of team color AppVeyor: 1/4 builds failed 20180410 16:10:27< irker868> Details vs2015/Release: https://ci.appveyor.com/project/wesnoth/wesnoth-7lnpw/build/Wesnoth-VS2015-master-2559 20180410 16:10:37-!- gallaecio [~quassel@38.red-83-46-126.dynamicip.rima-tde.net] has quit [Remote host closed the connection] 20180410 16:28:23-!- gallaecio [~quassel@57.99.79.188.dynamic.jazztel.es] has joined #wesnoth-dev 20180410 16:41:50-!- stikonas [~gentoo@wesnoth/translator/stikonas] has joined #wesnoth-dev 20180410 17:07:32-!- stikonas [~gentoo@wesnoth/translator/stikonas] has quit [Remote host closed the connection] 20180410 17:09:41< irker868> wesnoth/wesnoth:master Jyrki Vesterinen c23fc2b666 Changelog entry for commit c42401a8deb92 AppVeyor: vs2015/Release Failed 20180410 17:09:42< irker868> Details: https://ci.appveyor.com/project/wesnoth/wesnoth-7lnpw/build/Wesnoth-VS2015-master-2560 20180410 17:16:15-!- Ivanovic [~ivanovic@p4FC53504.dip0.t-ipconnect.de] has quit [Changing host] 20180410 17:16:15-!- Ivanovic [~ivanovic@wesnoth/developer/ivanovic] has joined #wesnoth-dev 20180410 17:38:30-!- Oebele [~quassel@143.177.58.202] has quit [Remote host closed the connection] 20180410 17:47:48-!- janebot [~Gambot@unaffiliated/gambit/bot/gambot] has joined #wesnoth-dev 20180410 18:18:53-!- janebot [~Gambot@unaffiliated/gambit/bot/gambot] has quit [Remote host closed the connection] 20180410 18:18:59-!- janebot [~Gambot@unaffiliated/gambit/bot/gambot] has joined #wesnoth-dev 20180410 18:27:06< vn971> I see a Help entry "Time Of Day Schedule". What should it mean? Screenshot: https://pointsgame.net/vn971/temp/2018.04.10_21:26:16_bdfd45b.png 20180410 18:27:52<+discordbot> It's the time of day schedule. 20180410 18:28:10<+discordbot> As in the time of day sequence for each turn. 20180410 18:29:00< vn971> Is it some kind of regression. Well @shadowm, I of course do know what ToD is. But Why is it important enough to take a whole main Help entry? Also, what do the numbers on the right mean? 20180410 18:29:17<+discordbot> How is its existence a regression? 20180410 18:29:52<+discordbot> They're not labeled for some reason but it's obvious to a veteran player (not to a new player though) that it's the lawful bonus value. 20180410 18:30:50< vn971> shadowm: there was meant to be a question mark, I made a typo. But generally, I do not understand why this menu entry was put there, and numbers on the right go without any kind of description, so for me this really is a kind of regression. Everything that makes UI less easy to use is a regression for me.. 20180410 18:31:33<+discordbot> I know it was meant to be a question mark. 20180410 18:33:16< vn971> what would be the proper way to put the current solution in doubt and propose to change anything about it? The problem is though that I do not see any other solution besides removing the entry.. 20180410 18:34:43<+discordbot> File a bug report explaining your concerns. 20180410 18:35:12<+discordbot> But bear in mind that the addition of unintuitive help entries does not qualify as a regression when they didn't exist before. 20180410 18:39:02< grzywacz> I wonder if veteran players need this help entry. :) 20180410 18:39:42<+discordbot> Depends on the scenario. 20180410 18:48:44< vn971> Help is not generally used to show scenario/map-specific info though, at least now. A better place might be the ToD icon/text on the right of main screen. 20180410 18:51:39<+discordbot> If you mouse over you'll see that's already done. 20180410 18:51:50<+discordbot> Also, what you said is kind of not completely true. 20180410 18:52:37<+discordbot> In a way it's possible to consider several help sections as campaign-specific, or even scenario-specific if the campaign is a single scenario or isn't actually a campaign (e.g. an MP scenario). 20180410 19:46:59-!- Sirp_ [d040cb0b@gateway/web/freenode/ip.208.64.203.11] has joined #wesnoth-dev 20180410 20:04:06-!- boucman [~rosen@wesnoth/developer/boucman] has joined #wesnoth-dev 20180410 20:10:02-!- irker868 [~irker@uruz.ai0867.net] has quit [Quit: transmission timeout] 20180410 20:26:17-!- octalot [~steve@213-225-13-31.nat.highway.a1.net] has quit [Ping timeout: 260 seconds] 20180410 20:41:00< Ravana_> after some time of keeping wesnoth idle, it acquired scrollbar https://i.imgur.com/RSvgK26.png, rejoining lobby fixed it 20180410 20:49:36< Soliton> probably due to a game with a long title. 20180410 20:54:11<+discordbot> Hey folks. I have a very basic question because I haven't done this in ages and because I am too tired for my brain to work. I have a fix for the recall/recruit bug for 1.14 and master, but because this is C++, I want to make it a PR rather than committing it directly. So, I create a branch, commit the changes to it, push the branch and then create a PR based against either 1.14 or master (and later cherry-pick to the other). My 20180410 20:54:11<+discordbot> question: since I am working directly of a wesnoth repo clone, not a fork, the commits will be reported here, but that's okay, right? 20180410 20:54:49<+discordbot> And I am asking because, for that reason, all of this is publicly visible and I have screwed it up before. 😛 20180410 20:57:08<+discordbot> Back in the day I'd have strongly preferred for you to push to a branch in a fork instead. 20180410 20:57:22<+discordbot> I believe (but don't quote me on that) these days nobody cares. 20180410 20:58:12<+discordbot> Well, I am always thinking that I should figure out how to switch to a fork, but there never seems to be time to figure out how to do that. 20180410 20:58:26<+discordbot> And if I want to do that now, this is not going to be in 1.13.14. 20180410 20:58:29<+discordbot> You just use the Fork option on GitHub and create a new remote for it in your clone. 20180410 20:58:37<+discordbot> The way it is, I am already doing this while sitting in meetings ... 20180410 20:58:48<+discordbot> Then push to that remote instead of "origin" or "upstream" or whatever your wesnoth/wesnoth remote is named. 20180410 20:59:04<+discordbot> I would suggest use a branch off a personal fork if you want to maintain control of the changes. If you want others to be able to update your PR without your approval, use a branch on main wesnoth repo 20180410 20:59:31<+discordbot> I'd be very happy if others made changes ... 20180410 20:59:41<+discordbot> The odds that will happen are near nil around here. 20180410 20:59:49<+discordbot> Right ... 20180410 21:00:06<+discordbot> That's why I am doing this myself in the first place, even though it really is outside my comfort zone. 20180410 21:00:09<+discordbot> yep. it's more likely a newbie will need it then someone who's been around 20180410 21:00:10<+discordbot> Especially for small temporary branches. 20180410 21:06:41<+discordbot> Well, I'll see if my next 10-min break will be long enough to do the fork thingy. 20180410 21:08:22<+discordbot> If you're using the command-line client I can easily explain, but otherwise it's up to your IDE or front-end or whatever it is you're using. 20180410 21:11:33<+discordbot> I'm set up to use either. I do some things on the CL, others with the github desktop app, or whatever it's called. 20180410 21:15:57<+discordbot> # Adds the URI for your fork as a new remote git remote add myfork git@github.com:shikadiqueen/wesnoth.git # Pushes my-topic-branch-name to the fork and sets the latter as the branch's default upstream git push -u myfork my-topic-branch-name 20180410 21:17:18<+discordbot> Okay, thanks! Much appreciated. 20180410 21:17:56<+discordbot> I'll try that later, right now I am off to the next ... whatever's next. 20180410 21:32:28-!- boucman [~rosen@wesnoth/developer/boucman] has quit [Remote host closed the connection] 20180410 21:59:39-!- grzywacz [~karol@89-70-226-147.dynamic.chello.pl] has quit [Ping timeout: 246 seconds] 20180410 22:09:48-!- irker643 [~irker@uruz.ai0867.net] has joined #wesnoth-dev 20180410 22:09:48< irker643> wesnoth/wesnoth:master Jyrki Vesterinen c23fc2b666 Changelog entry for commit c42401a8deb92 AppVeyor: 1/4 builds failed 20180410 22:09:48< irker643> Details vs2015/Release: https://ci.appveyor.com/project/wesnoth/wesnoth-7lnpw/build/Wesnoth-VS2015-master-2560 20180410 22:14:55-!- stikonas [~gentoo@wesnoth/translator/stikonas] has joined #wesnoth-dev 20180410 22:47:20<+discordbot> Gallaecio has really been finding a lot of translation issues o__o 20180410 22:47:42<+discordbot> @mattsc branches in the main repo are perfectly acceptable. 20180410 22:47:58< gallaecio> It was bound to happen :) 20180410 22:48:28< gallaecio> Not as many as I though, though. Wesnoth is the best game internationalization I know. 20180410 22:48:36<+discordbot> it's a good thing you're finding these 20180410 22:49:01<+discordbot> are map sizes also not translatable? 20180410 22:50:21< gallaecio> Vultraz: They are translatable as far as I know. 20180410 22:50:38<+discordbot> interesting 20180410 22:50:39< gallaecio> (n×n works for Galician) 20180410 22:51:08<+discordbot> quite interesting... 20180410 22:52:15<+discordbot> from looking at the code it seems it should not be so 20180410 22:52:18<+discordbot> ¯_(ツ)_/¯ 20180410 22:52:34<+discordbot> @shadowm do I just need to add a dsgettext call here? https://github.com/wesnoth/wesnoth/blob/master/src/gui/dialogs/multiplayer/mp_create_game.cpp#L737 20180410 22:53:36<+discordbot> gallaecio: does "Random map teams are untranslatable" only happen with random maps? 20180410 22:53:44< gallaecio> Damn, two duplicated issues in a row. I really need to search first. 20180410 22:53:54<+discordbot> or does it also happen when you have any scenario with Use Map Settings? 20180410 22:53:55<+discordbot> er 20180410 22:54:00<+discordbot> when you do NOT use UMS 20180410 22:54:03< gallaecio> Vultraz: I checked some scenarios and the campaign, and both were translated. 20180410 22:54:28< gallaecio> I’ll check 20180410 22:54:36<+discordbot> Use Map Settings means the proper team names are used, else it falls back to the default "Team n" 20180410 22:54:53<+discordbot> I tried my damndest to make sure they were translated, but I might have failed miserably... 20180410 22:55:55<+discordbot> @Vultraz Use VGETTEXT for that. 20180410 22:55:56< gallaecio> Vultraz: On scenarios it works on both cases. 20180410 22:56:09< gallaecio> It seems to be just with random maps. 20180410 22:56:24<+discordbot> You can't just assume that "N to M" is always translated as "N M" in all languages". 20180410 22:56:40<+discordbot> the "to" is not always included 20180410 22:56:54<+discordbot> Then you need two different strings. 20180410 22:57:14<+discordbot> it only says "to" if min != max. 20180410 22:57:17<+discordbot> (I really needn't be more specific. The logic change required here is trivial.) 20180410 22:57:17<+discordbot> else it's just a number 20180410 22:57:38<+discordbot> Stop thinking about the code, think about the logic instead. 20180410 22:57:59<+discordbot> Position yourself at line 730, ignore the rest, rethink the algorithm to follow. 20180410 22:59:40<+discordbot> Also make sure to put out a PR or issue to backport your patch after 1.14.0. 20180410 23:05:30<+discordbot> AGH. The random maps team name issue touches code I didn't want to deal with again... 20180410 23:05:46<+discordbot> I probably fucked it up when I changed it... 20180410 23:07:06<+discordbot> it involves translatable strings over the network in serialized form... 20180410 23:10:22< gallaecio> Updated translations sent to Nick in time for 1.14.0, all detected issues reported… I feel realized :) Time to sleep, good night! 20180410 23:11:03-!- gallaecio [~quassel@57.99.79.188.dynamic.jazztel.es] has quit [Remote host closed the connection] 20180410 23:15:25< irker643> wesnoth: Charles Dang wesnoth:master a4dd74c32afb / src/gui/dialogs/multiplayer/mp_create_game.cpp: MP Create Game: fixed campaign player numbers label being untranslatable https://github.com/wesnoth/wesnoth/commit/a4dd74c32afb2f6c37453eafb60f60b8b215df01 20180410 23:19:23<+discordbot> @shadowm should I also use VGETTEXT here? https://github.com/wesnoth/wesnoth/blob/master/src/game_initialization/connect_engine.cpp#L138-L140 20180410 23:19:31<+discordbot> if so, maybe the fix is simpler than I thought 20180410 23:19:55<+discordbot> but then again, there's that comment... 20180410 23:20:20<+discordbot> yeah, maybe that's not the fix... 20180410 23:20:35<+discordbot> maybe it need it at 143 20180410 23:20:54<+discordbot> or 118! 20180410 23:21:08<+discordbot> OR 163! 20180410 23:21:10<+discordbot> *flails! 20180410 23:22:30<+discordbot> Looks like this is for team_name, not user_team_name. 20180410 23:22:44<+discordbot> but it's then assigned to utn 20180410 23:22:51<+discordbot> See line 143. 20180410 23:23:02<+discordbot> It's not. 20180410 23:23:16<+discordbot> See line 103 for where the expression in 143 comes from. 20180410 23:23:18<+discordbot> oh right... 20180410 23:23:29<+discordbot> ...but that's translated! 20180410 23:23:44<+discordbot> (The way that string is composed is bad too btw. ) 20180410 23:25:35<+discordbot> ugh 20180410 23:25:43<+discordbot> ok, so I guess I should use VGETTEXT at 143? 20180410 23:28:48<+discordbot> I'll od toag 20180410 23:37:01<+discordbot> @Vultraz Yeah, but I've been meaning to set up a fork for a while anyway, might as well just do it. The fork's set up and it's 'origin' now. Default remote is still the main wesnoth repo, so I'll either change that or try to be careful. 20180410 23:37:23<+discordbot> The main problem this week is that I am traveling again and just don't have any continuous blocks of time to just get it all done. 20180410 23:43:44<+discordbot> travel a lot, you do 20180410 23:47:19< irker643> wesnoth: Charles Dang wesnoth:master 275057df59ae / src/gettext.hpp: Gettext: used [[maybe_unused]] for UNUSEDNOWARN on C++17 https://github.com/wesnoth/wesnoth/commit/275057df59ae52214761d73bc32bbb96a7595f10 20180410 23:47:21<+discordbot> if someone can test that, that'd be awesome ^ 20180410 23:47:22< irker643> wesnoth: Charles Dang wesnoth:master 1c8b50877750 / src/game_initialization/connect_engine.cpp: Connect Engine: attempt to fix fallback user team name not being translated https://github.com/wesnoth/wesnoth/commit/1c8b50877750876499e87bc3482011e9afbe5f00 20180410 23:52:38-!- celticminstrel [~celmin@unaffiliated/celticminstrel] has joined #wesnoth-dev --- Log closed Wed Apr 11 00:00:39 2018