Anonymous | Login | Signup for a new account | 2025-06-14 14:41 UTC | ![]() |
My View | View Issues | Change Log | Roadmap | Doomseeker Issue Support Ranking | Rules | My Account |
View Issue Details [ Jump to Notes ] | [ Issue History ] [ Print ] | ||||||||
ID | Project | Category | View Status | Date Submitted | Last Update | ||||
0001586 | Doomseeker | [All Projects] Suggestion | public | 2013-11-19 21:49 | 2018-09-29 14:46 | ||||
Reporter | Blzut3 | ||||||||
Assigned To | Zalewa | ||||||||
Priority | urgent | Severity | block | Reproducibility | have not tried | ||||
Status | closed | Resolution | fixed | ||||||
Platform | OS | OS Version | |||||||
Product Version | 0.11 Beta | ||||||||
Target Version | 0.12 Beta | Fixed in Version | 0.12 Beta | ||||||
Summary | 0001586: Plugin API changes | ||||||||
Description | It looks like a plugin API/ABI change is inevitable for some features so this ticket will be used to track issues that need to be resolved. One major issue that should probably be done for 0.12 is getting Server pointers wrapped into QSharedPointers to solve some stability issues. The server object could also use some redesign (PIMPL?) so that it can be extended easily in the future if need be. Doomseeker should probably also be more aware of testing binary support. Currently the priority file searching support uses the offline binary as a reference for the server list, but then looks at the actual client binary when joining. This may cause some minor issues. | ||||||||
Attached Files | |||||||||
![]() |
|
Blzut3 (administrator) 2013-11-19 22:06 |
GhostlyDeath wanted to note a few possible issues: Multicasts, IPv6 (which Zandronum could be supporting soon enough and I think chocolate doom does already), and asynchronous improvements (although I think Doomseeker doesn't have a problem with updated signals being fired at any time) particularly with the master server protocol. |
Zalewa (developer) 2013-11-20 06:40 |
IPv6 - I believe Qt handles all of this already. Perhaps there are instances where program expects IPv4 and won't accept anything else, but we'd have to find them first. Can he be more specific about what he means with "asynchronous improvements"? |
Blzut3 (administrator) 2013-11-20 18:18 |
There seems to be a little more setup required to do dual stack in Qt. I believe you need two active sockets (one for v4, one for v6) otherwise whatever gets sent first will determine the mode. The chocolate doom plugin had to work around this issue. Perhaps a later version of Qt made this more transparent, but that's what I know. As for the asynchronous thing, I don't remember how much we fixed throughout the various changes to the refreshing thread. But ensuring we can support partial master list updates comes to mind (in theory we can start querying servers as soon as the first master packet comes in). We also don't really have a mechanism in place for resending dropped packets in the master protocol. I believe our server query protocol code doesn't really provide means for packet splitting either (since it's not really needed). There is, of course an abstraction trade off if we try to make thing perfectly flexible, but there could be room to consider improvement there. |
Zalewa (developer) 2013-11-20 21:05 |
Quote from "Blzut3" Is that necessary? In my experience servers start appearing right after I press the "Get Servers" button. I've never seen any delays in this matter. Quote from "Blzut3" Yes, I guess this needs to be considered if we want to avoid plugin API changes in the future. |
Blzut3 (administrator) 2013-11-20 21:37 |
The master client change probably isn't necessary. He'll have to explain his needs though to get a clearer picture. He says he not really actively working on the ReMooD protocol, so don't expect much in the near future. It'll be awhile before 0.12 is ready for release so until then we can be open to further changes. |
Zalewa (developer) 2013-11-20 22:01 |
Funny thing: I've just read a chapter a moment ago in this book about the Bridge design pattern. One of the things this pattern allows is to have polymorphism without actual virtual functions. The book itself states that one of the purposes of this pattern is to maintain compatibility with dynamically loaded libraries. The implementation in our case would change this:
into this:
By using this pattern we ensure no future ABI problems. Of course, there are some drawbacks: Obviously, we would need to remember to check for NULL and to delete the handlers properly. There's also the issue of classes and methods explosion, which makes implementation of new functionalities very cumbersome and time consuming. And lastly, we would have to consider what happens when a method becomes obsolete (as in Doomseeker doesn't use it anymore, or it's expanded with additional parameter), but old plugins still use it. I guess some fallback needs to be implemented - when a new handler is NULL, check if the old one isn't and try to use it instead. It appears that's the same kind of problem that occurs when you need to maintain compatibility between new server and old clients in distributed software development. Still, I think it's a viable solution. |
Blzut3 (administrator) 2013-11-20 23:56 |
Well if you really want to go with that style of a solution I would suggest reducing the number of classes/objects there. Essentially what that pattern is doing is trying to move the vtable into the d-pointer, which is a leaf class and thus can be expanded. If you were to do this, the best C++ way to handle that would be to just use method function pointers in the d-pointer. This way the functions can still be a member of the GameRunner subclass (and use the state) and you remove one level of indirection (remember virtual functions are essentially function pointers) and don't have to delete. It's definitely a good thought, but is the trade off worth it? While I'd like to keep the ABI as stable as possible (good practice and is kind of nice come release to reuse unchanged plugins), it's not like there are that many external plug-ins out there. I'm only aware of one being developed, so it doesn't really kill us to break ABI on occasion. If you really want to give it a try I don't really have anything against it, if you use function pointers like I suggest I don't believe there's any overhead to the pattern (vtables are separate allocations, one per class IIRC, so the levels of indirection are the same). It's just a matter of if this is something we really want to maintain manually? |
Edward-san (reporter) 2013-11-21 01:34 |
speaking of c++ object oriented solutions, is this relevant? |
Zalewa (developer) 2013-11-21 17:18 |
This presentation has 300 slides and little explanation. What should I be looking at? |
Edward-san (reporter) 2013-11-21 18:42 edited on: 2013-11-21 18:54 |
Ah, sorry. It comes from this one. [edit]For better understanding, try these conferences which use the documents in the link above. |
Blzut3 (administrator) 2013-11-21 22:23 |
The method presented seems to be somewhat similar to the bridge pattern Zalewa mentioned. The difference being that objects are wrapped in a vtable object of sorts. Using templates this wrapping is automatic and polymorphic. I'm not certain, but I think using that method would require Doomseeker to actually be linked to the plugins at compile time since it needs to know about each object type in order to call the proper function. Server objects are also not a value type, at least not currently. I do not believe they can be made one either since there's a bit of state they need to have in order to allow the refreshing thread to be able to push packets through them. Also, even though the premise is to reduce heap allocations to improve performance, I'm seeing one extra level of indirection not unlike the non-function pointer bridge pattern as presented by Zalewa. Maybe watching the presentation will prove something wrong there, but that's what I'm seeing. |
Zalewa (developer) 2013-11-30 13:48 |
While we're at it, I'd like to discuss a matter that's been bugging me for some time now: Shouldn't we ditch the type-to-name alignment with tabs? Consider this example:'http://i.imgur.com/8IiZgBd.jpg [^]' Here you have a series of methods with short return type names. They are all nicely aligned until you need to add something long like the "virtual const GameCVar *modifier()". As there is not enough space, this goes out of alignment destroying the entire organized layout. To fix the layout you basically need to manually realign every other member of this class. This is very tedious and I basically never do it as it wastes too much time. Ditching the type-to-name separation won't destroy readability, and will actually prevent such mess and prevent text expanding horizontally which is something I always try to avoid. |
Zalewa (developer) 2013-11-30 15:29 |
Aside from my previous note, I've also done some initial work on the main issue. The first thing to go were the data members in Server class. I've d-pointered the class and changed all code that uses it so that the program compiles and works. No more data fields should be left in Server class now. Some further changes are necessary to minimize the risk of having to add new virtual methods in the future. I already see that team related virtual methods can be moved to a separate object (akin to GameRunner). The modifier() allows only one modifier so it also needs to be changed for better flexibility. Also, all virtuals that return a single value should be changed so they're not virtual anymore and return a data member instead. The offenders here are engineName() and hasRcon(). I'm not sure if they're really required here as I think the EnginePlugin* should return that data. We also have a scores() list. This is currently hardcoded to have max 4 values. I've already changed it from plain-old C array to a QList<int>, but most of the code still assumes the number 4. I don't think such limitation should be even considered by Doomseeker and it needs to be removed. I think that's it for the Server class. |
Blzut3 (administrator) 2013-11-30 17:09 |
Regarding the alignment, I'm fine with that. I've sort of ditched it myself in my more recent work. |
Blzut3 (administrator) 2013-12-13 03:58 edited on: 2013-12-13 03:59 |
Quote |
Zalewa (developer) 2013-12-26 16:36 |
I did some further modifications just now. Binaries class has been split into ExeFile objects. GameExeFactory showcases the Bridge design pattern. I was considering implementing it by using pointers to methods, but pointers are data objects, and adding data objects breaks the ABI. I still stick to virtual methods in some areas, although this may change in future commits. Currently these handlers aren't set anywhere, but they're there for future purposes. I guess now is the time to dive in to how games are launched so that it's more easy to extend it with additional parameters in the future. Hopefully this ticket will be resolved after a few more commits. Some additional TODOs were also added during this entire process and these should also be resolved before the work is concluded. |
Blzut3 (administrator) 2013-12-26 20:34 |
I'm not sure what you mean by the virtuals vs pointers thing. After the compiler is through with them, they are exactly the same thing. A class that wraps a single virtual function just introduces one extra level of indirection that is not necessary with function pointers (vtable is a pointer). So they're both data objects. The function pointer can be shoved into the d-pointer which should prevent ABI breakage from adding or removing pointers. |
Zalewa (developer) 2013-12-26 23:29 |
Oh, I was under impression that you meant pointers to methods, rather than pointers to functions. I also considered them, actually, but it's difficult to pass caller object identity to a separate function. Naturally, you can pass a pointer to "this" explicitly, but still, with handler classes it's a bit easier. You can set various data members, including the caller, in the inherited handler class, and then easily access that data in the overwritten method. As a drawback you need to remember that the handler objects need to be deleted somewhere, possibly together with the object they're assigned to, whereas functions can simply be ignored. I want to make the plugin interface as flexible as possible, so some "boilerplate" code needs to be added. |
Blzut3 (administrator) 2013-12-26 23:43 edited on: 2013-12-27 01:04 |
I did mean pointers to methods (I use function and method interchangeably since they're the same thing, one just has an implicit this argument). What is the problem with having setServerExeRetriever take a member pointer and then storing that ExeFile *(GameExeFactory::*)() in the d-pointer? From what I can tell the plugins wouldn't care how many of those pointers are there since the set functions are non-virtual (and likewise a non-virtual function can be made to call them if need be). Edit: In case my description is vague. Here's an example implementation:'http://pastebin.com/NX6SjW1b [^]' The macro would need to be different in Doomseeker's case, but this is just to give the general idea. |
Zalewa (developer) 2013-12-27 01:17 |
Could you provide a working proof of concept for that? I'm having trouble compiling when trying to assign a method from a plugin subclass to a method pointer in the base class. The method pointer syntax is very complicated. |
Blzut3 (administrator) 2013-12-27 01:28 edited on: 2013-12-27 01:29 |
Did you miss my edit or do you mean you want me to implement it in Doomseeker? The code in that pastebin compiles on GCC and Clang warning free and runs fine. I even show that the type checking prevents assigning a function from a non-derived class. |
Zalewa (developer) 2013-12-27 10:13 |
Yes, I missed your edit. Thanks for the example. It compiles properly in Microsoft compiler, and I guess it really is the best solution here. Some modifications are required, given that we start our method names from small letter and that contents of PrivData is hidden inside the .cpp file. I also figured out how to add doxydoc for these functions:'http://pastebin.com/k2DyyR2i [^]' |
Zalewa (developer) 2014-01-12 13:51 |
Blzut, can you please take a look at gamerunner.cpp line 195 and tell me if this is needed for anything? |
Blzut3 (administrator) 2014-01-12 18:36 |
Hmm... It was always like that since connection passwords were added. I have no idea why it works (does it?) though. 'https://bitbucket.org/Blzut3/doomseeker/src/90c8ac4992b2/src/server.cpp#cl-382 [^]' |
Zalewa (developer) 2014-01-12 19:10 |
I have no idea what this line is for. It doesn't do anything, IMO, only confuses source ports to try to load a PWAD under the same filename as the password. I'll just remove it. |
Zalewa (developer) 2014-02-02 18:52 |
This commit shows an example on how method pointers are declared, defined and used. If you think there should be any changes in naming conventions or overall usage then they should be made now while it's still easy to do so. |
Blzut3 (administrator) 2014-02-02 18:59 |
Looks fine to me. The only question I have is if there's a reason POLYMORPHIC_SETTER_DECLARE and POLYMORPHIC_METHOD_DECLARE are separate macros? |
Zalewa (developer) 2014-02-02 19:03 edited on: 2014-02-02 19:03 |
I figured you'd sometimes want to have a protected setter for a public method. In fact: I think you can also keep the METHOD private too if you want to. |
Zalewa (developer) 2014-02-03 23:31 |
I think we're nearing to a close of this ticket soon. I'll try to work on it as much as possible in upcoming days to get it finally done. It's been open for far too long. Still, I don't want to leave this issue in a state where we can't say that it's completely done, as this would leave potential risk for more problems and delays in the future. Following items are of main concern now: - Clean up GameHost the same way as GameClientRunner was cleaned up. - Make sure that all MAIN_EXPORT classes at least have a d-pointer defined so that adding data members to them in the future won't break their ABI. It's preferable to also move all existing data members to d-pointers and replace them with accessor methods. Now, the polymorphism thing: I've gone and converted a bunch of virtual and pure virtual methods to method pointers where defaults do something, do nothing, or are set to fail an assertion in debug builds when called, the last being a cheap substitute for pure virtual methods. The main idea here was to get a hold of this system and to provide examples for further expansion. I don't think it's absolutely necessary to replace every existing virtual method with this mechanism, but we have to remember to never add new virtual methods to existing classes, unless we want to break the ABI on purpose. The drawback is that we'll get a mixed system, but apart from the aesthetics I don't see any other issues with that. The advantage is that we gain time to do other things. I also think we can leave the "setArg..." methods and their duplication as it is. Moving these to ExeFile would actually increase complexity of plugins as they would have to overwrite these classes as well as the current owners that are already overwritten. Finally, as we're moving towards a stable plugin API, I also think we should be considering writing proper documentation for this API. It doesn't have to be anything overly extensive, as existing plugins already provide examples on how to use it, but some introduction page and a few words for each MAIN_EXPORT class should be considered. |
Blzut3 (administrator) 2014-02-04 01:38 |
Sounds good. One thing I noticed when fixing the Odamex plugin is there are probably a few things there that we could add support in the API for. Odamex actually passes the hash for the password to the browser so that the password can be checked before actually joining the server. Odamex also sends MD5 sums for all wads, although I have no idea what we could do in a user friendly way if the sums don't match. (Skulltag had a similar feature for skulltag_data that we never ended up using, but in that case the solution would have been to download the new version from a known location.) |
Zalewa (developer) 2014-02-04 06:44 |
Quote from Blzut3 Sounds like a good improvement, although I think this can be added after the branch merge. If we merge and then have to break all the plugins in order to expand one of them then it means that the branch was closed prematurely. |
Zalewa (developer) 2014-02-09 14:08 |
7 days of commits. Main class needs some further attention. All other MAIN_EXPORTs are now d-pointered which means that huge amount of necessary work is done. I want to modify Main so that it doesn't provide access to anything that isn't exported anyway. After that, I'll revise this thread to check if I didn't miss anything. After that, I think we can merge the branch into default and resume normal work. Meanwhile, question: What is the best way to handle a class that is supposed to be accessible like a singleton but also requires initialization with user-defined arguments and should be instantiatable like normal class anyway if user desires so? I'm looking here at PluginLoader, as one of the examples. I want to move it out of Main but I've no idea where to put it. One solution would be to create a PluginLoaderInstance class with accessor methods. |
Blzut3 (administrator) 2014-02-09 17:16 |
The two normal patterns for that would be to provide static accessors for the common instance. There are many examples of this, but the one that comes to mind is Objective-C's NSFileManager where you typically use [NSFileManager defaultManager], but may create your own managers for various reasons. The other way would be to just use globals. Encapsulating them in another class doesn't really add anything. All that basically does is create a namespace. |
Zalewa (developer) 2014-02-11 21:48 |
Alright. I think I'm done on the branch. The documentation thing as well as the normalization of whitespace in header files can be done gradually after the merge so I don't think we should do these things now at all costs. The two things that come to my mind right now that still need to be considered are multicasts and support for IPv6. Are they both possible with the current state of the API without having to break the compatibility? If yes, then are there any other things that you think that need to be done before the merge can occur? I will also put up a testing build before the merge is done and ask folks on the forums to help us check if everything is okay so that we can minimize the risk of something being broken in the process. |
Blzut3 (administrator) 2014-02-13 06:31 |
I believe those two could be added safely. The issues I'd be more concerned about are considering QSharedPointer for Server objects and improve two way communication. The former since even with the ABI safe guards, a fundamental change in how pointers are passed around could be really difficult to provide a fall back for. The latter could probably be dealt with later, but raises the question of how painful would it be to wrap the old API into the new. Basically what is needed is a way to pass a packet back to the socket and then inform the refreshing thread that we're waiting on more data. (Reset any time outs.) |
Zalewa (developer) 2014-02-13 06:39 |
Very well. Do you have ideas for the latter? If so, can you do this? I can do the QSharedPointer thing, even though I don't think any actual work is needed as this is a simple search&replace task. |
Blzut3 (administrator) 2014-02-13 23:54 |
Sure, I can take care of the communication changes. Just reassign this ticket to me when you're done with the shared pointer things so I don't forget about it. |
Zalewa (developer) 2014-02-16 19:44 |
I had a look at the QSharedPointer thing, and the task is not as simple as just "find and replace". Following code will cause a crash:
Therefore we cannot do something like this anymore:
Plugins also need to be aware of this. One instance where QSharedPointer to Server will be particularly useful is the Zandronum testing binaries thing where the Server instance needs to survive through client download and internal event loop generated by the message dialog box. For this to be possible though, Zandronum plugin needs to take the QSharedPointer from somewhere. As 'this' cannot be passed from Server instances directly, it means that we will need to have some kind of method of converting "Server* this" pointers to QSharedPointer instances through some kind of globally accessible manager. This is a quite radical change and I think it even deserves a new branch within the current pluginapi branch so it can be easily reviewed and ditched if it doesn't turn out to be actually what we want. The alternative to this is to wrap "Server*" pointers with QWeakPointer for asynchronous operations on demand, and then checking if pointer is still valid when synchronous execution resumes. Both solutions can lead to some errors where one forgets to either extract pointer from manager or to check if "isNull()" returns true. In the end I believe the QSharedPointer is a step in the right direction, but it may also complicate some stuff. |
Blzut3 (administrator) 2014-02-16 20:26 |
A pointer lookup table doesn't sound like a particularly good solution. It would work if there's no other option I suppose. Perhaps a better choice would be to add a protected QWeakPointer member to the Server class (lets call it self). I believe this could work if the EnginePlugin's server() function is wrapped in something like: QSharedPointer s(plugin->server(...)); This way the ClientRunner line can be changed to `return new GameClientRunner(self)`. Since in theory the function would be executed by something dereferencing a SharedPointer and GameClientRunner would take a SharedPointer. I would think the null check wouldn't be needed in this case. Not the prettiest solution since the QWeakPointer can't be const, but it's a solution that could potentially bring the required changes closer to search and replace. The documentation suggests that since Server is a subclass of QObject we can actually start with a QWeakPointer (thus potentially use direct initialization avoiding the wrapper function and non-const), but I can't say for sure. |
Zalewa (developer) 2014-02-16 23:58 |
That's not very elegant either, but I think it can work. We'll need a public setter for the "self" pointer or introduce some friendships here and there. I'll try to do it with baby steps, hoping that it will prevent some crashing that my previous "search & replace" attempts have done. As for const: sometimes it's just better to ditch const where it causes too much trouble and just use common sense or documentation instead. |
Zalewa (developer) 2014-02-17 19:42 |
I've committed some changes, one of them adds the self() thing you mentioned. It seems to work, but it also looks like a giant with clay legs. Nevertheless, I couldn't come up with a better solution. Perhaps if Server 'signals' were redesigned and if GameClientRunner wasn't instantiated by Server we could do it better, but then again other parts could get a bit more complicated. As a side node, and as I learned some time ago but still way after the fact, the signals don't even need to send the Server pointer as the first argument. You can access the signal sender with sender() method in the slot. The problem is that the slot would then have to be called only from signals, as sender() would return null otherwise, and still we'd be left with a problem of converting Server* to ServerPtr. Perhaps you can come up with some ideas now that the thing is done and it's clearly visible how it's done. I still need to check if more Server* pointers can be replaced with ServerPtrs, but I'm done for today. My wrists are getting really strained. As for the server transaction: I think this can be done by simply creating a new server response code, something akin to SERVER_NEEDS_MORE_COMMUNICATION (but with a smarter name), and then reusing the already available methods to optionally send more challenge packets and to await for more data. The thing that needs to be considered here is that some ports will require additional challenge packets, while others may just split and send the response without informing the client how many packets will arrive. I already see some bad responses for Zandronum servers and given the fact that some servers load million WADs I'm inclined to believe that the servers in fact respond as they should but we can't interpret their response properly. |
Zalewa (developer) 2014-02-18 17:12 |
If you greenlit it, the serverptr branch can be merged back to pluginapi. |
Blzut3 (administrator) 2014-02-18 22:57 |
The serverptr branch seems to work. I poked around a bit and made a few changes. There appear to be a few vanilla Server pointers hanging around. The most questionable being the refresher server registration. I suppose in theory server objects shouldn't disappear while the refresher is working. While I think the following are safe, I'll also mention that some pointers remain in PasswordsCfg, CreateServerDialog, and MasterClient::hasServer. I could take care of these but not right this moment. |
Zalewa (developer) 2014-02-19 06:33 |
Refresher: I think QPointer should be used here. If server is already removed from all other parts of the program we don't need to refresh it anymore, we just want to remove it from the queue. I'll convert these Sever*s to QPointers before merging. As for the other parts where Server* was left in: I inspected the code and noticed no asynchronous operations, so I decided that conversion isn't really needed there. |
Zalewa (developer) 2014-02-19 18:46 |
Reassigned the ticket to Blzut3. Do your magic. |
Zalewa (developer) 2014-02-21 16:24 |
One thing that has come to my mind just today about servers and shared pointers. Perhaps there was a better way to solve this problem, without having to use shared pointers and without having to resort to self() thing, as I believe the whole self() thing can be error prone. Perhaps it would be better to move all server data to a separate structure that can copied freely. Then, when passing Server instances somewhere where asynchronous operations could outlive the Server instance, only this copyable data would be extracted, and server instances could be killed off. Everything would have to be designed in a way to accomodate this: RCon client (which already was, actually), GameClientRunner, buddy list, Wadseeker interface when attempting to connect server with missing WADs, and so on. Of course, there would be some issues with data that is kept in Server instance and only known to plugins, but even that could be worked around somehow. For example: game start operation when launching Wadseeker eventually needs to create the GameClientRunner from the Server instance, but creating GameClientRunner could be the first thing to be done, thus only the GameClientRunner would have to be kept in memory and it'd be guaranteed that this object wouldn't be deleted before its time. I'm not saying we should just go and change it back, but I'm not exactly sure if the current solution is the best that we could do. |
Blzut3 (administrator) 2014-02-21 21:35 |
That is an interesting idea. I'm not sure if it would be an adequate solution to the problem though. Some parts of the program use the pointers to listen for changes and then update, others use them to just pull information (the latter would work in your proposed solution). I guess the biggest concern I have with that is do we need to ensure that up to date information is available to the code using the pointer? On a related note this also makes me wonder if there are any modules (like the buddies list) that may be using shared pointers even though they don't need to keep the object alive (that is should be using a weak pointer)? However, it does make me wonder if we might want to have a server pool regardless. Consider a full refresh, shouldn't we take note of what servers we found before and only delete the ones that are no longer listed? While there's not really a case for it right now, I imagine there could be use for monitoring a server object over time that should survive full refreshes. |
Blzut3 (administrator) 2014-02-27 23:38 |
Looking at the PasswordsCfg and CreateServerDialog again I determined the change would be extra pointless since the functions are private and not exported. I agree with your idea to just add a few more response codes to the server refresh protocol. Right now asking to send another packet allows the object to send immediately. I believe this should work fine, but if any plugin starts using this feature and it turns out otherwise, it might be a better idea to put the server back on the queue to be re-batched. I also made the MasterClients follow a similar API which simplifies things a bit. It's worth noting here that there could be more room for refactoring there by having bother Server and MasterClient inherit from some "refreshable" class. Combined with your server pool idea this could really streamline the API and let the refreshing thread treat the masters and servers the same. (Which implies being able to query servers while waiting for additional master responses.) However, this may be something to consider for another API/ABI revision since there are honestly more important areas that need refactoring before worrying about something minor like that. I will turn this issue back over to you. Probably worth putting out another test build and then if everything seems OK, going ahead and merging. |
Zalewa (developer) 2014-02-28 08:51 |
There are two more things: - "virtual bool MasterClient::getServerListRequest(QByteArray &data)=0;" I think it should just return QByteArray instead of accepting a reference to one and returning a bool. I'll take care of that. - How would we handle master servers that don't work on UDP but rather provide server lists through HTTP, or through some other TCP-based means? I think we had something like that with ZDaemon, and we need to be prepared that other games may do that too. I don't imagine that game servers themselves would use anything other than the same UDP port that they use for normal gameplay, but perhaps we should also be prepared for this. |
Blzut3 (administrator) 2014-02-28 13:03 |
In regards to the first point, if you do that, don't forget to also mirror the change in the Server API. In regards to TCP. The ZDaemon plugin did indeed once use HTTP, but that was taken down as soon as we started using it and thus I had to reverse engineer their UDP protocol. The hack of opening the socket in the plugin code worked well. Obviously it circumvented the refresher thread a bit, but the end result was the required signals got emitted. Given that TCP has to make an actual connection, I don't think its possible to share a single socket like we do for UDP. |
Zalewa (developer) 2014-03-03 17:40 |
Done! Finally. Anyway, I think it's still safe to do commits to pluginapi branch and merge with default as long as we're still inbetween versions, therefore I'm not closing the branch itself, yet. |
This issue is already marked as resolved. If you feel that is not the case, please reopen it and explain why. |
|
Supporters: | No one explicitly supports this issue yet. |
Opponents: | No one explicitly opposes this issue yet. |
![]() |
|||
Date Modified | Username | Field | Change |
2013-11-19 21:49 | Blzut3 | New Issue | |
2013-11-19 22:06 | Blzut3 | Note Added: 0007576 | |
2013-11-20 06:40 | Zalewa | Note Added: 0007577 | |
2013-11-20 18:18 | Blzut3 | Note Added: 0007578 | |
2013-11-20 21:05 | Zalewa | Note Added: 0007583 | |
2013-11-20 21:37 | Blzut3 | Note Added: 0007584 | |
2013-11-20 22:01 | Zalewa | Note Added: 0007585 | |
2013-11-20 23:56 | Blzut3 | Note Added: 0007586 | |
2013-11-21 01:34 | Edward-san | Note Added: 0007587 | |
2013-11-21 17:18 | Zalewa | Note Added: 0007588 | |
2013-11-21 18:42 | Edward-san | Note Added: 0007590 | |
2013-11-21 18:54 | Edward-san | Note Edited: 0007590 | View Revisions |
2013-11-21 22:23 | Blzut3 | Note Added: 0007591 | |
2013-11-30 13:48 | Zalewa | Note Added: 0007644 | |
2013-11-30 15:29 | Zalewa | Note Added: 0007645 | |
2013-11-30 17:09 | Blzut3 | Note Added: 0007647 | |
2013-12-13 03:58 | Blzut3 | Note Added: 0007698 | |
2013-12-13 03:59 | Blzut3 | Note Edited: 0007698 | View Revisions |
2013-12-26 16:36 | Zalewa | Note Added: 0007728 | |
2013-12-26 20:34 | Blzut3 | Note Added: 0007729 | |
2013-12-26 23:29 | Zalewa | Note Added: 0007731 | |
2013-12-26 23:43 | Blzut3 | Note Added: 0007732 | |
2013-12-27 01:04 | Blzut3 | Note Edited: 0007732 | View Revisions |
2013-12-27 01:17 | Zalewa | Note Added: 0007733 | |
2013-12-27 01:28 | Blzut3 | Note Added: 0007734 | |
2013-12-27 01:29 | Blzut3 | Note Edited: 0007734 | View Revisions |
2013-12-27 10:13 | Zalewa | Note Added: 0007735 | |
2014-01-12 13:51 | Zalewa | Note Added: 0007978 | |
2014-01-12 18:36 | Blzut3 | Note Added: 0007982 | |
2014-01-12 19:10 | Zalewa | Note Added: 0007983 | |
2014-02-02 18:52 | Zalewa | Note Added: 0008157 | |
2014-02-02 18:59 | Blzut3 | Note Added: 0008158 | |
2014-02-02 19:03 | Zalewa | Note Added: 0008159 | |
2014-02-02 19:03 | Zalewa | Note Edited: 0008159 | View Revisions |
2014-02-03 23:31 | Zalewa | Note Added: 0008164 | |
2014-02-04 01:38 | Blzut3 | Note Added: 0008165 | |
2014-02-04 06:44 | Zalewa | Note Added: 0008166 | |
2014-02-09 14:08 | Zalewa | Note Added: 0008178 | |
2014-02-09 17:16 | Blzut3 | Note Added: 0008180 | |
2014-02-11 21:48 | Zalewa | Note Added: 0008190 | |
2014-02-12 17:33 | Zalewa | Assigned To | => Zalewa |
2014-02-12 17:33 | Zalewa | Status | new => needs testing |
2014-02-13 06:31 | Blzut3 | Note Added: 0008193 | |
2014-02-13 06:39 | Zalewa | Note Added: 0008194 | |
2014-02-13 23:54 | Blzut3 | Note Added: 0008203 | |
2014-02-16 19:44 | Zalewa | Note Added: 0008226 | |
2014-02-16 19:44 | Zalewa | Status | needs testing => assigned |
2014-02-16 20:26 | Blzut3 | Note Added: 0008227 | |
2014-02-16 23:58 | Zalewa | Note Added: 0008229 | |
2014-02-17 19:42 | Zalewa | Note Added: 0008234 | |
2014-02-18 17:12 | Zalewa | Note Added: 0008238 | |
2014-02-18 22:57 | Blzut3 | Note Added: 0008242 | |
2014-02-19 06:33 | Zalewa | Note Added: 0008244 | |
2014-02-19 18:45 | Zalewa | Assigned To | Zalewa => Blzut3 |
2014-02-19 18:46 | Zalewa | Note Added: 0008248 | |
2014-02-21 16:24 | Zalewa | Note Added: 0008257 | |
2014-02-21 21:35 | Blzut3 | Note Added: 0008261 | |
2014-02-27 23:38 | Blzut3 | Note Added: 0008290 | |
2014-02-27 23:38 | Blzut3 | Assigned To | Blzut3 => Zalewa |
2014-02-28 08:51 | Zalewa | Note Added: 0008291 | |
2014-02-28 13:03 | Blzut3 | Note Added: 0008292 | |
2014-03-03 17:40 | Zalewa | Note Added: 0008308 | |
2014-03-03 17:40 | Zalewa | Status | assigned => resolved |
2014-03-03 17:40 | Zalewa | Fixed in Version | => 0.12 Beta |
2014-03-03 17:40 | Zalewa | Resolution | open => fixed |
2018-09-29 14:46 | WubTheCaptain | Status | resolved => closed |
Copyright © 2000 - 2025 MantisBT Team |