Creating an NRaas project Attn C# Devs: Traveler

Talk nerdy to us here.
User avatar
JunJayMdM
Reactions:
Posts: 262
Joined: April 2nd, 2012, 6:00 pm

Attn C# Devs: Traveler

Post by JunJayMdM » February 9th, 2014, 2:02 am

Might as well create one for Traveler too where we can discuss about it.

@Chain I sent you an email, not sure if you got it, so I'm asking here. I need to know what you're working on right now, as I have changes planned for the FutureDescendantServiceEx class, regarding those annoying llama maxis notifications spamming all over the place. So I was wondering if that was ok or you're currently working on that class so I better wait for a new version before I apply changes to it.

User avatar
Chain_Reaction
Site Admin
Reactions:
Posts: 7613
Joined: December 30th, 2011, 6:00 pm
Answers: 81
Contact:

Post by Chain_Reaction » February 9th, 2014, 2:26 am

Didn't get the email so good thing you posted. If you sent it to the gmail it's not an account I monitor.

I am working in that area but you can go ahead and push your changes and release if you like. I'm not sure when I'll finish. :)

User avatar
JunJayMdM
Reactions:
Posts: 262
Joined: April 2nd, 2012, 6:00 pm

Post by JunJayMdM » February 9th, 2014, 2:30 am

Yeah I think it was that one on GitHub, I figured you weren't monitoring it. I'm going ahead then :)

User avatar
JunJayMdM
Reactions:
Posts: 262
Joined: April 2nd, 2012, 6:00 pm

Post by JunJayMdM » February 12th, 2014, 6:46 am

It's taking more than I expected, mainly because I expected the Listeners to be added at startup when the service instance is created, but apparently that's not the case. The most logical solution I can think of is to entirely replace the instance (much like the Singleton replacement for interactions) with a new class.

So, I'll be exploring that path, also try to understand the deep meaning behind EA adding 4 listeners that invoke the following delegate method when the 4 events occur :

<!-- ws:start:WikiTextCodeRule:0:
<pre class="text"> private ListenerAction OnHouseholdUpdateEvent(Event e)<br/> {<br/> return ListenerAction.Keep;<br/> }</pre>
-->
<style type="text/css"><!--
/**
* GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann
* (http://qbnz.com/highlighter/ and http://geshi.org/)
*/
.text {font-family:monospace;}
.text .imp {font-weight: bold; color: red;}
.text span.xtra { display:block; }

-->
</style><pre class="text"> private ListenerAction OnHouseholdUpdateEvent(Event e)
{
return ListenerAction.Keep;
}</pre>


That, to me, is the best way to waste resources, unless there really is a deep meaning behind it....

User avatar
Chain_Reaction
Site Admin
Reactions:
Posts: 7613
Joined: December 30th, 2011, 6:00 pm
Answers: 81
Contact:

Post by Chain_Reaction » February 12th, 2014, 4:46 pm

Hmm. Are you sure they aren't added when the class is initialized? Cause we have:

<!-- ws:start:WikiTextCodeRule:0:
<pre class="text"> private void OnStartup()<br/> {<br/> this.InitializeFutureDescendantService();<br/> }</pre>
-->
<style type="text/css"><!--
/**
* GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann
* (http://qbnz.com/highlighter/ and http://geshi.org/)
*/
.text {font-family:monospace;}
.text .imp {font-weight: bold; color: red;}
.text span.xtra { display:block; }

-->
</style><pre class="text"> private void OnStartup()
{
this.InitializeFutureDescendantService();
}</pre>


then

<!-- ws:start:WikiTextCodeRule:1:
<pre class="text">public void InitializeFutureDescendantService()<br/> {<br/> if (sPersistableData == null)<br/> {<br/> sPersistableData = new FutureDescendantServicePersistableData();<br/> }<br/> this.InitializeHouseholdEventListeners();<br/> }</pre>
-->
<style type="text/css"><!--
/**
* GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann
* (http://qbnz.com/highlighter/ and http://geshi.org/)
*/
.text {font-family:monospace;}
.text .imp {font-weight: bold; color: red;}
.text span.xtra { display:block; }

-->
</style><pre class="text">public void InitializeFutureDescendantService()
{
if (sPersistableData == null)
{
sPersistableData = new FutureDescendantServicePersistableData();
}
this.InitializeHouseholdEventListeners();
}</pre>


so I assumed that as well. Once they have been added they are stored in mEventListeners which can be cleared by calling CleanupEventListeners.

Technically you should be able to clear them then add your own to that list. Were you planning on making the notices optional?

As for the 4 that seem pointless, I was looking at that myself. I assume EA just never got around to implementing those. They don't seem to serve any other purpose than being a waste, I agree. Anything that should be handled there is done so when the descendant households are checked at future world loadup... well except for condition testing of if the Sim somehow vanished from the household so it doesn't error out but hey, EA has no time for that. :)

User avatar
JunJayMdM
Reactions:
Posts: 262
Joined: April 2nd, 2012, 6:00 pm

Post by JunJayMdM » February 12th, 2014, 6:21 pm

That's the funny part : I can't find anywhere in the code where OnStartup() is being used, nor CreateInstance(). In addition, InitializeFutureDescendantService() is called again separately, so even if I replace them on startup, the old ones will still be added back whenever you're switching Households or moving them, unless I also intercept when that happens.

So I thought, since everytime the service is initialized, the instance is retrieved with GetInstance(), the simpler thing to do would be overriding that one with a class that has a new InitializeHouseholdEventListeners() that adds my Listeners instead, which have the notification thing cut out. This is why not finding where CreateInstance() is called is also a problem

User avatar
Chain_Reaction
Site Admin
Reactions:
Posts: 7613
Joined: December 30th, 2011, 6:00 pm
Answers: 81
Contact:

Post by Chain_Reaction » February 12th, 2014, 6:48 pm

CreateInstance is an internal method called on all classes by the script core when classes are initialized. OnStartup is as well but it is called whenever the world is loading for each class. EA calls it themselves in CreateInstance as well though because you can create instances statically and obviously OnStartup wouldn't run in such case. There's a lot of those auto called internal methods.

Where do you see the EA listeners are readded if you switch households or move?

User avatar
JunJayMdM
Reactions:
Posts: 262
Joined: April 2nd, 2012, 6:00 pm

Post by JunJayMdM » February 12th, 2014, 7:22 pm

In 3 classes (one being an interaction), plus some of Twallan's included in Common, with the following usage :

<!-- ws:start:WikiTextCodeRule:0:
<pre class="text"> FutureDescendantService instance = FutureDescendantService.GetInstance();<br/> if (instance != null)<br/> {<br/> instance.CleanUpFutureDescendantService(true);<br/> instance.InitializeFutureDescendantService();<br/> }</pre>
-->
<style type="text/css"><!--
/**
* GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann
* (http://qbnz.com/highlighter/ and http://geshi.org/)
*/
.text {font-family:monospace;}
.text .imp {font-weight: bold; color: red;}
.text span.xtra { display:block; }

-->
</style><pre class="text"> FutureDescendantService instance = FutureDescendantService.GetInstance();
if (instance != null)
{
instance.CleanUpFutureDescendantService(true);
instance.InitializeFutureDescendantService();
}</pre>


NRaas.CommonSpace.Helpers.DreamCatcher.Task+PrepareToBecomeActiveHousehold
NRaas.TravelerSpace.Options.TestDescendantScoringSetting+Run

Sims3.Gameplay.CAS.Household+PrepareToBecomeActiveHousehold
Sims3.Gameplay.GameStates+SetupPostMoveData
Sims3.Gameplay.Objects.Miscellaneous.TimePortal.ResetTimeContinuum+ResetTheFuture

There may be other NRaas mods using it, cos I don't have all of them loaded in ILSpy.

The interaction can be overriden and that's not a problem, but what about SetupPostMoveData() ? Also, by modyfing the DreamCatcher thing, since it's in Common, how many mods does it affect? It sounds like a huge work just to get rid of EA's dumb thinking.

BTW That OnStartup() is not called externally, it's marked private, nor is CreateInstance(), unless they're using Reflection to invoke them, which would explain why ILSpy can't tell me where they're called from

User avatar
Chain_Reaction
Site Admin
Reactions:
Posts: 7613
Joined: December 30th, 2011, 6:00 pm
Answers: 81
Contact:

Post by Chain_Reaction » February 12th, 2014, 9:00 pm

Nooooo. I just lost my reply. :( This wiki software. I have no words. On to retyping...

I have no idea how the magic methods work, just that the script core is aware to call them should they exist. I haven't been able to find the code for them so I assume it exists in the mystery that is Sims3Common.dll. We have to remember Twallan's mods work by exploiting the mono interpreter allowing private methods to be called publically so I'm sure EA's own engine has little regard for the scope.

As for replacing the instance... that sound sticky indeed and probably not worth the effort. What about clearing EA's listeners at start up then listening for kMovedHouses to catch the move event and reapply? As for the active household being changed... there has to be a way to catch that I am missing?

User avatar
JunJayMdM
Reactions:
Posts: 262
Joined: April 2nd, 2012, 6:00 pm

Post by JunJayMdM » February 12th, 2014, 9:45 pm

Through years of experience with boards, I got the habit of copying whatever I typed before hitting the button. That's of course good unless there's a crash or something, but better than nothing :)

You have no idea how much I'd love to put my hands on that Sims3.Common.dll, I dream about it every night...

About the possible solutions, I thought about the one you suggested, but there's one catch. Twallan almost certainly knows how it works, but personally I'm not familiar with the whole household switching/moving/splitting/merging process, so I'm not sure when those methods will be called.

Some idea hit me though. Let's say those 4 apparently useless Listeners do have a deep meaning. Not their function per se, but let's say they're "reminders". The service is initialized whenever those 4 events happen and they're there to serve some "magic". Because, if they were reminders, one could argue "ok, use comments, not actual resource-wasting stuff". But suppose that's actually what they're there for, reminding or serving a purpose, I guess it could be worth a try? Still, we wouldn't know when exactly the service will be initialized, if that's what happens.

Just for the sake of it, I'm throwing here the first idea I had, an alarm that checks when those Listeners have been added and they get replaced. The downside is that it should be a 1 minute alarm but that's too heavy, and if it's 10 minutes, then there's no guarantee the notifications will not slip through

Post Reply