Source Code and Ideas question

General discussion for players of Oolite.

Moderators: winston, another_commander

User avatar
Pleb
---- E L I T E ----
---- E L I T E ----
Posts: 908
Joined: Sun Apr 29, 2012 2:23 pm
Location: United Kingdom

Re: Source Code and Ideas question

Post by Pleb »

cim wrote:
The stars aren't showing up because the translation from Unicode to Oolite's non-standard 256-character encoding only happens when processing text from plists. A literal string is just treated as is. So you'll need to embed the characters in Oolite's charset - octal notation is probably the shortest way: you can find the stars' byte numbers by looking at the oolite-font texture or plist.
I actually found an easier way of doing this:

Code: Select all

		NSString *eliteRating = [NSString stringWithUTF8String:"★★★ E L I T E ★★★"];
		NSString *deadlyRating = [NSString stringWithUTF8String:"☆ Deadly ☆"];
By using the stringWithUTF8String I can get the stars to appear! 8)

I am now in the process of simplifying this all as suggested, by having one long function and two short ones. I will post up full instructions of implementation afterwards, as the instructions have gotten a bit all over the place! :oops:
Desktop PC: CPU: Intel i7-4790K Quad Core 4.4GHz (Turbo-Charged) GPU: Nvidia GeForce GTX 1080Ti RAM: 32GB DDR3

Laptop PC: CPU: Intel i5-10300H Quad Core 4.5GHz (Turbo-Charged) GPU: Nvidia GeForce GTX 1650 RAM: 32GB DDR4
User avatar
Pleb
---- E L I T E ----
---- E L I T E ----
Posts: 908
Joined: Sun Apr 29, 2012 2:23 pm
Location: United Kingdom

Re: Source Code and Ideas question

Post by Pleb »

Okay I've hit a slight snag when trying to move as much of these two functions into one as possible. The biggest problem is that one function (the ratings one) takes the unsigned value (kills) and gives a rating based on that value. The other function (the legal status one) takes an integer value (bounty) and gives a legal status based on that value. So trying to write a big function that does both is a problem, because if it's expecting an integer value it won't accept an unsigned value, and vice versa.

My next approach was to devise a BOOL function, that would validate whether it could use the new descriptions or not, and this way the integer and unsigned problem wouldn't be an issue. Unfortunately this will not work either as at the end of the functions, when they are about to generate the new descriptions it now needs a sorted array and a mutable dictionary to do this, which is part of the BOOL function.

The only way around this, would be to have a few different functions. The two original functions (display rating name and display legal status), then separate functions (one that sorts the number array and another that puts the text array into a mutable dictionary). This is the only way of shortening this code, because of the dependencies it needs... :(
Desktop PC: CPU: Intel i7-4790K Quad Core 4.4GHz (Turbo-Charged) GPU: Nvidia GeForce GTX 1080Ti RAM: 32GB DDR3

Laptop PC: CPU: Intel i5-10300H Quad Core 4.5GHz (Turbo-Charged) GPU: Nvidia GeForce GTX 1650 RAM: 32GB DDR4
another_commander
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 6681
Joined: Wed Feb 28, 2007 7:54 am

Re: Source Code and Ideas question

Post by another_commander »

Since bounty can't be a negative value, what stops you from changing the function that expects an integer to one that expects an unsigned? That would bypass the largest part of your problem, I think.
User avatar
Pleb
---- E L I T E ----
---- E L I T E ----
Posts: 908
Joined: Sun Apr 29, 2012 2:23 pm
Location: United Kingdom

Re: Source Code and Ideas question

Post by Pleb »

I was just testing this by changing the int to an unsigned and seeing if that compiled okay - I also couldn't figure out why the bounty was an int value when it's never a negative number! As this has just compiled okay I will now make sure the 2 little functions and big functions I devised work, and then I will post everything up again to see if anything else can break it!
Desktop PC: CPU: Intel i7-4790K Quad Core 4.4GHz (Turbo-Charged) GPU: Nvidia GeForce GTX 1080Ti RAM: 32GB DDR3

Laptop PC: CPU: Intel i5-10300H Quad Core 4.5GHz (Turbo-Charged) GPU: Nvidia GeForce GTX 1650 RAM: 32GB DDR4
User avatar
Pleb
---- E L I T E ----
---- E L I T E ----
Posts: 908
Joined: Sun Apr 29, 2012 2:23 pm
Location: United Kingdom

Re: Source Code and Ideas question

Post by Pleb »

So, let's start at the beginning. First, open the file PlayerEntity.h and go to line 1029 and replace that line with the following:

Code: Select all

NSString *OODisplayStringFromLegalStatus(unsigned legalStatus);
Now open the NSStringOOExtensions.h file and add this at line 61:

Code: Select all

- (NSComparisonResult)oo_compareNumerically:(NSString *)str;
Now open the OOConstToString.h file and add this at line 106:

Code: Select all

NSString *OODisplayCustomStringFromDescriptionsArray(NSString *inputNumArray, NSString *inputStringArray, unsigned inputNum, NSString *context);
This takes care of the header files. Now, open the NSStringOOExtensions.m file and add the following at line 151:

Code: Select all

- (NSComparisonResult)oo_compareNumerically:(NSString *)str 
{
	NSNumber * num1 = [NSNumber numberWithInt:[self intValue]];
	NSNumber * num2 = [NSNumber numberWithInt:[str intValue]];

	return [num1 compare:num2];
}
Now open the OOConstToString.m file and go to line 470. Insert the following here (do not replace anything yet, just insert this function):

Code: Select all

NSString *OODisplayCustomStringFromDescriptionsArray(NSString *inputNumArray, NSString *inputStringArray, unsigned inputNum, NSString *context)
{
	NSArray				*stringArray = nil;
	NSArray				*numArray = nil;
	NSMutableArray   	*mutableNumArray = [[NSMutableArray alloc] init];
	NSArray       		*sortedNumArray = nil;
	NSMutableDictionary *stringArrayDict = [[NSMutableDictionary alloc] init];
	NSString			*numString;
	NSString			*textString;
	unsigned			i;
	int					numInt;
	BOOL				customStringInvalid;
	NSString			*logKey;

	stringArray = [[UNIVERSE descriptions] oo_arrayForKey:inputStringArray];
	numArray = [[UNIVERSE descriptions] oo_arrayForKey:inputNumArray];
	customStringInvalid = NO;
	numInt = 0;
	logKey = @"_default";
	
	if ([context isEqualToString:@"ratings"]) logKey = @"new.ratings.error";
	if ([context isEqualToString:@"legal_status"]) logKey = @"new.legal.status.error";

	for (i = 0; i < [numArray count]; ++i)
	{
		textString = [NSString stringWithFormat:@"%u", [numArray oo_intAtIndex:i]];
		numInt = [textString integerValue];
		if (numInt < 0)
		{
			customStringInvalid = YES;
			OOLog(logKey, @"'%@' array in descriptions.plist contains a negative value - reverting to original system.", inputNumArray);
			break;
		}
	}

	for (i = 0; i < [numArray count]; ++i)
	{
		textString = [NSString stringWithFormat:@"%u", [numArray oo_intAtIndex:i]];
		[mutableNumArray addObject:textString];
	}
   
	sortedNumArray = [mutableNumArray sortedArrayUsingSelector:@selector(oo_compareNumerically:)];

	if ([stringArray count] != [sortedNumArray count] && !customStringInvalid) 
	{
		customStringInvalid = YES;
		OOLog(logKey, @"'%@' and '%@' array size in descriptions.plist not equal - reverting to original system.", inputNumArray, inputStringArray);
	}

	if ([sortedNumArray oo_unsignedIntAtIndex:0] != 0 && !customStringInvalid)
	{
		customStringInvalid = YES;
		OOLog(logKey, @"'%@' array in descriptions.plist does not start at 0 - reverting to original system.", inputNumArray);
	}

	if (!customStringInvalid)
	{
		for (i = 0; i < [mutableNumArray count]; ++i)
		{
			numString = [NSString stringWithFormat:@"%u", [mutableNumArray oo_unsignedIntAtIndex:i]];
			textString = [stringArray oo_stringAtIndex:i];
			[stringArrayDict setObject:textString forKey:numString];
		}
		
		for (i = 0; i < [sortedNumArray count]; ++i)
		{
			if (inputNum < [sortedNumArray oo_unsignedIntAtIndex:i])  
			{
				numString = [NSString stringWithFormat:@"%u", [sortedNumArray oo_unsignedIntAtIndex:i-1]];
				if ([stringArrayDict objectForKey:numString] != nil)
				{
					return [stringArrayDict objectForKey:numString];
				}
				else
				{
					customStringInvalid = YES;
					OOLog(logKey, @"'nil' value returned when trying to display rating status - reverting to original system.");
					break;
				}
			}
		}
	}

	if (customStringInvalid)
	{
		if ([context isEqualToString:@"ratings"])
		{
			enum { kRatingCount = 9 };

			const unsigned	killThresholds[kRatingCount - 1] =
							{
								0x0008,
								0x0010,
								0x0020,
								0x0040,
								0x0080,
								0x0200,
								0x0A00,
								0x1900
							};

			NSString *eliteRating = [NSString stringWithUTF8String:"★★★ E L I T E ★★★"];
			NSString *deadlyRating = [NSString stringWithUTF8String:"☆ Deadly ☆"];
			stringArray = [NSArray arrayWithObjects:@"Harmless",@"Mostly Harmless",@"Poor",@"Average",@"Above Average",@"Competent",@"Dangerous",deadlyRating,eliteRating,nil];
			for (i = 0; i < kRatingCount - 1; ++i)
			{
				if (inputNum < killThresholds[i])  return [stringArray oo_stringAtIndex:i];
			}

			return [stringArray oo_stringAtIndex:kRatingCount - 1];
		}
		if ([context isEqualToString:@"legal_status"])
		{
			enum { kStatusCount = 3 };

			const int		statusThresholds[kStatusCount - 1] =
							{
								1,
								51
							};

			stringArray = [NSArray arrayWithObjects:@"Clean",@"Offender",@"Fugitive",nil];
			for (i = 0; i != kStatusCount - 1; ++i)
			{
				if (inputNum < statusThresholds[i])  return [stringArray oo_stringAtIndex:i];
			}

			return [stringArray oo_stringAtIndex:kStatusCount - 1];
		}
	}

	i = [sortedNumArray count] - 1;
	numString = [NSString stringWithFormat:@"%u", [sortedNumArray oo_unsignedIntAtIndex:i]];
	return [stringArrayDict objectForKey:numString];
}
Now, go to line 607 and replace the section/function there with the following:

Code: Select all

NSString *OODisplayRatingStringFromKillCount(unsigned kills)
{
	NSString *killsArrayKey = @"oolite_rating_kills";
	NSString *ratingsArrayKey = @"oolite_rating_names";
	NSString *contextType = @"ratings";
	
	return [NSString stringWithFormat:@"%@", OODisplayCustomStringFromDescriptionsArray(killsArrayKey, ratingsArrayKey, kills, contextType)];
}
Go down to line 624 and the replace the section/function there with the following:

Code: Select all

NSString *OODisplayStringFromLegalStatus(unsigned legalStatus)
{
	NSString *bountyArrayKey = @"oolite_legal_status_bounty";
	NSString *statusArrayKey = @"oolite_legal_status_names";
	NSString *contextType = @"legal_status";
	
	return [NSString stringWithFormat:@"%@", OODisplayCustomStringFromDescriptionsArray(bountyArrayKey, statusArrayKey, legalStatus, contextType)];
}
This takes care of the source files. Now open up the descriptions.plist file in the resources and insert the following four arrays:

Code: Select all

	"oolite_rating_kills" = 
	(
		0,
		8,
		15,
		32,
		64,
		128,
		512,
		2560,
		6400
	);
   
	"oolite_rating_names" = 
	(
		"Harmless",
		"Mostly Harmless",
		"Poor",
		"Average",
		"Above Average",
		"Competent",
		"Dangerous",
		"☆ Deadly ☆",
		"★★★ E L I T E ★★★"
	);
   
	"oolite_legal_status_bounty" =
	(
		0,
		1,
		51
	);
   
	"oolite_legal_status_names" =
	(
		"Clean",
		"Offender",
		"Fugitive"
	);
Finally, open up logcontrol.plist and add the following two lines:

Code: Select all

	new.ratings.error						= yes;
	new.legal.status.error					= yes;
This should now provide a fully customisable ratings and legal status system. Any errors will be picked up, logged accordingly and will revert to the original systems. The only thing these new systems are dependent on, is making sure that the numeric value that corresponds to the text value are at the same positions on the arrays. But numerical order is not required, and it doesn't matter if the numeric value is considered to be string or integer, as the code deals with this accordingly...

...Now, I'm hoping this takes care of everything, but I fear there's still something I've forgotten about (although I can't figure out what)...
Desktop PC: CPU: Intel i7-4790K Quad Core 4.4GHz (Turbo-Charged) GPU: Nvidia GeForce GTX 1080Ti RAM: 32GB DDR3

Laptop PC: CPU: Intel i5-10300H Quad Core 4.5GHz (Turbo-Charged) GPU: Nvidia GeForce GTX 1650 RAM: 32GB DDR4
User avatar
Pleb
---- E L I T E ----
---- E L I T E ----
Posts: 908
Joined: Sun Apr 29, 2012 2:23 pm
Location: United Kingdom

Re: Source Code and Ideas question

Post by Pleb »

I stayed up late last night, trying desperately to find a way to break this. Anything I could think of seemed to force the code to revert to the original coding, so effectively I think this might be the winning ticket! If anyone else wants to follow the instructions above and test this out in the trunk (you will need to be able to compile the game from the source) and can find a way of creating unwanted results, let me know. Otherwise I will be submitting this as a serious suggestion for the next release. :D
Desktop PC: CPU: Intel i7-4790K Quad Core 4.4GHz (Turbo-Charged) GPU: Nvidia GeForce GTX 1080Ti RAM: 32GB DDR3

Laptop PC: CPU: Intel i5-10300H Quad Core 4.5GHz (Turbo-Charged) GPU: Nvidia GeForce GTX 1650 RAM: 32GB DDR4
hangar18
Competent
Competent
Posts: 45
Joined: Sun Sep 04, 2011 9:10 am

Re: Source Code and Ideas question

Post by hangar18 »

Many thanks Pleb for your analysis...I'm afraid its too complex for me at this stage to use but I am keen to learn and grow because Oolite has so much potential. I still cant make an executable out of v1.77.1! I've downloaded the source code (as all attempts to use the git checkout 1.77.1 failed) and tried immediately to do a 'make debug = no', but got this response


This is a gnustep-make 2.4.0
Making all for Objc_program oolite....
Compiling ...
....
...
...
...
src/Core/OOOPenGLonly.h.61.22: Fatal error: GL/Glext.h: No such file or directory exists
Compilation terminated.
If I could just get past first base I'm sure things great things would follow...
User avatar
cim
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 4072
Joined: Fri Nov 11, 2011 6:19 pm

Re: Source Code and Ideas question

Post by cim »

hangar18 wrote:
src/Core/OOOPenGLonly.h.61.22: Fatal error: GL/Glext.h: No such file or directory exists
What OS is this on? It looks like you don't have the OpenGL development headers installed - a package called something like libgl-dev if you're on Linux. (On Windows it should be in the right place from the compiler environment that another_commander put together, and you really are in for a lot of preparatory work if you don't use that...)
another_commander
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 6681
Joined: Wed Feb 28, 2007 7:54 am

Re: Source Code and Ideas question

Post by another_commander »

hangar18 wrote:
src/Core/OOOPenGLonly.h.61.22: Fatal error: GL/Glext.h: No such file or directory exists
Compilation terminated.
GLext.h is included in the dependency headers for Windows, both for the x64 and the x86 variants. It looks like you did not execute a git submodule update --init after doing the git pull, or you did it and it failed for some reason. Make sure that all submodules have been downloaded successfully before you begin any attempt to build.
hangar18
Competent
Competent
Posts: 45
Joined: Sun Sep 04, 2011 9:10 am

Re: Source Code and Ideas question

Post by hangar18 »

I've tried both ways...

Method 1
Download the raw tar 1.77.1
Then run the make debug=no

Which failed as per my previous post

So I then tried

git submodule update --init (which also failed)

Method 2
Tried the original instructions (have skipped the bits about changing/making directories but trust me I did them)
git clone https://github.com/OoliteProject/oolite.git (ok so far)
git checkout 1.77.1 (ok again)
git checkout -b 1.77.1 (as there's a note to say you need to type the -b bit to get changes to stick)
git submodule update --init (ok)
<then I made changes to description file in config - simply changed "harmless" to "rookie" just to see if it would work>
make debug=no

...seemed to go ok until the end where I go the following messages

collect2.exe: error 1d returned 1 exit status
make[3] : *** [obj.win.spk/oolite.exe] Error 1
make[2] : *** [internal-objc_program-all_] Error 2
make[1] : *** [oolite.all.objc-program.variales] Error 2
*** [internal-all] Error 2
another_commander
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 6681
Joined: Wed Feb 28, 2007 7:54 am

Re: Source Code and Ideas question

Post by another_commander »

You are making life difficult for yourself. You have deviated from the original instructions in Method 2 by doing the checkouts to 1.77.1 I suggest you start from scratch one last time and follow the instructions in the Oolite-PC thread precisely and without missing a comma. Don't bother with 1.77.1 for now, make sure that the trunk builds and you can worry about 1.77.1 later.

Regarding the error message you are receiving, we need the part of the error just above the lines you quoted in order to be able to see what went wrong. Also, it is not "1d", it is "ld" (lower case letter 'L'). ld is the GNU linker, the program that takes all objects compiled and combines them in one executable format file. Your build fails in one of the final steps and the reason is that somehow it cannot find libraries that it needs. If you have followed the instructions these libraries will be already in their right place for the linker to locate them.

But in any case, if you just follow the instructions on how to build without taking initiatives and deviations or shortcuts, it builds.

Edit: It looks like the github source tarball of 1.77.1 does not contain the submodule files. That would explain the missing GLext.h issue. If you really must download the 1.77.1 source, it is still available with all its dependencies at Berlios' project download page. Still, I would recommend ensuring that you have a healthy trunk repository clone available if you want to play with the source.
another_commander
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 6681
Joined: Wed Feb 28, 2007 7:54 am

Re: Source Code and Ideas question

Post by another_commander »

What I think happened with the steps in Method 2 is this:
- You cloned the trunk repository. Latest trunk code arrived on your computer.
- You did a git checkout of the 1.77.1 tag. The source was reverted to what it was four-five months ago, at the time of 1.77.1 release.
- You did a submodule update with the parameter --init. This brings the latest version of the submodules which, as mentioned in the past, are separate subprojects. So now you have the source code of 1.77.1 with the resource and dependency files we are using for current trunk.
- You attempted a build. It failed because with the changes that have gone in in the space of five months, it is impossible for the new resources to be compatible with the old code. Just the transition to OpenAL is enough to make the old code totally incompatible. The linker errors you got could be related (but not restricted) to not being able to find the SDL_mixer library.
hangar18
Competent
Competent
Posts: 45
Joined: Sun Sep 04, 2011 9:10 am

Re: Source Code and Ideas question

Post by hangar18 »

Apologies, it wasn't my intention to miss steps or not follow instructions precisely...the reason I didn't want the 1.79 build is because planets were missing textures, so I assumed 1.79 being the bleeding edge, was bound to have a few bugs. I wanted a stable release but having so little knowledge of how the build thing works, guessed where and when to checkout 1.77.1. I'll try again from scratch and checkout 1.77.1 at the end. Sorry for being slow on the uptake.
another_commander
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 6681
Joined: Wed Feb 28, 2007 7:54 am

Re: Source Code and Ideas question

Post by another_commander »

No worries and no need to apologize for anything. The reason I am asking you to stick to 1.79 building for now is that, at least for that one, we have instructions that we know work. Anything outside those instructions can be considered uncharted territory. Once you have a healthy build environment and you are able to make changes to the executable, you can start experimenting with branches and other fancy stuff if you like, but it's best to get the basics right first. Also, if your code tweaks turn out to be something that is really cool and desired by the community, it will be much much easier for us to merge them if they are made against trunk rather than against 1.77.1 (see Pleb's spinning ship in status screen for a very recent example of what I am talking about).

Although trunk is definitely work in progress and can break from one moment to the next, I can tell you that at least at the revision we are currently in, it is quite stable and does not have planet texture problems (at least as far as I can tell). If you find that it does, a bug report with a way to reproduce the problem would be more than welcome.

Edit to add: While a git checkout of a branch does update all submodules to their correct revisions, it seems that a git checkout of a tag does not (and 1.77.1 is a tag). I would rather not do extensive experimentation with it because I don't want to bork my own source tree :-). Even if you try git checkout 1.77.1 at the end of the process, chances are that it will not switch the submodules to their 1.77.1 state. This is another reason why it would probably be best to stick to the trunk build for now.
hangar18
Competent
Competent
Posts: 45
Joined: Sun Sep 04, 2011 9:10 am

Re: Source Code and Ideas question

Post by hangar18 »

Thanks, appreciate your patience!
e
I tried to checkout 1.77.1 at the end of the process after changing the description plist but got an error: your local changes to the following files would be overwritten: (description.plist)

Please commit your changes or stash them before you can switch branches
Aborting

However, if I could get 1.79 to work properly, I'd be happy to use that instead. What I find is the planets aren't rendering properly. In 1.77.1 there is a gradual fade from light to dark across the planet based on the sun's position (which looks good). In 1.79, there is a light part or half of the planet, which unfortunately flickers, and then a line followed by a sudden dark part (no graduation of light to dark unlike 1.77.1). I then tried to copy the addons (OXPs) into the folder in the hope that the ones I had downloaded relating to nice planet textures would somehow fix the problem, but alas they did not. I know they do work in the normal 1.77.1 download executable

Note that the flickering/sudden light to dark problem happened before I copied any addons (or OXPs) into place. All I did was follow the 4 steps in your original post
Post Reply