So I have just started working on a new project in Unreal which is intended to be a simple networked multiplayer game. What I have done so far is make a Weapon class that handles the spawning of projectiles, and give the player character an instance of a weapon on BeginPlay.
The weapon class is simple, but the problem that I am having is that the Server RPC I have for spawning projectiles is not being called from clients, only servers.
Here is how I am calling this RPC:
The Player Character has an OnFire method, that is bound to an input action.
This then calls the Fire method on the current weapon that the player has.
// Bind fire event
PlayerInputComponent->BindAction("Fire", IE_Pressed, this, &AMultiplayerFPSCharacter::OnFire);
...
void AMultiplayerFPSCharacter::OnFire()
{
// Call our weapon's fire method
if (CurrentWeapon)
{
CurrentWeapon->Fire(GetControlRotation());
}
}
Now, the weapon's Fire method simply calls the Server RPC to actually handle spawning the projectiles.
void AWeapon::Fire(const FRotator SpawnRotation)
{
UE_LOG(LogTemp, Warning, TEXT("LOCAL Fire"));
Server_Fire(SpawnRotation);
}
void AWeapon::Server_Fire_Implementation(const FRotator SpawnRotation)
{
UE_LOG(LogTemp, Warning, TEXT("SERVER RPC: Called RPC"));
// try and fire a projectile
if (ProjectileClass != NULL)
{
// Spawn Projectile
....
}
}
I also have the validation method for the Server RPC, which simply returns true for this so I can make sure it actually works.
This implementation is all fine and good on the server or Listen-Server, but when I call it from the client I only get the local Fire method on the Weapon. The client never even calls the server RPC.
One work around that I think I have found is to make the Player Character's OnFire method a Server RPC as well, but this feels like it is not the best way to go about doing this.
Could anyone explain why this is happening?
A client can only call a server RPC on a net-owned actor. For example, a client net-owns his PlayerController, so you can add a RPC to that, and call it. If you call it on a server-owned object, like I'm assuming your AWeapon actor is, the log will show something like "can't call RPC on non-owned object".
Related
I am attempting to fake a transfer between two QTcpSockets that happen to be in the same class (which is a googletest fixture). The focus of this is to see if I can send multiple messages between the two and properly extract them again. However, it seems that the two sockets won't connect. Most of the posts I've seen that relate to this don't come up with a working answer, and being as this is definitely not the intended means of use, I'm not sure that there is a simple one.
What I have for setting up the connection:
class TTest : public ::testing::Test, public QObject
{
//Q_OBJECT
protected:
QTcpServer qserv;
QTcpSocket qtcpsock1; //send
QTcpSocket *qtcpsock2; //rcv
TTest() : qserv(this), qtcpsock1(this)
{
while (!qserv.isListening())
{
qserv.listen();
}
qtcpsock1.connectToHost(QHostAddress::LocalHost, qserv.serverPort());
qtcpsock2 = qserv.nextPendingConnection();
qtcpsock1.waitForConnected();
if (!qtcpsock2) std::cout << "socket 2 not initialized\n";
qserv.close();
}
}
Signals/slots currently not in use.
The problem with this is that the event polling loop of the application will not run, so no events will be handled and your function calls will simply not work without it.
In short, the waitForConnected() call will wait for an event that never happens.
The natural solution with Qt is of course to use signals and slots, and let the normal application event loop run.
On a slightly related note: If you want internal communication within the same process consider something other than (heavy and complex) TCP sockets. Simple message queues? Anonymous pipes? Plain strings or arrays?
I have a version hit check right after my application gets start.
But when simulator is loading its sending the request and all that stuff. After my application starts it give version hit value NULL but after I close the application and open it again it gives the correct value.
1) My Question is that Why is this behavior occurring and what should I do that app starts and version check gives correct value at first attempt!
2) And the app is even not executed by user why its line of codes are executed?????
public MyScreen() {
Bitmap bitmap = Bitmap.getBitmapResource("background.png");
this.getMainManager().setBackground(
BackgroundFactory.createBitmapBackground(bitmap));
synchronized (Application.getEventLock())
{
UiApplication.getUiApplication().invokeLater(new Runnable()
{
public void run()
{
Status.show("Please Wait...", Bitmap.getPredefinedBitmap(Bitmap.INFORMATION), 1000);
LoginScreen();
}
});
}
Now what does it do is that it shows only the background screen and nothing happens no service but when I start it again it works. Whats the problem? Thanks
If your MyScreen class is actually a kind of Screen (through inheritance), then there's no need for you to synchronize on the event lock in this case. The constructor for a Screen will already be called on the UI thread, so, just simplify your code to:
public MyScreen() {
Bitmap bitmap = Bitmap.getBitmapResource("background.png");
this.getMainManager().setBackground(
BackgroundFactory.createBitmapBackground(bitmap));
UiApplication.getUiApplication().invokeLater(new Runnable()
{
public void run()
{
Status.show("Please Wait...", Bitmap.getPredefinedBitmap(Bitmap.INFORMATION), 1000);
LoginScreen();
}
});
Also, you might be able to get rid of the invokeLater() call, too, leaving you with this:
public MyScreen() {
Bitmap bitmap = Bitmap.getBitmapResource("background.png");
this.getMainManager().setBackground(
BackgroundFactory.createBitmapBackground(bitmap));
Status.show("Please Wait...", Bitmap.getPredefinedBitmap(Bitmap.INFORMATION), 1000);
LoginScreen();
You would normally use invokeLater() if you just wanted to safely initiate the code inside its run() method from a background thread, or if you wanted to queue it to be run after the constructor finishes.
But, if you're ready for it to happen right away, and you were just using that call to ensure that
Status.show("Please Wait...", Bitmap.getPredefinedBitmap(Bitmap.INFORMATION), 1000);
LoginScreen();
was run on the UI thread, then there's no need for that, because as I said, you're already on the UI thread in the MyScreen constructor.
But, I also can't see what you do at the end of your MyScreen constructor, so it's possible that using invokeLater() is appropriate.
Post some more information in response to my comment above, and I'll try to help with more.
A quick overview of what's happening: I am trying to do a GET request using Qt's QNetworkAccessManager, but the callback function on my QObject::connect(..) function is not being called. My questions is can I call QObject::connect from one object, but connect to a slot of another object (given that I have a pointer to both the object and the slot) - See below for more details.
My ultimate goal is to POST the data (seeing as it's a login function), I had POST Request code that was ultimately suffering from the same issue - callback function not being called. So I would like to be able to do a simple GET request first, once I have that, I think I'll be fine on my own from there.
I currently have a QMainWindow LoginWindow, with a button that calls a slot doLogin() in the LoginWindow class. This all works as you would expect. LoginWindow also has a public slots function called loginResponse(QNetworkReply* response).
//---LoginWindow.h
...
public slots:
void doLogin();
void loginResponse(QNetworkReply* response)
...
//---LoginWindow.cpp
LoginWindow::LoginWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::LoginWindow)
{
ui->setupUi(this);
ui->username_le->setFocus();
}
void LoginWindow::doLogin()
{
MyProduct::Network network(this);
qDebug() << "Logging in...";
//Here I call network.login from LoginWindow and pass
//references to the Slot I want to use and the LoginWindow itself
network.login(
ui->username_le->text(), //username
ui->password_le->text(), //password
this, //reference to this object (LoginWindow*)
SLOT(loginResponse(QNetworkReply*)) //loginResponse slot
);
}
void LoginWindow::loginResponse(QNetworkReply* response)
{
qDebug() << "Log in complete";
}
Next I have another class, under the MyProduct namespace, called Network. As you can see above, Network has a function called login. Here it is:
void MyProduct::Network login(QString username, QString password, QObject *receiver, const char *slot)
{
QNetworkRequest request(QUrl(API_ROOT + LOGIN_PATH)); //"http://localhost/basic/login.php"
request.setHeader(QNetworkRequest::ContentTypeHeader,"application/x-www-form-urlencoded");
//nam = QNetworkAccessManager* declared in the constructor
QObject::connect(nam,SIGNAL(finished(QNetworkReply*)), receiver, slot);
qDebug() << "Posting login data...";
nam->get(request);
}
The goal here is to create a login function in my Network class that can be used and connected in any number of windows (as users may log in from multiple places). But I'm getting no response - LoginWindow::loginResponse is not run.
I see "Logging in..." and "Posting login data" output in the console, but not "Log in complete".
Can anyone please point me in the right direction or tell me I'm crazy or that this is a bad idea?
Thanks in advance!
Note that QNetworkAccessManager operates asynchronously. The get() method does not block while the network operation occurs; it returns immediately. (See the Detailed Description section of the documentation for more info.)
This is pretty typical of Qt's network-related APIs, because you usually don't want your application to freeze while waiting for data to move across a network.
What this means is what your instance, nam, isn't alive long enough for the GET request to actually finish. Your instance of the Product::Network class is deleted immediately after the call to login() because it's allocated on the stack. Although I can't see the code, I'm guessing it cleans up the QNetworkAccessManager as well.
If you extend the lifetime of your network object, you may find that your slot will eventually be invoked.
Also, this is more a matter of preference, but I think it would be cleaner to avoid passing a receiver and a slot to your login() function. I'd recommend declaring your own signals in the Network class as part of its API, and to connect to those in the LoginWindow class.
I'm using OpalVoip for making a softphone application and i got stuck with following:
void MyManager::main()
{
//variables
PNotifier notify; // this is the problem
//it is the template PNotifierFunctionTemplate<INT>
//more stuff
listener->Open(notify);
//listener is of type OpalListenerUDP
//it should start the listener and wait for incoming connection
//but however i need to pass this NOTIFY which should be the INT parameter to the
//new OpalTransport instance created by the listener...
//however OpalListenerUDP only creates OpalTransport after the connection is
//accepted as so in following: OpalListenerUDP::Accept(/*time interval*/)
//
//So far I think that this notifier should be a pointer to an object of type
//OpalListenerUDP but i have no idea how to get it done
}
Any help will be appreciated, Red.
After deeper research into opal source code, I've found the solution.
It turns out that
OpalConnection::StartListener(OpalListener&);
Will do the job of opening listener, so there is no need of calling OpalListener::Open() so after it is only needed to call OpalListener::Accept to accept a connection.
I am designing a little game for my own fun's and training's sake. The real identity of the game being quite irrelevant for my actual question, suppose it's the Mastermind game (which it actually is :)
My real goal here is to have an interface IPlayer which will be used for any player: computer or human, console or gui, local or network. I am also intending to have a GameController, which will deal with just two IPlayers.
the IPlayer interface would look something like this:
class IPlayer
{
public:
//dtor
virtual ~IPlayer()
{
}
//call this function before the game starts. In subclasses,
//the overriders can, for example, generate and store the combination.
virtual void PrepareForNewGame() = 0;
//make the current guess
virtual Combination MakeAGuess() = 0;
//return false if lie is detected.
virtual bool ProcessResult(Combination const &, Result const &) = 0;
//Answer to opponent's guess
virtual Result AnswerToOpponentsGuess(Combination const&) = 0;
};
The GameController class would do something like this:
IPlayer* pPlayer1 = PlayerFactory::CreateHumanPlayer();
IPlayer* pPlayer1 = PlayerFactory::CreateCPUPlayer();
pPlayer1->PrepareForNewGame();
pPlayer2->PrepareForNewGame();
while(no_winner)
{
Guess g = pPlayer1->MakeAguess();
Result r = pPlayer2->AnswerToOpponentsGuess(g);
bool player2HasLied = ! pPlayer1->ProcessResult(g, r);
etc.
etc.
}
By this design, I am willing to make GameController class immutable, that is, I stuff the just game rules in it, and nothing else, so since the game itself is established, this class shouldn't change. For a console game this design would work perfectly. I would have HumanPlayer, which in its MakeAGuess method would read a Combination from the standard input, and a CPUPlayer, which would somehow randomly generate it etc.
Now here's my problem: The IPlayer interface, along with the GameController class, are synchronous in their nature. I can't imagine how I would implement the GUI variant of the game with the same GameController when the MakeAGuess method of GUIHumanPlayer would have to wait for, for example, some mouse movements and clicks. Of course, I could launch a new thread which would wait for user input, while the main thread would block, so as to imitate synchronous IO, but somehow this idea disgusts me. Or, alternatively, I could design both the controller and player to be asynchronous. In this case, for a console game, I would have to imitate asynchronousness, which seems easier than the first version.
Would you kindly comment on my design and my concerns about choosing synchronous or asynchronous design? Also, I am feeling that I put more responsibility on the player class than GameController class. Etc, etc.
Thank you very much in advance.
P.S. I don't like the title of my question. Feel free to edit it :)
Instead of using return values of the various IPlayer methods, consider introducing an observer class for IPlayer objects, like this:
class IPlayerObserver
{
public:
virtual ~IPlayerObserver() { }
virtual void guessMade( Combination c ) = 0;
// ...
};
class IPlayer
{
public:
virtual ~IPlayer() { }
virtual void setObserver( IPlayerObserver *observer ) = 0;
// ...
};
The methods of IPlayer should then call the appropriate methods of an installed IPlayerObserver instead of returning a value, as in:
void HumanPlayer::makeAGuess() {
// get input from human
Combination c;
c = ...;
m_observer->guessMade( c );
}
Your GameController class could then implement IPlayerObserver so that it gets notified whenever a player did something interesting, like - making a guess.
With this design, it's perfectly fine if all the IPlayer methods are asynchronous. In fact, it's to be expected - they all return void!. Your game controller calls makeAGuess on the active player (this might compute the result immediately, or it might do some network IO for multiplayer games, or it would wait for the GUI to do something) and whenever the player did his choice, the game controller can rest assured that the guessMade method will be called. Furthemore, the player objects still don't know anything about the game controller. They are just dealing with an opaque 'IPlayerObserver' interface.
The only thing making this different for the GUI as compared to the console is that your GUI is event driven. Those events take place on the GUI thread, and therefore, if you host the Game code on the GUI thread, you have a problem: Your call to have the player make a move blocks the GUI thread, and this means you can't get any events until that call returns. [EDIT: Inserted the following sentence.] But the call can't return until it gets the event. So you're deadlocked.
That problem would go away if you simply host the game code on another thread. You'd still need to synchronize the threads, so MakeAGuess() doesn't return until ready, but it's certainly doable.
If you want to keep everything single-threaded you may want to consider a different model. Game could notify Players it's their turn with an event but leave it to players to initiate operations on the Game.