Upcoming development build

3 months have passed since last release. It is high time for a development build. I’d like to release one within a day or two.

Please let me know if:

  • this date is ok with you (features you work on are not in the half-done state)
  • there are any particular issues you’d like me to take a look at*
  • there are other significant issues :wink:
  • @Ivan — Yes, I remember about the writeable location issue on Windows.

Date is OK. There are still a few remaining issues concerning campaigns and probably I will fix them during next week. Do not wait further for dev build :slight_smile:

I also think that date is OK, but I don’t know, it’ll be better if someone with more experience will tell something about it.

One thing I forgot about - serialization of AI is partially disabled due to some problems with serializer encountered earlier. However, this thing makes savegames totally buggy and any game won’t load.

That’s pretty terrible blocker. Without saves it would be hard to reproduce reported issues.

AI, even if unable to store its own state, should not break the savegame loading itself.

Any chance you could get it to work in the near future?

I just un-abstracted AbstractGoal to allow serialization.

However, that doesn’t help. Console reports the following error:

Failed to save game: Access violation - no RTTI data!

It seems that the issue is elsewhere or I don’t understand it either way.

Could you just disable goal serialization altogether for the time being? It would reset AI “thinking” at the loading but it should work.

Goals are not registered, polymorphic serialization won’t work. And even if it did, serialzier doesn’t properly work with shared_ptr. [And if it did, I have no idea how to make it work both with shared-ptr and polymorphic serialization.]
Class hierarchies and pointers are so much trouble, that’s why I used value semantics (and huge switch). Now you’d probably need a similar switch to handle serialziation.

That’s how it was for last month or so - that is, part of AI responsible for storing goals was excluded from serialization.

So I guess you need to disable as much of AI serialziation as is needed to make game loading again. (Does it work when AI load/save are total no-ops?)

Still, I don’t see how disabling some aprts of AI serialziation can break savegame. Breaks happen basically when save/load oparations are not symmetrical.

These do not have to be directly related.

Either way, I can’t find where does “no RTTI data” exception come from. Please take a look.

So the broken savegames are not necesserily realted to AI?

[EDIT] Not as simple as I thought. I’ll check this.

How do I reproduce the problem?

I have built current trunk, started Arrogance, passed one turn, saved, loaded and it worked.

I launched “Arrogance 3” and it happened fter 1st turn.

However, there was no bug when I launched the game with only WoG mod active. So seems to be mod-related issue.

Try — as soon before the crash as possible, to avoid false exceptions — to make debugger break on throwing exceptions.
Enter Debug -> Exceptions, check the checkbox next to “C++ exceptions”.

The debugger will stop the program when exception is thrown (regardless if it is handled), so you’ll be able to tell where it comes from, get the stacktraces, variables and so on.

It looks as if typeid was called on a invalid pointer. Serializing invalid pointer is illegal. The question is — who tries that and why.

Actually as soon as starting autosave is made, this line fails:

	ui16 getTypeID(const std::type_info *type);
	template <typename T> ui16 getTypeID(const T * t = nullptr)
		return getTypeID(getTypeInfo(t));

With CreatureID.

Note that my machine barely works so I can’t really debug efficiently.

What is value of t? I believe it is not a valid pointer (neither nullptr nor the pointer to an existing object).
What is the stacktrace?

Stack trace:

 	KernelBase.dll!7648c41f()	Unknown
 	[Frames below may be incorrect and/or missing, no symbols loaded for KernelBase.dll]	
>	msvcr110.dll!_CxxThrowException(void * pExceptionObject, const _s__ThrowInfo * pThrowInfo) Line 152	C++
 	msvcr110.dll!__RTtypeid(void * inptr) Line 147	C++
 	VCMI_lib.dll!CTypeList::getTypeID<CCreature>(const CCreature * t) Line 103	C++
 	VCMI_lib.dll!COSer<CSaveFile>::savePointer<CCreature *>(CCreature * const & data) Line 668	C++
 	VCMI_lib.dll!CHeroClass::serialize<COSer<CSaveFile> >(COSer<CSaveFile> & h, const int version) Line 141	C++
 	VCMI_lib.dll!COSer<CSaveFile>::savePointer<CHeroClass *>(CHeroClass * const & data) Line 671	C++
 	VCMI_lib.dll!CHeroClassHandler::serialize<COSer<CSaveFile> >(COSer<CSaveFile> & h, const int version) Line 186	C++
 	VCMI_lib.dll!CHeroHandler::serialize<COSer<CSaveFile> >(COSer<CSaveFile> & h, const int version) Line 255	C++
 	VCMI_lib.dll!COSer<CSaveFile>::savePointer<CHeroHandler *>(CHeroHandler * const & data) Line 671	C++
 	VCMI_lib.dll!LibClasses::serialize<COSer<CSaveFile> >(COSer<CSaveFile> & h, const int version) Line 63	C++
 	VCMI_lib.dll!CPrivilagedInfoCallback::saveCommonState<CSaveFile>(CSaveFile & out) Line 249	C++
 	VCMI_client.exe!SaveGame::applyCl(CClient * cl) Line 802	C++
 	VCMI_client.exe!CApplyOnCL<SaveGame>::applyOnClAfter(CClient * cl, void * pack) Line 74	C++
 	VCMI_client.exe!CClient::handlePack(CPack * pack) Line 517	C++
 	VCMI_client.exe!CClient::run() Line 151	C++
 	VCMI_client.exe!boost::`anonymous namespace'::thread_start_function(void *)	C++
 	msvcr110.dll!_callthreadstartex() Line 354	C
 	msvcr110.dll!_threadstartex(void * ptd) Line 332	C
 	kernel32.dll!76e5336a()	Unknown
 	ntdll.dll!77949f72()	Unknown
 	ntdll.dll!77949f45()	Unknown

At this line:

		//write type identifier
		ui16 tid = typeList.getTypeID(data);
		*this << tid;

tid = 52186.

tid value is bogus magic bytes (0xbcda). Exception is thrown when evaluating the initializing expression.

The crahs is apparently caused by a invalid poitner CHeroClass::commander. Apparently it wasn’t initialized. I have committed a fix. Please check if the issue is gone.

Looks like it works fine now :slight_smile:

I figured out how to solve this issue.
Basically registering classees should not register the class but the relationship between base and its descendant. With that serializaer can build proper inheritance graph and instantiate helpers for all conversions it needs.

TCP serialization treats shared/weak/unique pointer as usual pointer.
File serialization keeps shared_ptr copy for each loaded type.
This will give exactly the semantics we need.