Identifying and solving OOS problems

Ok. I´ve tried it like this:
Code:
import os
from CvPythonExtensions import *
import CvUtil
[COLOR="Red"]import BugPath[/COLOR]

gc = CyGlobalContext()

szFilename = "OOSLog.txt"
iMaxFilenameTries = 100

bWroteLog = False

SEPERATOR = "-----------------------------------------------------------------\n"


# Simply checks every game turn for OOS. If it finds it, writes the
# info contained in the sync checksum to a log file, then sets the bWroteLog
# variable so that it only happens once.
def doGameUpdate():
	global bWroteLog
	bOOS = CyInterface().isOOSVisible()

	if (bOOS and not bWroteLog):
		writeLog()
		bWroteLog = True

def writeLog():
	playername = CvUtil.convertToStr(gc.getPlayer(gc.getGame().getActivePlayer()).getName())
	szNewFilename = [COLOR="Red"]getRootDir() + "\\Logs\\" + [/COLOR]"%s - Player %s - " % (playername, gc.getGame().getActivePlayer()) + "OOSLog - Turn " + "%s" % (gc.getGame().getGameTurn()) + ".txt"
	pFile = open(szNewFilename, "w")

Then I provoked an OOS in the first round (founding a city). Unfortunatly no OOSLogger.txt.:(
 
Ok. I´ve tried it like this:
Code:
import os
from CvPythonExtensions import *
import CvUtil
[COLOR="Red"]import BugPath[/COLOR]

gc = CyGlobalContext()

szFilename = "OOSLog.txt"
iMaxFilenameTries = 100

bWroteLog = False

SEPERATOR = "-----------------------------------------------------------------\n"


# Simply checks every game turn for OOS. If it finds it, writes the
# info contained in the sync checksum to a log file, then sets the bWroteLog
# variable so that it only happens once.
def doGameUpdate():
	global bWroteLog
	bOOS = CyInterface().isOOSVisible()

	if (bOOS and not bWroteLog):
		writeLog()
		bWroteLog = True

def writeLog():
	playername = CvUtil.convertToStr(gc.getPlayer(gc.getGame().getActivePlayer()).getName())
	szNewFilename = [COLOR="Red"]getRootDir() + "\\Logs\\" + [/COLOR]"%s - Player %s - " % (playername, gc.getGame().getActivePlayer()) + "OOSLog - Turn " + "%s" % (gc.getGame().getGameTurn()) + ".txt"
	pFile = open(szNewFilename, "w")

Then I provoked an OOS in the first round (founding a city). Unfortunatly no OOSLogger.txt.:(
You need to use BugUtil.getRootDir() I think (that is the difference between "import BugUtil" and "from BugUtil import *").
 
Shouldn´t it be BugPath.getRootDir() instead of BugUtil.getRootDir() since getRootDir is defined there?

Neither way worked for me.:(

My problem is, that I believe the ooslogge.txt isn´t written anywhere because I tried it the "normal" path again and even in the folder where the exe of bts is I could find nothing.

Do I have to change anything else beside the CvEventManager.py and adding the OOSLogger.py? I´ve already checked BugCore.xml and it´s the same.

All logging options I found in the CivilizationsIV.ini are activated:
Code:
; Enable the logging system
LoggingEnabled = 1

; Enable synchronization logging
SynchLog = 1

; Overwrite old network and message logs
OverwriteLogs = 1

; Enable rand event logging
RandLog = 1

; Enable message logging
MessageLog = 1
 
Shouldn´t it be BugPath.getRootDir() instead of BugUtil.getRootDir() since getRootDir is defined there?
You are right. BugPath needs to be imported and used.

Neither way worked for me.:(

My problem is, that I believe the ooslogge.txt isn´t written anywhere because I tried it the "normal" path again and even in the folder where the exe of bts is I could find nothing.

Do I have to change anything else beside the CvEventManager.py and adding the OOSLogger.py? I´ve already checked BugCore.xml and it´s the same.
OOSLogger should run on every game update event. When you use BUG, that means registering it properly with BUG.
 
:)

It works now and it´s written in the log-folder!:goodjob: I had to add it on the onGameUpdate in BugEventManager.py. I´ve no clue why it wasn´t enough to add it in the CvEventManager.py but it´s ok.

Thank you very much for your help. But of course I had a new problem. When the logfile is written the following error occurs many times:
Code:
Traceback (most recent call last):
  File "BugEventManager", line 362, in _handleDefaultEvent
  File "BugEventManager", line 455, in onGameUpdate
  File "OOSLogger", line 24, in doGameUpdate
  File "OOSLogger", line 106, in writeLog
UnicodeEncodeError: 'ascii' codec can't encode character u'\xd6' in position 10: ordinal not in range(128)

It´s a problem with an umlaut which I solved in the following way (new parts are red):
Code:
			pFile.write("Bonus Info:\n")
			pFile.write("-----------\n")
			for iBonus in range(gc.getNumBonusInfos()):
				pFile.write("Player %d, %s, Number Available: %d\n" % (iPlayer, gc.getBonusInfo(iBonus).getDescription()[COLOR="Red"].encode(fileencoding)[/COLOR], pPlayer.getNumAvailableBonuses(iBonus) ))
				pFile.write("Player %d, %s, Import: %d\n" % (iPlayer, gc.getBonusInfo(iBonus).getDescription()[COLOR="Red"].encode(fileencoding)[/COLOR], pPlayer.getBonusImport(iBonus) ))
				pFile.write("Player %d, %s, Export: %d\n" % (iPlayer, gc.getBonusInfo(iBonus).getDescription()[COLOR="Red"].encode(fileencoding)[/COLOR], pPlayer.getBonusExport(iBonus) ))
				pFile.write("\n")

Additional the fileencoding has to be added at the top (line 7 in my OOSLogger.py):
Code:
gc = CyGlobalContext()
fileencoding = "latin_1"	# aka "iso-8859-1"

After I added these, the logfile was written without an error.:D

Perhaps the part for the fileencoding should be added at the other lines where something is written too, to make sure that no error occurs.

Just wrote it in case you want it to use for your mod for the players who play in a language with umlauten.
 
Hi,

it´me again with a question about the ooslogger. We actually play a Pitboss-Game with my mod and some times an OOS occurs. The Checksum of all players is the same and even the files that are created with the OOSLogger are the same for all players. So I think the problem are the gamestats at the pitboss-server but unfortunatly there the OOSLogger don´t write a log although logging is enabled. Any ideas why the log is missing?

Thank you for your help.
 
Hi,

it´me again with a question about the ooslogger. We actually play a Pitboss-Game with my mod and some times an OOS occurs. The Checksum of all players is the same and even the files that are created with the OOSLogger are the same for all players. So I think the problem are the gamestats at the pitboss-server but unfortunatly there the OOSLogger don´t write a log although logging is enabled. Any ideas why the log is missing?

Thank you for your help.
The Pitboss computer is running a full instance of the game but some functions behave different (and you can get a player number of -1 in some functions that don't usually expect it which can cause OOS). Especially in regards to the UI part which is not needed on the Pitboss.
So it might be that CyInterface().isOOSVisible() does not actually return true there and the OOSLogger fails to recognize that it has gone OOS.
Or, more likely, since the active player on the Pitboss is -1, it will fail when it tries to get the player name with
gc.getPlayer(gc.getGame().getActivePlayer()).getName()

So best change that piece of the code to first check if gc.getGame().getActivePlayer() is -1 and then set playername to "Pitboss" in the OOSLogger writeLog function.
 
Thanks for the quick answer. I´ll try it but what do you mean with "the UI part"?
Pitboss runs the entire game and AI same as a normal player but obviously it does not need to run the user interface elements of the game. So likely some of them are switched off for performance reasons which might cause some different behavior when you query the UI.
 
So best change that piece of the code to first check if gc.getGame().getActivePlayer() is -1 and then set playername to "Pitboss" in the OOSLogger writeLog function.

:goodjob:

That worked! Great.

Another question about writing the logs. Sometimes computers of some players don´t write an OOSlog although we have an OOS. Mostly the first OOS on one day is correctly logged but if we get another OOS shortly after the first, some logs are not written. Any idea what could cause these problems?
 
:goodjob:

That worked! Great.

Another question about writing the logs. Sometimes computers of some players don´t write an OOSlog although we have an OOS. Mostly the first OOS on one day is correctly logged but if we get another OOS shortly after the first, some logs are not written. Any idea what could cause these problems?
The reason is that the code uses a Python variable named bWroteLog to store that it has already written an OOS log. And the Python environment is only reset on restarting the game. So when it encounters the next OOS it thinks that it has already written the log.

One option would be to count whenever you get into doGameUpdate but CyInterface().isOOSVisible() is not true and when that variable reaches 100 or so, then reset bWroteLog to false (and set that variable to 0 when you actually see an OOS).
 
Ok. The only thing I don´t understand is why I should count. Wouldn´t it be easier to check if CyInterface().isOOSVisible() is not true and then just reset bWroteLog to false?
 
Ok. The only thing I don´t understand is why I should count. Wouldn´t it be easier to check if CyInterface().isOOSVisible() is not true and then just reset bWroteLog to false?
Simply because I am not sure if it will always stay true in every time slice when an OOS has happened. So I chose the safe way and count to make sure that it has not been an OOS for 100 time slices before resetting the bWroteLog. If it is reset too early, it will overwrite the OOS logs with some maybe not as enlightening because they are later.

Of course it might be that isOOSVisible stays true. Then you don't need to count. But the checksum calculated is on a 4 time slice rotation and in each one some different part of the total game state is included. If only part of the game state has desynced yet some of those checksums might actually be ok and that might toggle isOOSVisible to be false in some time slices. Hence the counting to make sure it stays false for a good amount of time slices.
 
Ok. Your solution works perfectly! Thx again!


EDIT:
When I substitute the old file with the new one, I´m not able to load an old savegame although it´s the only file I´ve changed. I thought changing or editing .py-files wouldn´t be a problem. Is there any way I could use the old save with the new file within the mod?
 
Ok. Your solution works perfectly! Thx again!


EDIT:
When I substitute the old file with the new one, I´m not able to load an old savegame although it´s the only file I´ve changed. I thought changing or editing .py-files wouldn´t be a problem. Is there any way I could use the old save with the new file within the mod?
Changing that Python file should not have any impact on savegames.
Are you sure it is the only thing you changed?
 
Yes. I sent the new file to my friends and the one who hosts the pitboss server said, that he couldn´t load the savegame with the pitboss (see attachment). He has only copied the old ooslogger.py to the desktop on the server and the new one in the right place in the Mod.
 

Attachments

  • Screenshot Pitboss-Message cut.jpg
    Screenshot Pitboss-Message cut.jpg
    69.2 KB · Views: 58
Back
Top Bottom