I’m trying to make a datagram iterator so I can check for my issue with the distributed network system. But…
File "/usr/share/panda3d/direct/distributed/ConnectionRepository.py", line 498, in connect
successCallback(*successArgs)
File "/home/croxis/src/ITF/ITFClientRepository.py", line 194, in connectSuccess
self.setInterestZones([1])
File "/usr/share/panda3d/direct/distributed/ClientRepository.py", line 258, in setInterestZones
self.send(datagram)
File "/usr/share/panda3d/direct/distributed/ConnectionRepository.py", line 648, in send
self.sendDatagram(datagram)
AssertionError: _current_index + sizeof(tempvar) <= _datagram->get_length() at line 203 of built/include/datagramIterator.I
bool CConnectionRepository::
send_datagram(const Datagram &dg) {
ReMutexHolder holder(_lock);
if (_simulated_disconnect) {
distributed_cat.warning()
<< "Unable to send datagram during simulated disconnect.\n";
return false;
}
if (get_verbose()) {
describe_message(nout, "SEND", dg);
}
if (is_bundling_messages() && get_want_message_bundling()) {
bundle_msg(dg);
return true;
}
#ifdef WANT_NATIVE_NET
if(_native)
return _bdc.SendMessage(dg);
#endif
#ifdef HAVE_NET
if (_net_conn) {
_cw.send(dg, _net_conn);
//
// MY CODE HERE
//
_di = DatagramIterator(_dg);
_msg_type = _di.get_uint16();
cout << _msg_type;
cout << "\n";
return true;
}
#endif // HAVE_NET
etc etc....
Doh! So I managed to get the DoId: 3906 every time I run it. Any pointers (I made a pun!) on getting additional details to find the culprit at the c or python level? I recall finding a function to get a DO from the doid, but i don’t remember where I found it.
when you detect that ID. That will raise a Python exception at the current line; that may give a hint.
If the Python line isn’t useful, you’ll have to look at the C++ stack; you can get this by putting:
assert-abort 1
in your Config.prc file, which will make the above line generate a fatal C++ error instead of a Python exception. Then you can inspect the C++ stack using the MSVS debugger.
File "/home/croxis/src/ITF/ITFAIRepository.py", line 116, in addNewShip
distributedShip.startPosHprBroadcast()
File "/home/croxis/src/ITF/DistributedSmoothNodeBase.py", line 95, in startPosHprBroadcast
self.cnode.sendEverything()
AssertionError: false at line 472 of direct/src/distributed/cConnectionRepository.cxx
Right, you aren’t the owner, so that is the correct behavior. If you want to allow the AI to move around an object that it didn’t create, you will have to add the “clsend” tag to all of the setComponentL, X, Y, Z, etc. functions for DistributedSmoothNode in the dc file.
Normally poshpr changes are made on normal clients so the code in the else segment is run, no problems. However if the AI flag is set to true the first chunk of the if statement is run instead, which seems to of gone untested until me and my shenanigans.
Please correct me if I am wrong, but my impression from the videos and the previous forums posts is that I need to code how to unpack a datagram as there is no magic way to figure out how it is all bundled up.
If this is true I find it unusual that, for the _is_ai block, a unit8 and two raw pack channels are packed BEFORE the unint16 updatefield type as opposed to after it. There is no guarantee that _do_id and _ai_id will be consistent to try and add a check for it in the Server Repository.
The problem is that the cmu server will always unpack the first thing as a uint16, which is not the case when the update is sent as an AI.
While I will probably end up using your workaround, it does seem kind of hackish and dances around the attempt to implement an open source OTP server.
Two questions in an attempt to find a more elegant solution.
Is it possible to release and incorporate the code for this specific element from OTP into the ServerRepository? (My guess is no as I am sure there are a bazillion legal and political issues involved.)
Any suggestions on how it could be handled in the ServerRepository? The only solution I have been able to come up with so far is create a second DataGramItereator instance and check if Uint8 is 1. I foresee problems with this as it could be that a separate datagram message could coincidentally begin with a uint8 that is 1 and result in an improperly interpreted message.
A for instance:
I have the hpr, pos as broadcast clsend. I know this opens it up to hacks but it’s a temp solution and it works.
I have game logic methods sent by the client via GUI elements and tagged with p2p ownsend. They are received by the AI’s version of the doId and handled via local methods and local classes until there’s output to send back. That output is sent with either p2p ownsend (if it’s doId specific) or broadcast if I want others to see it (for instance combat chat). Works as well.
What I want is to create a new keyword: aisend. This is a field that can only be sent by the ai repository. Also want to get airecv working so it only sends those fields to the ai repo’s version of the doId.
I may be wrong in this but I don’t think there’s any other way to dictate via the .dc system who is allowed to send out the message. If it’s ownsend then the doId’s have to match up but it doesn’t stop a client Repo from sending out a field as a doId that you might want the AI to handle explicitly. If it’s clsend then anyone can send it.
Anyway the point being, if you had something such as aisend (which implies broadcast from the ai only), then you wouldn’t need to worry about other clients hacking pos and hpr for godspeed or messing with your ai-run entities. Because the SR would ignore any field that came in with those tags from a repo != ai.
Drwr or someone else can probably point out my faults (and there are many, I am sure). But it’s the only logical solution I came up with without having to go in and mess with the source.
However, I have a few more threads to kill and integrate into my polling dict functions on the ai repo before I get a chance to play with it.
Good luck!
P.S. other thing you could do is have the AI actually create all the DOs, thus they are the owner of everything. I do this for some things in my project (pets, charming, etc.) and it works but I have an additional field to toggle what can and can’t be controlled by a cliennt which is held by a local attribute in an AI’s local class (so nothing is distributed).
The problem is DistributedSmoothNode, with automatic position smoothing, does some unique stuff in a task to help minimize the effects of laggy updates. This is something I would like to use and try to fix.
No, the whole thing about the _is_ai block is that it is completely wrong, at least for the CMU release, which doesn’t make a distinction between AI clients and other clients.
The _is_ai block is only correct for the Disney version, which does have a completely different format for these two types of clients. But this just means that really, this code doesn’t belong in DistributedSmoothNode; it should be elsewhere.
Since it is here, though, you can easily work around that mistake just by telling it you’re not an AI. That’s not a hack; that’s correct information: you’re not a Disney AI. The only reason for the _is_ai switch is to tell the node to format its messages according to the convention for Disney AI’s, which you don’t want it to do.