瀏覽代碼

Net Packs BulkMoveArtifacts structure and BulkMoveArtifacts::applyCl

SoundSSGood 3 年之前
父節點
當前提交
95ab343116
共有 6 個文件被更改,包括 152 次插入17 次删除
  1. 1 0
      client/CPlayerInterface.cpp
  2. 22 0
      client/NetPacksClient.cpp
  3. 2 1
      lib/CArtHandler.h
  4. 4 1
      lib/NetPacks.h
  5. 113 15
      lib/NetPacksLib.cpp
  6. 10 0
      server/NetPacksServer.cpp

+ 1 - 0
client/CPlayerInterface.cpp

@@ -2591,6 +2591,7 @@ void CPlayerInterface::artifactMoved(const ArtifactLocation &src, const Artifact
 		if (artWin)
 			artWin->artifactMoved(src, dst);
 	}
+	GH.listInt.back()->redraw();
 	askToAssembleArtifact(dst);
 }
 

+ 22 - 0
client/NetPacksClient.cpp

@@ -279,6 +279,28 @@ void MoveArtifact::applyCl(CClient *cl)
 		callInterfaceIfPresent(cl, dst.owningPlayer(), &IGameEventsReceiver::artifactMoved, src, dst);
 }
 
+void BulkMoveArtifacts::applyCl(CClient * cl)
+{
+	auto & movingArts = artsPack0;
+	for (auto & slotToMove : movingArts.slots)
+	{
+		auto srcLoc = ArtifactLocation(movingArts.srcArtHolder, slotToMove.srcPos);
+		auto dstLoc = ArtifactLocation(movingArts.dstArtHolder, slotToMove.dstPos);
+		MoveArtifact(&srcLoc, &dstLoc).applyCl(cl);
+	}
+
+	if (artsPack1.has_value())
+	{
+		movingArts = artsPack1.value();
+		for (auto & slotToMove : movingArts.slots)
+		{
+			auto srcLoc = ArtifactLocation(movingArts.srcArtHolder, slotToMove.srcPos);
+			auto dstLoc = ArtifactLocation(movingArts.dstArtHolder, slotToMove.dstPos);
+			MoveArtifact(&srcLoc, &dstLoc).applyCl(cl);
+		}
+	}
+}
+
 void AssembledArtifact::applyCl(CClient *cl)
 {
 	callInterfaceIfPresent(cl, al.owningPlayer(), &IGameEventsReceiver::artifactAssembled, al);

+ 2 - 1
lib/CArtHandler.h

@@ -303,8 +303,9 @@ struct DLL_LINKAGE ArtSlotInfo
 	ui8 locked; //if locked, then artifact points to the combined artifact
 
 	ArtSlotInfo() : locked(false) {}
+	const CArtifactInstance * getArt() const;
 
-	template <typename Handler> void serialize(Handler &h, const int version)
+	template <typename Handler> void serialize(Handler & h, const int version)
 	{
 		h & artifact;
 		h & locked;

+ 4 - 1
lib/NetPacks.h

@@ -994,12 +994,15 @@ struct EraseArtifact : CArtifactOperationPack
 
 struct MoveArtifact : CArtifactOperationPack
 {
+	MoveArtifact() {}
+	MoveArtifact(ArtifactLocation * src, ArtifactLocation * dst) 
+		: src(*src), dst(*dst) {}
 	ArtifactLocation src, dst;
 
 	void applyCl(CClient *cl);
 	DLL_LINKAGE void applyGs(CGameState *gs);
 
-	template <typename Handler> void serialize(Handler &h, const int version)
+	template <typename Handler> void serialize(Handler & h, const int version)
 	{
 		h & src;
 		h & dst;

+ 113 - 15
lib/NetPacksLib.cpp

@@ -845,18 +845,11 @@ DLL_LINKAGE CBonusSystemNode *ArtifactLocation::getHolderNode()
 
 DLL_LINKAGE const CArtifactInstance *ArtifactLocation::getArt() const
 {
-	const ArtSlotInfo *s = getSlot();
-	if(s && s->artifact)
-	{
-		if(!s->locked)
-			return s->artifact;
-		else
-		{
-			logNetwork->warn("ArtifactLocation::getArt: This location is locked!");
-			return nullptr;
-		}
-	}
-	return nullptr;
+	auto s = getSlot();
+	if (s)
+		return s->getArt();
+	else
+		return nullptr;
 }
 
 DLL_LINKAGE const CArtifactSet * ArtifactLocation::getHolderArtSet() const
@@ -1093,13 +1086,13 @@ DLL_LINKAGE void EraseArtifact::applyGs(CGameState *gs)
 	al.removeArtifact();
 }
 
-DLL_LINKAGE void MoveArtifact::applyGs(CGameState *gs)
+DLL_LINKAGE void MoveArtifact::applyGs(CGameState * gs)
 {
-	CArtifactInstance *a = src.getArt();
+	CArtifactInstance * art = src.getArt();
 	if(dst.slot < GameConstants::BACKPACK_START)
 		assert(!dst.getArt());
 
-	a->move(src, dst);
+	art->move(src, dst);
 
 	//TODO what'll happen if Titan's thunder is equipped by pickin git up or the start of game?
 	if (a->artType->id == ArtifactID::TITANS_THUNDER && dst.slot == ArtifactPosition::RIGHT_HAND) //Titan's Thunder creates new spellbook on equip
@@ -1114,6 +1107,86 @@ DLL_LINKAGE void MoveArtifact::applyGs(CGameState *gs)
 	}
 }
 
+DLL_LINKAGE void BulkMoveArtifacts::applyGs(CGameState * gs)
+{
+	int numBackpackArtifactsMoved = 0;
+	if (artsPack1.has_value())
+	{
+		// Swap
+		auto & leftRightPack = artsPack0;
+		auto & rightLeftPack = artsPack1.value();
+		auto leftSet = leftRightPack.getSrcHolderArtSet();
+		auto rightSet = leftRightPack.getDstHolderArtSet();
+		CArtifactFittingSet ArtFittingSet(leftSet->bearerType());
+		std::vector<std::pair<ArtifactPosition, ArtSlotInfo>> unmovableArtsLeftHero, unmovableArtsRightHero;
+
+		// Keep unmovable artifacts separately until the swap
+		for (auto artPos : ArtifactUtils::unmovablePositions())
+		{
+			auto slotInfo = leftSet->getSlot(artPos);
+			if (slotInfo)
+			{
+				unmovableArtsLeftHero.push_back(std::make_pair(artPos, *slotInfo));
+				leftSet->eraseArtSlot(artPos);
+			}
+
+			slotInfo = rightSet->getSlot(artPos);
+			if (slotInfo)
+			{
+				unmovableArtsRightHero.push_back(std::make_pair(artPos, *slotInfo));
+				rightSet->eraseArtSlot(artPos);
+			}
+		}
+
+		ArtFittingSet.artifactsWorn = rightSet->artifactsWorn;
+		ArtFittingSet.artifactsInBackpack = rightSet->artifactsInBackpack;
+		rightSet->artifactsWorn = leftSet->artifactsWorn;
+		rightSet->artifactsInBackpack = leftSet->artifactsInBackpack;
+		leftSet->artifactsWorn = ArtFittingSet.artifactsWorn;
+		leftSet->artifactsInBackpack = ArtFittingSet.artifactsInBackpack;
+
+		// Return non movable artifacts to their place after the swap
+		for (auto & art : unmovableArtsLeftHero)
+		{
+			leftSet->putArtifact(art.first, art.second.artifact);
+		}
+		for (auto & art : unmovableArtsRightHero)
+		{
+			rightSet->putArtifact(art.first, art.second.artifact);
+		}
+	}
+	else
+	{
+		// Move
+		auto & artsPack = artsPack0;
+		for (auto & slot : artsPack.slots)
+		{
+			// When an object gets removed from the backpack, the backpack shrinks
+			// so all the following indices will be affected. Thus, we need to update
+			// the subsequent artifact slots to account for that
+			if (slot.srcPos >= GameConstants::BACKPACK_START)
+			{
+				slot.srcPos = ArtifactPosition(slot.srcPos.num - numBackpackArtifactsMoved);
+			}
+			auto srcSlotInfo = artsPack.getSrcHolderArtSet()->getSlot(slot.srcPos);
+			auto dstSlotInfo = artsPack.getDstHolderArtSet()->getSlot(slot.dstPos);
+
+			if (slot.dstPos < GameConstants::BACKPACK_START)
+				assert(!dstSlotInfo->getArt());
+			assert(srcSlotInfo);
+
+			auto art = srcSlotInfo->getArt();
+			const_cast<CArtifactInstance*>(art)->move(
+				ArtifactLocation(artsPack.srcArtHolder, slot.srcPos), ArtifactLocation(artsPack.dstArtHolder, slot.dstPos));
+
+			if (slot.srcPos >= GameConstants::BACKPACK_START)
+			{
+				numBackpackArtifactsMoved++;
+			}
+		}
+	}
+}
+
 DLL_LINKAGE void AssembledArtifact::applyGs(CGameState *gs)
 {
 	CArtifactSet *artSet = al.getHolderArtSet();
@@ -1712,4 +1785,29 @@ DLL_LINKAGE void EntitiesChanged::applyGs(CGameState * gs)
 		gs->updateEntity(change.metatype, change.entityIndex, change.data);
 }
 
+const CArtifactInstance * ArtSlotInfo::getArt() const
+{
+	if (artifact)
+	{
+		if (!locked)
+			return artifact;
+		else
+		{
+			logNetwork->warn("ArtifactLocation::getArt: This location is locked!");
+			return nullptr;
+		}
+	}
+	return nullptr;
+}
+
+CArtifactSet * BulkMoveArtifacts::HeroArtsToMove::getSrcHolderArtSet()
+{
+	return boost::apply_visitor(GetBase<CArtifactSet>(), srcArtHolder);
+}
+
+CArtifactSet * BulkMoveArtifacts::HeroArtsToMove::getDstHolderArtSet()
+{
+	return boost::apply_visitor(GetBase<CArtifactSet>(), dstArtHolder);
+}
+
 VCMI_LIB_NAMESPACE_END

+ 10 - 0
server/NetPacksServer.cpp

@@ -180,6 +180,16 @@ bool ExchangeArtifacts::applyGh(CGameHandler * gh)
 	return gh->moveArtifact(src, dst);
 }
 
+bool BulkExchangeArtifacts::applyGh(CGameHandler * gh)
+{
+	const CGHeroInstance * pSrcHero = gh->getHero(srcHero);
+	throwOnWrongPlayer(gh, pSrcHero->getOwner());
+	if (swap)
+		return gh->bulkSwapArtifacts(srcHero, dstHero);
+	else
+		return gh->bulkMoveArtifacts(srcHero, dstHero);
+}
+
 bool AssembleArtifacts::applyGh(CGameHandler * gh)
 {
 	throwOnWrongOwner(gh, heroID);