Mam grę online, w której gracze mogą w jakiś sposób kształtować świat - np. Obudowa Ultima Online, w której możesz budować domy bezpośrednio na określonych częściach mapy świata. Są to zmiany, które powinny trwać z czasem w ramach trwałego świata.
W tym samym czasie zespół projektowy dodaje nowe treści i modyfikuje stare, aby ulepszyć i rozszerzyć grę dla nowych graczy. Zrobią to najpierw na serwerze programistycznym podczas testowania, a następnie będą musieli połączyć swoją pracę z „pracą” graczy na serwerze na żywo.
Zakładając, że rozwiązujemy problemy z projektem gry - np. gracze mogą budować tylko w wyznaczonych obszarach, więc nigdy nie kolidują geograficznie z edycjami projektantów - jakie są dobre sposoby obsługi danych lub uporządkowania struktur danych, aby uniknąć konfliktów, gdy nowe dane projektanta zostaną połączone z danymi nowego gracza?
Przykład 1: gracz tworzy nowy typ przedmiotu, a gra przypisuje mu identyfikator 123456. Wszystkie instancje tego przedmiotu odnoszą się do 123456. Teraz wyobraź sobie, że projektanci gier mają podobny system, a projektant tworzy nowy przedmiot o numerze 123456. Jak tego uniknąć?
Przykład 2: ktoś tworzy popularny mod, który nadaje wszystkim twoim smokom francuski akcent. Zawiera skrypt z nowym obiektem o nazwie, assignFrenchAccent
którego używają do przypisania nowych zasobów głosu do każdego obiektu smoka. Ale masz zamiar wdrożyć swoje DLC „Napoleon vs Smaug”, które ma obiekt o tej samej nazwie - jak możesz to zrobić bez wielu problemów z obsługą klienta?
Myślałem o następujących strategiach:
- Możesz użyć 2 oddzielnych plików / katalogów / baz danych, ale wtedy operacje odczytu są znacznie skomplikowane. „Pokaż wszystkie elementy” musi wykonać jeden odczyt na DB projektanta i jeden na DB odtwarzacza (i nadal musi jakoś rozróżniać 2).
- Możesz użyć 2 różnych przestrzeni nazw w jednym sklepie, np. używanie ciągów jako klucza podstawowego i poprzedzanie ich słowami „DESIGN:” lub „PLAYER:”, ale tworzenie tych przestrzeni nazw może być nietrywialne, a zależności nie są jasne. (np. w RDBMS możesz nie być w stanie efektywnie używać ciągów jako kluczy podstawowych. Możesz użyć liczb całkowitych i przydzielić wszystkie klucze podstawowe poniżej pewnej liczby, np. 1 miliona, aby być danymi projektowymi i wszystko powyżej tego dane odtwarzacza. Ale te informacje są niewidoczne dla RDBMS, a linki klucza obcego przekroczą „podział”, co oznacza, że wszystkie narzędzia i skrypty muszą jawnie je obejść).
- Zawsze możesz pracować na tej samej współużytkowanej bazie danych w czasie rzeczywistym, ale wydajność może być niska, a ryzyko uszkodzenia danych odtwarzacza może zostać zwiększone. Nie obejmuje również gier, które działają na więcej niż 1 serwerze z różnymi danymi światowymi.
- ... jakieś inne pomysły?
Przyszło mi do głowy, że chociaż jest to przede wszystkim problem w przypadku gier online, koncepcje mogą dotyczyć również modowania, w którym społeczność tworzy mody w tym samym czasie, gdy twórcy łatają swoją grę. Czy zastosowano tu jakieś strategie, aby zmniejszyć ryzyko złamania modów, gdy pojawią się nowe łatki?
Oznacziłem to również jako „kontrolę wersji”, ponieważ na jednym poziomie to jest to - 2 gałęzie rozwoju danych, które wymagają scalenia. Być może z tego kierunku mogą pochodzić pewne spostrzeżenia.
EDYCJA - kilka przykładów dodanych powyżej w celu wyjaśnienia problemu. Zaczynam myśleć, że problemem jest tak naprawdę przestrzeń nazw, którą można zaimplementować w sklepie za pomocą kluczy kompozytowych. To przynajmniej upraszcza strategię scalania. Ale mogą istnieć alternatywy, których nie widzę.
źródło
Odpowiedzi:
Myślę, że odpowiedzi proponujące rozwiązania DB przeskakują do konkretnej implementacji bez zrozumienia problemu. Bazy danych nie ułatwiają scalania, po prostu dają ramy do przechowywania danych. Konflikt jest nadal konfliktem, nawet jeśli znajduje się w DB. A sprawdzenie to rozwiązanie problemu biednego człowieka - zadziała, ale będzie to kosztem dla twojej użyteczności.
To, o czym tu mówisz, wpada w rozproszony model rozwoju problemu. Uważam, że pierwszym krokiem nie jest myślenie o graczach i projektantach jako o osobnych typach twórców treści. To usuwa sztuczny wymiar problemu, który nie wpływa na rozwiązanie.
Skutecznie masz swoją główną linię - kanoniczną wersję zatwierdzoną przez programistę. Możesz (prawdopodobnie) mieć także inne oddziały - serwery na żywo, na których ludzie aktywnie rozwijają i udostępniają mody. Treść można dodawać w dowolnym oddziale. Co najważniejsze, twoi projektanci nie są tutaj niczym specjalnym - są po prostu twórcami treści, którzy mieszkają w domu (i możesz je znaleźć i uderzyć, gdy coś spieprzą).
Zatem akceptowanie treści generowanych przez użytkowników jest standardowym problemem scalania. Musisz albo wyciągnąć ich zmiany z powrotem na linię główną, scalić, a następnie wypchnąć ponownie, lub przeciągnąć zmiany linii głównej na ich gałąź i scalić (pozostawiając linię główną „czystą” rzeczy generowanych przez użytkownika). Jak zwykle, przyciągnięcie do gałęzi i naprawienie jest bardziej przyjazne niż proszenie innych osób o wycofanie zmian, a następnie próba naprawienia ich zdalnie na ich końcu.
Po pracy z tego rodzaju modelem obowiązują wszystkie normalne procesy dotyczące unikania konfliktów scalania. Niektóre z bardziej oczywistych:
źródło
Przechowuj wszystko jako atrybut (lub dekorator) - z punktami montażu. Weźmy dom, który gracz zaprojektował jako przykład:
Dlatego każda jednostka może mieć jeden lub więcej punktów montowania - każdy punkt montowania może przyjmować zero lub więcej innych komponentów. Te dane będą przechowywane wraz z wersją , w której zostały zapisane, wraz z wszelkimi istotnymi właściwościami (takimi jak Przemieszczenie itp. W moim przykładzie) - NoSQL najprawdopodobniej byłby tutaj naprawdę fajny (klucz = identyfikator jednostki, wartość = szeregowy plik binarny Dane).
Każdy komponent musiałby wtedy być w stanie „uaktualnić” stare dane z poprzedniej wersji (nigdy nie usuwaj pól z danych serializowanych - po prostu „zeruj” je) - to uaktualnienie ma miejsce od momentu załadowania (wówczas zostanie natychmiast zapisane z powrotem w najnowsza dostępna wersja). Powiedzmy, że w naszym domu zmieniły się wymiary. Kod ulepszenia względnie obliczy odległość między północną a południową ścianą i proporcjonalnie zmieni przemieszczenia wszystkich zawartych bytów. Jako kolejny przykład w naszej misce z mięsem może zostać usunięte pole „Jedzenie”, a zamiast tego dostaniemy „Odmianę” (Mięso) i „Przepis” (Kulki). Skrypt aktualizacji zmieniłby „Kulki mięsne” w „Mięso”, „Kulki”. Każdy element powinien także wiedzieć, jak radzić sobie ze zmianami punktów montowania - np
To wszystko pozostawia dokładnie jedną kwestię otwartą: co się stanie, jeśli dwa obiekty zderzą się ze sobą (nie ich kontener - punkty montażu chronią cię przed tym)? Po aktualizacji powinieneś sprawdzić kolizje i spróbować je rozwiązać (rozsuwając różne elementy, trochę jak SAT). Jeśli nie możesz dowiedzieć się, jak rozwiązać kolizję, usuń jeden z przedmiotów i umieść go w skrytce - gdzie mogą kupić te usunięte przedmioty (za darmo) lub sprzedać je (za pełną cenę); i oczywiście powiadom gracza, że uaktualnienie zepsuło część jego układu - być może z funkcją powiększania, aby mogli zobaczyć problem.
Ostatecznie powinieneś pozostawić złożone zmiany w rękach graczy (szybko zawieść), ponieważ żaden algorytm nie może uwzględnić estetyki - powinieneś być w stanie dać graczowi kontekst, w którym miejscu był kiedyś (aby mogli pamiętać, nie tylko wylądować z tymi wszystkimi przedmiotami w skrytce i nie wiedzieć, gdzie były).
źródło
Próbuję powiązać to z czymś, co rozumiem, więc teraz myślę w kategoriach Minecraft. Wyobrażam sobie serwer na żywo, w którym gracze wprowadzają zmiany w czasie rzeczywistym, podczas gdy programiści działają na serwerze testowym, który naprawia / tworzy nowe treści.
Twoje pytanie wydaje się prawie 2 wyjątkowymi pytaniami:
Spróbowałbym rozwiązać numer 1 za pomocą tymczasowego systemu odwołań. Na przykład, gdy ktoś tworzy nowy obiekt, może być oznaczony jako niestabilny lub tymczasowy. Wyobrażam sobie, że wszystkie nowe treści tworzone na serwerze testowym będą oznaczone jako niestabilne (chociaż mogą również odnosić się do nietrwałych treści).
Gdy będziesz gotowy przenieść nową zawartość do serwera na żywo, proces importowania znajdzie obiekty lotne i przypisze im identyfikatory obiektów serwera na żywo, które są ustawione w kamieniu. Różni się to od zwykłego importu / scalania, ponieważ musisz być w stanie odwoływać się do istniejących nieulotnych obiektów, jeśli musisz je naprawić lub zaktualizować.
W przypadku # 2 wydaje się, że naprawdę potrzebujesz pewnego poziomu pośredniej transmutacji skryptu, który może mieszać nazwę funkcji do unikalnej przestrzeni nazw. to znaczy
Staje się
źródło
Jeśli pliki danych mają format tekstowy, a nie binarny, a projektanci i odtwarzacze modyfikują różne obszary, możesz spróbować scalenia SVN.
źródło
Myślę, że baza danych / system plików replikowany w różnych środowiskach przy użyciu procedury „wyewidencjonowywania” byłby najlepszy.
Tak więc, ilekroć projektant chce wprowadzić jakieś zmiany w świecie, wyewidencjonuje / zablokuje wszystkie zasoby, które chce utworzyć / zmodyfikować na wszystkich kopiach bazy danych (rozwój i produkcja), więc żaden inny gracz lub projektant nie może go zmodyfikować . Następnie pracowałby nad bazą danych programowania do czasu zakończenia nowego projektu, a wtedy zmiany zostałyby scalone z produkcyjną bazą danych, a te zasoby byłyby rejestrowane / odblokowywane we wszystkich środowiskach.
Edycja odtwarzacza działałaby w ten sam sposób, z tym wyjątkiem, że role bazy danych / systemu plików zostałyby odwrócone - działają one na produkcyjnej bazie danych, a wszystkie aktualizacje są przesyłane do dev po zakończeniu.
Blokowanie zasobów może być ograniczone do właściwości, w których nie chcesz gwarantować konfliktów: w przykładzie 1 blokujesz,
ID 123456
gdy tylko gracz zacznie tworzyć, więc programiści nie będą mieli przypisanego tego identyfikatora. W przykładzie 2 Twoi programiści zablokowaliby nazwę skryptuassignFrenchAccent
podczas programowania, więc gracz musiałby wybrać inną nazwę podczas opracowywania swojej modyfikacji (to małe uciążliwości można zmniejszyć przez przestrzeń nazw, ale to samo w sobie nie pozwoli uniknąć konfliktów, chyba że podasz każdą z nich użytkownik / programista określonej przestrzeni nazw, a wtedy będziesz miał ten sam problem z zarządzaniem przestrzeniami nazw). Oznacza to, że cały programista musiałby czytać z pojedynczej bazy danych on-line, ale wszystko, czego potrzebujesz w tej bazie danych w tych przykładach, to nazwy obiektów, więc wydajność nie powinna stanowić problemu.Jeśli chodzi o implementację, wystarczy jedna tabela ze wszystkimi kluczami i stanem zasobów (dostępna, zablokowana od programisty, zablokowana od prod) zsynchronizowana / dostępna w czasie rzeczywistym w różnych środowiskach. Bardziej złożone rozwiązanie zaimplementowałoby kompletny system kontroli wersji - możesz użyć istniejącego systemu, takiego jak CVS lub SVN, jeśli wszystkie zasoby są w systemie plików.
źródło
Myślę, że chodzi tutaj o to, aby czysto przyjąć na siebie odpowiedzialność. 1) Serwer mówi, co jest obecnie akceptowalne, oraz interfejs API, za pomocą którego można uzyskać dostęp. Baza danych jest modyfikowana zgodnie z pewnymi zasadami. 2) Twórcy mogą tworzyć treści, ale po aktualizacji muszą być dostępne. Jest to wyłącznie twoja odpowiedzialność: każda aktualizacja musi być w stanie przeanalizować stare struktury danych, najlepiej tak czyste i łatwe, jak to możliwe.
Pomysł na punkt montowania ma swoje zalety, jeśli chcesz śledzić unikalne przedmioty i pozycje wewnątrz plastycznej struktury, szczególnie jeśli przyjmiemy, że cała „domowa” struktura gracza ulegnie dramatycznej zmianie i chcesz to zachować małe rzeczy dekoracyjne w odpowiednich szafkach.
To bardzo skomplikowana sprawa, powodzenia! Prawdopodobnie nie ma jednej odpowiedzi.
źródło
Nie wydaje mi się, żeby to stanowiło duży problem, kiedy to robicie.
Po prostu nadpisałbym mody stworzone przez użytkownika, z ostrzeżeniem, że „Mod X może nie działać poprawnie z tą wersją”, pozostawiam twórcom modów zmianę pracy. Nie sądzę, że jest to nierealne oczekiwanie, że aktualizacje mogą wyłączyć niektóre mody.
To samo dotyczy treści utworzonych przez użytkownika, wystarczy wykonać kopię zapasową i zastąpić.
Nie mam w tym żadnego doświadczenia, tylko sugeruję.
źródło