(Feat) Add mulitplayer
This commit is contained in:
@@ -67,6 +67,8 @@ public:
|
||||
|
||||
virtual void InitializeComponent() override;
|
||||
|
||||
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
|
||||
|
||||
/**
|
||||
* Ajoute des objets, en remplissant d'abord les piles entamees.
|
||||
* @param RemainingUses charges de l'exemplaire ajoute ; -1 signifie "plein".
|
||||
@@ -274,11 +276,89 @@ protected:
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Inventaire|Barre rapide", meta = (ClampMin = "0"))
|
||||
int32 HotbarSlotCount = 10;
|
||||
|
||||
/** Toujours dimensionne a GetTotalSlotCount(). */
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Inventaire")
|
||||
/**
|
||||
* Toujours dimensionne a GetTotalSlotCount().
|
||||
*
|
||||
* Replique a TOUT LE MONDE et non au seul proprietaire, pour deux raisons.
|
||||
*
|
||||
* Technique d'abord : les conditions de GetLifetimeReplicatedProps sont
|
||||
* mises en cache par CLASSE, pas par instance. Un COND_OwnerOnly viserait
|
||||
* donc aussi le composant d'un coffre -- or un coffre n'appartient a aucune
|
||||
* connexion, et sa grille n'arriverait chez personne. Le meme composant sert
|
||||
* le sac et le contenant, c'est une decision d'architecture qu'on ne veut pas
|
||||
* defaire pour un drapeau de replication.
|
||||
*
|
||||
* De fond ensuite : les coffres sont a acces simultane, donc leur contenu
|
||||
* DOIT arriver a tous ceux qui l'ouvrent. Et voir le sac d'un coequipier n'a
|
||||
* rien d'un probleme dans une coop entre amis sans anti-triche -- c'est meme
|
||||
* ce qui rendra un futur echange d'objets gratuit.
|
||||
*
|
||||
* Cout reel : 4 joueurs x 30 slots de trois champs, envoyes uniquement quand
|
||||
* ils changent, et delta-compresses. Negligeable.
|
||||
*/
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, ReplicatedUsing = OnRep_Slots, Category = "Inventaire")
|
||||
TArray<FInventorySlot> Slots;
|
||||
|
||||
/**
|
||||
* Le contenu vient d'arriver du serveur : on rediffuse le delegue habituel.
|
||||
*
|
||||
* C'est LA ligne qui recable toute l'interface d'un coup. Grille, barre
|
||||
* rapide, panneau de detail et coffres sont deja abonnes a
|
||||
* OnInventoryChanged et ne font aucun Tick -- ils n'ont donc pas une seule
|
||||
* ligne a changer pour devenir reseau.
|
||||
*/
|
||||
UFUNCTION()
|
||||
void OnRep_Slots();
|
||||
|
||||
private:
|
||||
// ------------------------------------------------------------------
|
||||
// Reseau
|
||||
//
|
||||
// Le routage vit DANS les fonctions publiques et non chez leurs appelants :
|
||||
// une case d'inventaire appelle MoveItem() sans savoir si elle tourne chez
|
||||
// l'hote ou chez un client, et c'est tres bien ainsi. Ajouter le test
|
||||
// d'autorite dans chaque widget serait dix occasions de l'oublier.
|
||||
//
|
||||
// Pas de prediction locale : le client envoie et attend OnRep_Slots. Sur un
|
||||
// relais Steam l'aller-retour est de quelques dizaines de millisecondes,
|
||||
// invisible pour un glisser-deposer -- alors qu'une prediction fausse
|
||||
// donnerait une pile qui saute, symptome bien plus desagreable.
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
/** Ce composant peut-il modifier son contenu ici et maintenant. */
|
||||
bool HasInventoryAuthority() const;
|
||||
|
||||
/**
|
||||
* Par quel composant faire transiter une RPC serveur.
|
||||
*
|
||||
* Renvoie celui des deux qui appartient au pawn du joueur LOCAL : un coffre
|
||||
* n'appartient a aucune connexion, et une RPC emise depuis lui serait
|
||||
* silencieusement jetee par le moteur. C'est le piege numero un des
|
||||
* transferts vers un conteneur.
|
||||
*/
|
||||
static UInventoryComponent* FindNetProxy(UInventoryComponent* A, UInventoryComponent* B);
|
||||
|
||||
UFUNCTION(Server, Reliable)
|
||||
void Server_TransferSlot(UInventoryComponent* From, int32 FromIndex, UInventoryComponent* To, int32 ToIndex, int32 Quantity);
|
||||
|
||||
UFUNCTION(Server, Reliable)
|
||||
void Server_QuickTransferSlot(UInventoryComponent* From, int32 FromIndex, UInventoryComponent* To);
|
||||
|
||||
/**
|
||||
* From est passe explicitement et n'est PAS "this" cote serveur : la RPC
|
||||
* transite par l'inventaire du joueur local, qui peut tres bien etre la
|
||||
* DESTINATION -- c'est le cas du bouton "Tout prendre" d'un coffre. Deduire
|
||||
* la source du recepteur viderait le sac du joueur dans lui-meme.
|
||||
*/
|
||||
UFUNCTION(Server, Reliable)
|
||||
void Server_TransferAllTo(UInventoryComponent* From, UInventoryComponent* To, int32 FirstIndex);
|
||||
|
||||
UFUNCTION(Server, Reliable)
|
||||
void Server_ConsumeUse(int32 SlotIndex);
|
||||
|
||||
/** Les regles de deplacement, une fois l'autorite acquise. */
|
||||
static bool ApplyTransferSlot(UInventoryComponent* From, int32 FromIndex, UInventoryComponent* To, int32 ToIndex, int32 Quantity);
|
||||
|
||||
/** Redimensionne le tableau si la taille cible a change. */
|
||||
void EnsureSlotCount();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user