J'ai un jeu en ligne où les joueurs peuvent façonner le monde d'une manière ou d'une autre - par exemple. Le logement d'Ultima Online, où vous pouvez construire vos maisons directement sur certaines parties de la carte du monde. Ce sont des changements qui devraient persister au fil du temps dans le cadre d'un monde persistant.
Dans le même temps, l'équipe de conception ajoute du nouveau contenu et modifie l'ancien contenu pour améliorer et étendre le jeu aux nouveaux joueurs. Ils le feront d'abord sur un serveur de développement pendant les tests et devront ensuite fusionner leur travail avec le "travail" des joueurs sur le serveur en direct.
En supposant que nous résolvions les problèmes de conception de jeu - par exemple. les joueurs ne peuvent construire que dans des zones désignées, de sorte qu'ils ne se heurtent jamais géographiquement aux modifications du concepteur - quelles sont les bonnes façons de gérer les données ou d'organiser les structures de données afin d'éviter les conflits lorsque de nouvelles données de concepteur sont fusionnées avec de nouvelles données de joueur?
Exemple 1: un joueur fabrique un nouveau type d'objet et le jeu lui attribue l'ID 123456. Les instances de cet élément se réfèrent toutes à 123456. Imaginons maintenant que les concepteurs de jeux aient un système similaire et qu'un concepteur crée un nouvel élément également numéroté 123456. Comment éviter cela?
Exemple 2: quelqu'un crée un mod populaire qui donne à tous vos dragons un accent français. Il comprend un script avec un nouvel objet appelé assignFrenchAccent
qu'ils utilisent pour attribuer les nouveaux actifs vocaux à chaque objet dragon. Mais vous êtes sur le point de déployer votre DLC "Napoleon vs Smaug" qui a un objet du même nom - comment pouvez-vous le faire sans beaucoup de problèmes de service client?
J'ai pensé aux stratégies suivantes:
- Vous pouvez utiliser 2 fichiers / répertoires / bases de données distincts, mais vos opérations de lecture sont alors considérablement compliquées. "Afficher tous les éléments" doit effectuer une lecture sur la base de données du concepteur et une lecture sur la base de données du lecteur (et doit toujours faire la distinction entre les 2, d'une manière ou d'une autre.)
- Vous pouvez utiliser 2 espaces de noms différents dans un même magasin, par exemple. utiliser des chaînes comme clé primaire et les préfixer avec "DESIGN:" ou "PLAYER:", mais la création de ces espaces de noms peut être non triviale et les dépendances ne sont pas claires. (par exemple. Dans un SGBDR, il se peut que vous ne puissiez pas utiliser efficacement des chaînes comme clés primaires. Vous pouvez utiliser des entiers et allouer toutes les clés primaires en dessous d'un certain nombre, par exemple 1 million, pour être des données de concepteur, et tout ce qui est au-dessus de ce point doit être Mais ces informations sont invisibles pour le SGBDR et les liens de clé étrangère traverseront le «fossé», ce qui signifie que tous les outils et scripts doivent explicitement contourner ce problème.)
- Vous pouvez toujours travailler sur la même base de données partagée en temps réel, mais les performances peuvent être médiocres et le risque de dommages aux données du joueur peut être amélioré. Il ne s'étend pas non plus aux jeux qui s'exécutent sur plus d'un serveur avec des données mondiales différentes.
- ... d'autres idées?
Il me semble que même si c'est principalement un problème pour les jeux en ligne, les concepts peuvent également s'appliquer au modding, où la communauté crée des mods en même temps que les développeurs corrigent leur jeu. Des stratégies sont-elles utilisées ici pour réduire les risques de rupture de mod lorsque de nouveaux correctifs sortent?
J'ai également étiqueté cela comme "contrôle de version" car à un niveau c'est ce que c'est - 2 branches de développement de données qui doivent être fusionnées. Peut-être que certaines idées pourraient venir de cette direction.
EDIT - quelques exemples ajoutés ci-dessus pour aider à clarifier le problème. Je commence à penser que le problème est vraiment celui de l'espace de noms, qui pourrait être implémenté dans un magasin via des clés composites. Cela simplifie au moins la stratégie de fusion. Mais il y a peut-être des alternatives que je ne vois pas.
la source
Réponses:
Je pense que les réponses proposant des solutions DB sautent sur une implémentation spécifique sans comprendre le problème. Les bases de données ne facilitent pas les fusions, elles vous fournissent simplement un cadre dans lequel stocker vos données. Un conflit est toujours un conflit même s'il se trouve dans une base de données. Et la vérification est la solution d'un pauvre homme au problème - cela fonctionnera, mais à un coût paralysant pour votre facilité d'utilisation.
Ce dont vous parlez ici tombe dans le modèle de développement distribué du problème. La première étape, je crois, n'est pas de considérer les joueurs et les concepteurs comme des types distincts de créateurs de contenu. Cela supprime une dimension artificielle à votre problème qui n'affecte pas la solution.
En fait, vous avez votre ligne principale - la version canonique approuvée par les développeurs. Vous pouvez (probablement) également avoir d'autres branches - des serveurs en direct où les gens développent et partagent activement des mods. Le contenu peut être ajouté sur n'importe quelle branche. Surtout, vos concepteurs n'ont rien de spécial ici - ce ne sont que des créateurs de contenu qui vivent en interne (et vous pouvez aller les trouver et les frapper quand ils bousillent).
Accepter le contenu généré par l'utilisateur est alors un problème de fusion standard. Vous devez soit ramener leurs modifications sur la ligne principale, fusionner, puis repousser, ou tirer les modifications de la ligne principale sur leur branche et fusionner (en laissant la ligne principale «propre» des éléments générés par l'utilisateur). Comme d'habitude, tirer vers votre branche et y remédier est plus convivial que de demander à d'autres personnes de retirer vos modifications, puis d'essayer de le réparer à distance de leur côté.
Une fois que vous travaillez avec ce type de modèle, tous les processus normaux pour éviter les conflits de fusion s'appliquent. Certains des plus évidents:
la source
Stockez tout en tant qu'attribut (ou décorateur) - avec des points de montage. Prenons l'exemple d'une maison conçue par le joueur:
Ainsi, chaque entité peut avoir un ou plusieurs points de montage - chaque point de montage peut accepter zéro ou plusieurs autres composants. Ces données seraient stockées avec la version dans laquelle elles ont été enregistrées, ainsi que toutes les propriétés pertinentes (telles que le déplacement, etc. dans mon exemple) - NoSQL ferait probablement un très bon ajustement ici (clé = ID d'entité, valeur = binaire sérialisé Les données).
Chaque composant devrait alors pouvoir «mettre à niveau» les anciennes données d'une version précédente (ne jamais supprimer les champs des données sérialisées - juste les «annuler») - cette mise à niveau se produit la minute où elle est chargée (elle serait ensuite immédiatement stockée dans la dernière version disponible). Disons que notre maison a vu ses dimensions changées. Le code de mise à niveau déterminerait relativement la distance entre les murs nord et sud et modifierait proportionnellement les déplacements de toutes les entités contenues. Comme autre exemple, notre bol de viande pourrait avoir le champ «Aliments» supprimé, et obtenir à la place une «Variété» (Viande) et une «Recette» (Boulettes). Le script de mise à niveau transformerait «Boulettes de viande» en «Viande», «Boules». Chaque composant doit également savoir comment gérer les modifications apportées aux points de montage - par exemple
Tout cela laisse exactement un problème ouvert: que se passe-t-il si deux objets se heurtent (pas leur conteneur - les points de montage vous protègent de cela)? Après une mise à niveau, vous devez vérifier les collisions et tenter de les résoudre (en séparant les choses, un peu comme SAT). Si vous ne savez pas comment résoudre la collision, retirez l'un des objets et placez-le dans une cachette - où ils peuvent acheter ces articles supprimés (gratuitement) ou les vendre (au prix fort); et informez évidemment le joueur que la mise à niveau a cassé une partie de sa mise en page - éventuellement avec une fonction de «zoom avant» afin qu'il puisse voir le problème.
En fin de compte, vous devriez laisser des changements complexes dans les mains des joueurs (échouer rapidement) car aucun algorithme ne peut rendre compte de l'esthétique - vous devriez simplement être en mesure de donner au joueur un contexte sur l'emplacement de l'élément (afin qu'ils puissent se souvenir, pas seulement atterrir avec tous ces articles dans leur cachette et ne pas savoir où ils étaient).
la source
J'essaie d'associer cela à quelque chose que je comprends, donc je pense en termes de Minecraft en ce moment. J'imagine un serveur en direct avec des joueurs apportant des modifications en temps réel pendant que les développeurs s'exécutent sur un serveur de test fixant / créant du nouveau contenu.
Votre question ressemble presque à 2 questions uniques:
J'essaierais de résoudre # 1 grâce à un système de référencement temporaire. Par exemple, lorsqu'un nouvel objet est créé par quelqu'un, il peut être marqué comme volatile ou temporaire. J'imagine que tout nouveau contenu créé sur le serveur de test serait marqué volatile (bien qu'il puisse également faire référence à du contenu non volatile).
Lorsque vous êtes prêt à apporter du nouveau contenu au serveur en direct, votre processus d'importation trouve les objets volatils et leur attribue des ID d'objet de serveur en direct qui sont définis dans la pierre. C'est différent d'une importation / fusion directe car vous devez pouvoir référencer des objets non volatils existants si vous avez besoin de les corriger ou de les mettre à jour.
Pour # 2, il semble que vous ayez vraiment besoin d'avoir un certain niveau de transmutation de script intermédiaire qui peut hacher le nom de la fonction dans un espace de noms unique. c'est à dire
Devient
la source
Si les fichiers des données sont du texte par opposition au binaire et que les concepteurs et les joueurs modifient différentes zones, vous pouvez essayer une fusion SVN.
la source
Je pense qu'une base de données / système de fichiers répliqué à travers des environnements avec une procédure de «check-out» serait le meilleur.
Ainsi, chaque fois qu'un concepteur souhaite apporter des modifications au monde, il extrait / verrouille tous les actifs qu'il souhaite créer / modifier sur toutes les copies de la base de données (développement et production), donc aucun autre joueur ou concepteur ne peut le modifier . Il travaillerait ensuite sur la base de données de développement jusqu'à ce que la nouvelle conception soit terminée, et à ce moment-là, les modifications seraient fusionnées avec la base de données de production et ces actifs seraient archivés / déverrouillés dans tous les environnements.
Les éditions des joueurs fonctionneraient de la même manière, sauf que les rôles de base de données / système de fichiers seraient inversés - ils fonctionnent sur la base de données de production, et toutes les mises à jour sont téléchargées vers dev une fois terminées.
Le verrouillage des actifs peut être limité aux propriétés pour lesquelles vous ne souhaitez garantir aucun conflit: dans l'exemple 1, vous verrouillez
ID 123456
dès que le joueur commence à le créer, de sorte que les développeurs ne se verront pas attribuer cet ID. Dans l'exemple 2, vos développeurs auraient verrouillé le nom du scriptassignFrenchAccent
pendant le développement, donc le joueur devrait choisir un nom différent lors du développement de sa modification (cette petite nuisance peut être réduite par l'espace de noms, mais cela en soi n'évitera pas les conflits à moins que vous ne donniez chacun utilisateur / développeur un espace de noms spécifique, puis vous aurez le même problème avec la gestion des espaces de noms). Cela signifie que tout développement devrait lire à partir d'une seule base de données en ligne, mais tout ce dont vous avez besoin dans cette base de données dans ces exemples sont les noms des objets, donc les performances ne devraient pas être un problème.En termes d'implémentation, disposer d'une table unique avec toutes les clés et l'état des actifs (disponible, verrouillé depuis le développeur, verrouillé depuis la prod) synchronisé / accessible en temps réel dans tous les environnements devrait suffire. Une solution plus complexe implémenterait un système de contrôle de version complet - vous pouvez utiliser un système existant comme CVS ou SVN si vos actifs sont tous dans un système de fichiers.
la source
Je pense que le point ici est d'accepter proprement votre responsabilité. 1) Le serveur indique ce qui est actuellement acceptable et l'API avec laquelle accéder. La base de données est en cours de modification, selon certaines règles. 2) Les créateurs sont autorisés à créer du contenu, mais il doit être jouable après les mises à jour. Ceci est de votre seule responsabilité: toute mise à jour doit pouvoir analyser les anciennes structures de données de préférence aussi propres et simples que possible.
L'idée de point de montage a des avantages si vous êtes intéressé à garder la trace d'objets et de positions uniques à l'intérieur d'une structure malléable, surtout si nous acceptons que toute la structure `` maison '' d'un joueur va subir un changement spectaculaire, et que vous souhaitez garder cela petits trucs déco dans leurs casiers respectifs.
C'est un problème extrêmement compliqué, bonne chance! Il n'existe probablement pas de réponse unique.
la source
Je ne pense pas que cela pose un gros problème pendant que vous le faites.
Je voudrais simplement écraser les mods créés par l'utilisateur, avec un avertissement notant que "Mod X peut ne pas fonctionner correctement avec cette version", laisser aux créateurs de mods le soin de changer leur travail. Je ne pense pas que ce soit une attente irréaliste que les mises à jour puissent désactiver certains mods.
Idem pour le contenu créé par l'utilisateur, effectuez simplement une sauvegarde et écrasez.
Je n'ai aucune expérience dans ce domaine, je fais juste des suggestions.
la source