浏览代码

Merge pull request #3051 from Laserlicht/name_change

possibility to change name in lobby
Nordsoft91 2 年之前
父节点
当前提交
1ffc246c8b

+ 8 - 0
client/CServerHandler.cpp

@@ -465,6 +465,14 @@ void CServerHandler::setPlayer(PlayerColor color) const
 	sendLobbyPack(lsp);
 }
 
+void CServerHandler::setPlayerName(PlayerColor color, const std::string & name) const
+{
+	LobbySetPlayerName lspn;
+	lspn.color = color;
+	lspn.name = name;
+	sendLobbyPack(lspn);
+}
+
 void CServerHandler::setPlayerOption(ui8 what, int32_t value, PlayerColor player) const
 {
 	LobbyChangePlayerOption lcpo;

+ 2 - 0
client/CServerHandler.h

@@ -67,6 +67,7 @@ public:
 	virtual void setCampaignBonus(int bonusId) const = 0;
 	virtual void setMapInfo(std::shared_ptr<CMapInfo> to, std::shared_ptr<CMapGenOptions> mapGenOpts = {}) const = 0;
 	virtual void setPlayer(PlayerColor color) const = 0;
+	virtual void setPlayerName(PlayerColor color, const std::string & name) const = 0;
 	virtual void setPlayerOption(ui8 what, int32_t value, PlayerColor player) const = 0;
 	virtual void setDifficulty(int to) const = 0;
 	virtual void setTurnTimerInfo(const TurnTimerInfo &) const = 0;
@@ -152,6 +153,7 @@ public:
 	void setCampaignBonus(int bonusId) const override;
 	void setMapInfo(std::shared_ptr<CMapInfo> to, std::shared_ptr<CMapGenOptions> mapGenOpts = {}) const override;
 	void setPlayer(PlayerColor color) const override;
+	void setPlayerName(PlayerColor color, const std::string & name) const override;
 	void setPlayerOption(ui8 what, int32_t value, PlayerColor player) const override;
 	void setDifficulty(int to) const override;
 	void setTurnTimerInfo(const TurnTimerInfo &) const override;

+ 47 - 2
client/lobby/OptionsTab.cpp

@@ -1041,9 +1041,11 @@ void OptionsTab::SelectedBox::scrollBy(int distance)
 }
 
 OptionsTab::PlayerOptionsEntry::PlayerOptionsEntry(const PlayerSettings & S, const OptionsTab & parent)
-	: pi(std::make_unique<PlayerInfo>(SEL->getPlayerInfo(S.color)))
+	: CIntObject(LCLICK | KEYBOARD | TEXTINPUT)
+	, pi(std::make_unique<PlayerInfo>(SEL->getPlayerInfo(S.color)))
 	, s(std::make_unique<PlayerSettings>(S))
 	, parentTab(parent)
+	, name(S.name)
 {
 	OBJ_CONSTRUCTION;
 	defActions |= SHARE_POS;
@@ -1081,7 +1083,13 @@ OptionsTab::PlayerOptionsEntry::PlayerOptionsEntry(const PlayerSettings & S, con
 	}};
 
 	background = std::make_shared<CPicture>(ImagePath::builtin(bgs[s->color]), 0, 0);
-	labelPlayerName = std::make_shared<CLabel>(55, 10, EFonts::FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, s->name);
+	if(s->isControlledByAI() || CSH->isGuest())
+		labelPlayerName = std::make_shared<CLabel>(55, 10, EFonts::FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, name);
+	else
+	{
+		labelPlayerNameEdit = std::make_shared<CTextInput>(Rect(6, 3, 95, 15), EFonts::FONT_SMALL, nullptr, false);
+		labelPlayerNameEdit->setText(name);
+	}
 	labelWhoCanPlay = std::make_shared<CMultiLineLabel>(Rect(6, 23, 45, (int)graphics->fonts[EFonts::FONT_TINY]->getLineHeight()*2), EFonts::FONT_TINY, ETextAlignment::CENTER, Colors::WHITE, CGI->generaltexth->arraytxt[206 + whoCanPlay]);
 
 	if(SEL->screenType == ESelectionScreen::newGame)
@@ -1115,6 +1123,43 @@ OptionsTab::PlayerOptionsEntry::PlayerOptionsEntry(const PlayerSettings & S, con
 	bonus = std::make_shared<SelectedBox>(Point(271, 2), *s, BONUS);
 }
 
+bool OptionsTab::PlayerOptionsEntry::captureThisKey(EShortcut key)
+{
+	return labelPlayerNameEdit && labelPlayerNameEdit->hasFocus() && key == EShortcut::GLOBAL_ACCEPT;
+}
+
+void OptionsTab::PlayerOptionsEntry::keyPressed(EShortcut key)
+{
+	if(labelPlayerNameEdit && key == EShortcut::GLOBAL_ACCEPT)
+		updateName();
+}
+
+bool OptionsTab::PlayerOptionsEntry::receiveEvent(const Point & position, int eventType) const
+{
+	return eventType == AEventsReceiver::LCLICK; // capture all left clicks (not only within control)
+}
+
+void OptionsTab::PlayerOptionsEntry::clickReleased(const Point & cursorPosition)
+{
+	if(labelPlayerNameEdit && !labelPlayerNameEdit->pos.isInside(cursorPosition))
+		updateName();
+}
+
+void OptionsTab::PlayerOptionsEntry::updateName() {
+	if(labelPlayerNameEdit->getText() != name)
+	{
+		CSH->setPlayerName(s->color, labelPlayerNameEdit->getText());
+		if(CSH->isMyColor(s->color))
+		{
+			Settings set = settings.write["general"]["playerName"];
+			set->String() = labelPlayerNameEdit->getText();
+		}
+	}
+
+	labelPlayerNameEdit->removeFocus();
+	name = labelPlayerNameEdit->getText();
+}
+
 void OptionsTab::onSetPlayerClicked(const PlayerSettings & ps) const
 {
 	if(ps.isControlledByAI() || humanPlayers > 0)

+ 8 - 0
client/lobby/OptionsTab.h

@@ -167,9 +167,11 @@ private:
 
 	struct PlayerOptionsEntry : public CIntObject
 	{
+		std::string name;
 		std::unique_ptr<PlayerInfo> pi;
 		std::unique_ptr<PlayerSettings> s;
 		std::shared_ptr<CLabel> labelPlayerName;
+		std::shared_ptr<CTextInput> labelPlayerNameEdit;
 		std::shared_ptr<CMultiLineLabel> labelWhoCanPlay;
 		std::shared_ptr<CPicture> background;
 		std::shared_ptr<CButton> buttonTownLeft;
@@ -186,8 +188,14 @@ private:
 
 		PlayerOptionsEntry(const PlayerSettings & S, const OptionsTab & parentTab);
 		void hideUnavailableButtons();
+		bool captureThisKey(EShortcut key) override;
+		void keyPressed(EShortcut key) override;
+		void clickReleased(const Point & cursorPosition) override;
+		bool receiveEvent(const Point & position, int eventType) const override;
 
 	private:
 		const OptionsTab & parentTab;
+
+		void updateName();
 	};
 };

+ 15 - 2
client/widgets/TextControls.cpp

@@ -532,7 +532,7 @@ Point CGStatusBar::getBorderSize()
 	return Point();
 }
 
-CTextInput::CTextInput(const Rect & Pos, EFonts font, const CFunctionList<void(const std::string &)> & CB)
+CTextInput::CTextInput(const Rect & Pos, EFonts font, const CFunctionList<void(const std::string &)> & CB, bool giveFocusToInput)
 	: CLabel(Pos.x, Pos.y, font, ETextAlignment::CENTER),
 	cb(CB),
 	CFocusable(std::make_shared<CKeyboardFocusListener>(this))
@@ -544,7 +544,8 @@ CTextInput::CTextInput(const Rect & Pos, EFonts font, const CFunctionList<void(c
 	addUsedEvents(LCLICK | SHOW_POPUP | KEYBOARD | TEXTINPUT);
 
 #if !defined(VCMI_MOBILE)
-	giveFocus();
+	if(giveFocusToInput)
+		giveFocus();
 #endif
 }
 
@@ -805,3 +806,15 @@ void CFocusable::moveFocus()
 		}
 	}
 }
+
+void CFocusable::removeFocus()
+{
+	if(this == inputWithFocus)
+	{
+		focus = false;
+		focusListener->focusLost();
+		redraw();
+
+		inputWithFocus = nullptr;
+	}
+}

+ 2 - 1
client/widgets/TextControls.h

@@ -184,6 +184,7 @@ public:
 
 	void giveFocus(); //captures focus
 	void moveFocus(); //moves focus to next active control (may be used for tab switching)
+	void removeFocus(); //remove focus
 	bool hasFocus() const;
 
 	static std::list<CFocusable *> focusables; //all existing objs
@@ -224,7 +225,7 @@ public:
 	void setText(const std::string & nText, bool callCb);
 	void setHelpText(const std::string &);
 
-	CTextInput(const Rect & Pos, EFonts font, const CFunctionList<void(const std::string &)> & CB);
+	CTextInput(const Rect & Pos, EFonts font, const CFunctionList<void(const std::string &)> & CB, bool giveFocusToInput = true);
 	CTextInput(const Rect & Pos, const Point & bgOffset, const ImagePath & bgName, const CFunctionList<void(const std::string &)> & CB);
 	CTextInput(const Rect & Pos, std::shared_ptr<IImage> srf);
 

+ 1 - 0
lib/NetPackVisitor.h

@@ -159,6 +159,7 @@ public:
 	virtual void visitLobbySetCampaignBonus(LobbySetCampaignBonus & pack) {}
 	virtual void visitLobbyChangePlayerOption(LobbyChangePlayerOption & pack) {}
 	virtual void visitLobbySetPlayer(LobbySetPlayer & pack) {}
+	virtual void visitLobbySetPlayerName(LobbySetPlayerName & pack) {}
 	virtual void visitLobbySetSimturns(LobbySetSimturns & pack) {}
 	virtual void visitLobbySetTurnTime(LobbySetTurnTime & pack) {}
 	virtual void visitLobbySetDifficulty(LobbySetDifficulty & pack) {}

+ 5 - 0
lib/NetPacksLib.cpp

@@ -755,6 +755,11 @@ void LobbySetPlayer::visitTyped(ICPackVisitor & visitor)
 	visitor.visitLobbySetPlayer(*this);
 }
 
+void LobbySetPlayerName::visitTyped(ICPackVisitor & visitor)
+{
+	visitor.visitLobbySetPlayerName(*this);
+}
+
 void LobbySetSimturns::visitTyped(ICPackVisitor & visitor)
 {
 	visitor.visitLobbySetSimturns(*this);

+ 14 - 0
lib/NetPacksLobby.h

@@ -250,6 +250,20 @@ struct DLL_LINKAGE LobbySetPlayer : public CLobbyPackToServer
 	}
 };
 
+struct DLL_LINKAGE LobbySetPlayerName : public CLobbyPackToServer
+{
+	PlayerColor color = PlayerColor::CANNOT_DETERMINE;
+	std::string name = "";
+
+	virtual void visitTyped(ICPackVisitor & visitor) override;
+
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & color;
+		h & name;
+	}
+};
+
 struct DLL_LINKAGE LobbySetSimturns : public CLobbyPackToServer
 {
 	SimturnsInfo simturnsInfo;

+ 1 - 0
lib/registerTypes/RegisterTypes.h

@@ -399,6 +399,7 @@ void registerTypesLobbyPacks(Serializer &s)
 	s.template registerType<CLobbyPackToServer, LobbySetCampaignMap>();
 	s.template registerType<CLobbyPackToServer, LobbySetCampaignBonus>();
 	s.template registerType<CLobbyPackToServer, LobbySetPlayer>();
+	s.template registerType<CLobbyPackToServer, LobbySetPlayerName>();
 	s.template registerType<CLobbyPackToServer, LobbySetTurnTime>();
 	s.template registerType<CLobbyPackToServer, LobbySetSimturns>();
 	s.template registerType<CLobbyPackToServer, LobbySetDifficulty>();

+ 19 - 0
server/CVCMIServer.cpp

@@ -835,6 +835,25 @@ void CVCMIServer::setPlayer(PlayerColor clickedColor)
 	}
 }
 
+void CVCMIServer::setPlayerName(PlayerColor color, std::string name)
+{
+	if(color == PlayerColor::CANNOT_DETERMINE)
+		return;
+
+	PlayerSettings & player = si->playerInfos.at(color);
+
+	if(!player.isControlledByHuman())
+		return;
+
+	if(player.connectedPlayerIDs.empty())
+		return;
+
+	int nameID = *(player.connectedPlayerIDs.begin()); //if not AI - set appropiate ID
+
+	playerNames[nameID].name = name;
+	setPlayerConnectedId(player, nameID);
+}
+
 void CVCMIServer::optionNextCastle(PlayerColor player, int dir)
 {
 	PlayerSettings & s = si->playerInfos[player];

+ 1 - 0
server/CVCMIServer.h

@@ -107,6 +107,7 @@ public:
 
 	// Work with LobbyInfo
 	void setPlayer(PlayerColor clickedColor);
+	void setPlayerName(PlayerColor player, std::string name);
 	void optionNextHero(PlayerColor player, int dir); //dir == -1 or +1
 	void optionSetHero(PlayerColor player, HeroTypeID id);
 	HeroTypeID nextAllowedHero(PlayerColor player, HeroTypeID id, int direction);

+ 1 - 0
server/LobbyNetPackVisitors.h

@@ -86,6 +86,7 @@ public:
 	virtual void visitLobbyChangeHost(LobbyChangeHost & pack) override;
 	virtual void visitLobbyChangePlayerOption(LobbyChangePlayerOption & pack) override;
 	virtual void visitLobbySetPlayer(LobbySetPlayer & pack) override;
+	virtual void visitLobbySetPlayerName(LobbySetPlayerName & pack) override;
 	virtual void visitLobbySetTurnTime(LobbySetTurnTime & pack) override;
 	virtual void visitLobbySetSimturns(LobbySetSimturns & pack) override;
 	virtual void visitLobbySetDifficulty(LobbySetDifficulty & pack) override;

+ 6 - 0
server/NetPacksLobbyServer.cpp

@@ -397,6 +397,12 @@ void ApplyOnServerNetPackVisitor::visitLobbySetPlayer(LobbySetPlayer & pack)
 	result = true;
 }
 
+void ApplyOnServerNetPackVisitor::visitLobbySetPlayerName(LobbySetPlayerName & pack)
+{
+	srv.setPlayerName(pack.color, pack.name);
+	result = true;
+}
+
 void ApplyOnServerNetPackVisitor::visitLobbySetSimturns(LobbySetSimturns & pack)
 {
 	srv.si->simturnsInfo = pack.simturnsInfo;