What is the difference between and the calling sequence (related to each other) of
APlayerController::Possess()
APlayerController::AcknowledgePossession()
APlayerController::SetPawn()
What function should I prefer to use (override), to trigger something once the player controller possessed a pawn?
SetPawn() will be called internally, when you call Possess(). In 4.22, Possess() is marked virtual final, you should override OnPossess() to do your specific job, but you can still call OnPossess() to change your controlled pawn, then OnPossess() will be automatically called.
Possess() only runs on server, the same as OnPossess(). So in clients, you should override AcknowledgePossession() to do a similar job in OnPossess(), it will be called when server change controlled pawn.
Related
I Have a variable that updates every time i move my cube in the level blueprint , now i want to access this variable from multiple class blueprints , what do I do , I tried casting to gamestate but didn't succeed , I am really new to ue4 if you could explain in details please
edit: sorry for not adding details ,
The var I want to access is an integer named cube_side that tells me what side the cube is on every time I move , all of this happens in the level bp , I want to access this variable to see what side the cube is on from other class blueprints ->
here are some details in a picture
I know it's not good to code everything in the level blueprint , but it's too late now , I only need to transfer the var cube_side to other class blueprints so the other object can change depending what side the cube is on.
Create an Actor Class for your logic/functionality. Then use Get all actors of class (choose your class) -> Get a copy -> get variable
Communication with the level blueprint is rather tricky in UE4, since they are not as persistent as e.g. the GameMode, and therefore shouldn't be accessed directly (Imagine older games like Final Fantasy where a new level was loaded every time you stepped outside a boundary, so relying on it could potentially break your actors or crash the game due to nullptrs).
It's a little hacky, but works:
Move the variable inside the cube-blueprint. Add an event dispatcher to the cube, if it is moved, call it and pass the variable in.
Select the cube in the editor, open the level blueprint, right-click, "add reference to selected actor" (the cube must be part of a blueprintclass, not only a static mesh dragged in, though), and bind the event dispatcher inside the Level BP.
Create a function inside every blueprint that needs access to the variable, which does whatever it should do, depending on the variable.
The custom event of the Level Bp (that was bound to the Event Dispatcher of the cube), needs references to all actors that have to work, when the variable changes and call each Actors function (you can get the references like you got the one from the cube)
Then, every time the variable changes, the Level BP is notified, the custom Event is executed and this custom event calls all the actor's functions.
Event Dispatchers explained
This is a huge wastage of functions/code, since you only need it for this one level and may never use it again. Avoid this in the future, by not relying on the level BP so much.
You can use GameStateBP to create and store all variables that you need in game, in GameModeBP create functions to get and set this variables via Get Game State function and then function Cast To GameState and then logic. After that from any blueprint access it using Get Game Mode -> Cast to you GameMode -> use your function to set or get data from GameState.
I have a console app that will create an instance of a class and execute a method on it, and that's really all it does (but this method may do a lot of things). The class is determined at runtime based on command line args, and this is registered to Autofac so it can be correctly resolved, supplying class-specific constructor parameters extracted from the command line. All this works.
Now, I need to impose a system-wide limit to the number of instances per class that can be running at any one time. I will probably use a simple SQL database to keep track of number of allowed and running instances per class, and I have no problem with the SQL side of things.
But how do I actually impose this limit in a nice manner using Autofac?
I am thinking that I would have some "slot service" that would do something like this:
Try to reserve a new instance "slot".
If no more slots, log a message and terminate the process.
If slot successfully reserved, create instance and return it.
My idea is also to free the instance's slot in the class' Dispose method, preferably by using another method on the slot service.
How would I fit this into Autofac?
One possibility would be to register the class I want to instantiate with a lambda/delegate that does the above steps. But in that case, how do I "terminate"? Throw an exception? That would require some code to catch the exception and either log it or simply ignore it before terminating the process. I don't like it. I'd like the entire slot reservation stuff inside the delegate, lambda or service.
Another solution might be to do the slot reservation outside of Autofac, but that also seems somewhat messy.
I would prefer a solution where the "slot service" itself can be nicely unit tested, i.e. non-static and with an interface, and preferably resolved with Autofac.
I'm sure I'm missing something obvious here... Any suggestions?
This is my "best bet" so far:
static void Main(string[] args)
{
ReadCommandLine(args, out Type itemClass, out Type paramsClass, out Type paramsInterface, out object parameters);
BuildContainer(itemClass, paramsClass, paramsInterface, parameters);
IInstanceHandler ih = Container.Resolve<IInstanceHandler>();
if (ih.RegisterInstance(itemClass, out long instanceid))
{
try
{
Container.Resolve<IItem>().Execute();
}
finally
{
ih.UnregisterInstance(itemClass, instanceid);
}
}
}
I've got a base class I'm using with MSpec which provides convenience methods around AutoMock:
public abstract class SubjectBuilderContext
{
static AutoMock _container;
protected static ISubjectBuilderConfigurationContext<T> BuildSubject<T>()
{
_container = AutoMock.GetLoose();
return new SubjectBuilderConfigurationContext<T>(_container);
}
protected static Mock<TDouble> GetMock<TDouble>()
where TDouble : class
{
return _container.Mock<TDouble>();
}
}
Occasionally, I'm seeing an exception happen when attempting to retrieve a Mock like so:
It should_store_the_receipt = () => GetMock<IFileService>().Verify(f => f.SaveFileAsync(Moq.It.IsAny<byte[]>(), Moq.It.IsAny<string>()), Times.Once());
Here's the exception:
System.ObjectDisposedExceptionInstances cannot be resolved and nested
lifetimes cannot be created from this LifetimeScope as it has already
been disposed.
I'm guessing it has something to do with the way MSpec runs the tests (via reflection) and that there's a period of time when nothing actively has references to any of the objects in the underlying lifetime scope being used by AutoMock which causes the lifetimescope to get disposed. What's going on here, and is there some simple way for me to keep it from happening?
The AutoMock lifetime scope from Autofac.Extras.Moq is disposed when the mock itself is disposed. If you're getting this, it means the AutoMock instance has been disposed or has otherwise lost scope and the GC has cleaned it up.
Given that, there are a few possibilities.
The first possibility is that you've got some potential threading challenges around async method calls. Looking at the method that's being mocked, I see you're verifying the call to a SaveFileAsync method. However, I don't see any async related code in there, and I'm not entirely sure when/how the tests running are calling it given the currently posted code, but if there is a situation where an async call causes the test to run on one thread while the AutoMock loses scope or otherwise gets killed on the other thread, I could see this happening.
The second possibility is the mix of static and instance items in the context. You are storing the AutoMock as a static, but it appears the context class in which it resides is a base class that is intended to supply instance-related values. If two tests run in parallel, for example, the first test will set the AutoMock to what it thinks it needs, then the second test will overwrite the AutoMock and the first will go out of scope, disposing the scope.
The third possibility is multiple calls to BuildSubject<T> in one test. The call to BuildSubject<T> initializes the AutoMock. If you call that multiple times in one test, despite changing the T type, you'll be stomping the AutoMock each time and the associated lifetime scope will be disposed.
The fourth possibility is a test ordering problem. If you only see it sometimes but not other times, it could be that certain tests inadvertently assume that some setup, like the call to BuildSubject<T>, has already been done; while other tests may not make that assumption and will call BuildSubject<T> themselves. Depending on the order the tests run, you may sometimes get lucky and not see the exception, but other times you may run into the problem where BuildSubject<T> gets called at just the wrong time and causes you pain.
I am trying to construct a workflow that can be assigned to arbitrary containers and will have the following behavior. When the container makes the transition from state A -> A', the contents of the container should be checked for their state and moved to a new state that depends on their present state. In other words:
obj1: in state 'a' would be transitioned to 'a*'
obj2: in state 'b' would be transitioned to 'b*'
and so on...
obj1 and obj2 are following the same workflow that branches to a number of final states (approved, denied, alternate, etc...)
I know how to do this, if I can trigger my python code as trusted code. Unfortunately, I have not been able to figure out how or where to put the code in my product so this will work. I have found references to using "external methods", however that seems to be going away. Also I want the code to reside in my project.
I think this is probably simple and I am overlooking something. Help with how to put this in my project or another route to achieving the same goal would be welcome.
The scripts support for DCWorkflow only supports through-the-web-addable objects, which limits you to External Methods there.
A better bet is to use workflow events instead. For each workflow transition, two events are fired:
Products.DCWorkflow.interfaces.IAfterTransitionEvent
Products.DCWorkflow.interfaces.IBeforeTransitionEvent
If you subscribe to either of those events, you can then filter on the correct workflow and transistion to react to transitions from trusted code.
Each event fired has the following attributes:
object: the workflowed object
workflow: the current applicable workflow object
old_state: a Products.DCWorkflow.States.StateDefinition object
new_state: another Products.DCWorkflow.States.StateDefinition object
transition: a Products.DCWorkflow.Transititions.TransitionDefinition object
status: a dictionary with the current workflow variables
kwargs: a dictionary of extra arguments passed in to the change-transition call.
Register a subscriber using ZCML:
<subscriber
provides="zope.component.testfiles.adapter.IS"
factory=".youreventsmodule.aftertransition_handler"
for="Products.DCWorkflow.interfaces.IAfterTransitionEvent"
/>
or, because the transition events are object events, listen only to the transition event if it applies to your objects:
<subscriber
provides="zope.component.testfiles.adapter.IS"
factory=".youreventsmodule.container_aftertransition_handler"
for=".interfaces.IMyContainerType
Products.DCWorkflow.interfaces.IAfterTransitionEvent"
/>
which registers your handler only for transition events on objects with the IMyContainerType interface only.
The handler would be:
def aftertransition_handler(event):
# handle all transition events, ever
or, when limiting it to one object interface:
def aftertransition_handler(obj, event):
# handle all transition events for our container interface
I've been going through the documentation for creating Prism applications and setting up the Shell seems to be split into 2 methods, CreateShell() and InitializeShell()
For CreateShell I simply have:
protected override DependencyObject CreateShell()
{
return ServiceLocator.Current.GetInstance<Shell>();
}
The documentation says that code is needed in the IntializeShell() method to ensure it is ready to be displayed. The following is given as an example:
protected override void InitializeShell()
{
Application.Current.MainWindow = (Window)this.Shell;
Application.Current.MainWindow.Show();
}
I have noticed however that if I omit the first line and just call the Show() method it seems to work (MainWindow already appears to have Shell assigned to it). Can you tell me why this is the case, and why we still need to explicity set the MainWindow property here?
Also as I did not specifically register Shell to an interface within the container, how is it able to resolve Shell in CreateShell()?
Question 1: Why does just calling Show() seem to work and why is Application.Current.MainWindow seem to be populated?
There are a few things you should check here. In a typical WPF application, the type for the main window can be specified in the App.xaml. If it is specified, WPF will instantiate one of those for you. This is not desirable because WPF won't use your container to instantiate your shell and any dependencies won't be resolved.
When you run that first line of code in InitializeShell, you'd be replacing the WPF-instantiated Shell object with the one you manually instantiated.
I looked at the code for the MEF and Unity bootstrappers and I don't see anywhere that MainWindow is being set, but I don't know if you might have customized the base bootstrappers, so that's something else to look for.
Show() works because you are simply showing the window you instantiated and the WPF-instantiated one isn't shown. This is my theory, but without seeing your code, it'd be tough to say for sure.
Question 2: How can Unity resolve something that hasn't been registered?
Unity can always resolve a concrete type, regardless of registration. It cannot resolve non-concrete classes that haven't been mapped to a concrete type. This is why Resolve<Shell> works, but Resolve<IMyInterface> doesn't unless you register a type.