Jak poradzić sobie ze zmianami wersji podczas zapisywania zasobów?

9

Od jakiegoś czasu pracuję nad RPG i używam dwóch różnych technik serializacji.

  • Wrogowie, broń i przedmioty są zapisywane w formacie XML.
  • Mapy i zdarzenia są zapisywane jako „kontrolowane pliki binarne” (każda klasa otrzymuje metodę zapisywania / ładowania i decyduje, co chce zapisać / załadować).

Ale zacząłem kwestionować mój wybór map i wydarzeń. Moje troski:

  • Utworzyłem edytor map, ale wciąż brakuje mi możliwości zmiany małych rzeczy po prostu poprzez otwarcie pliku.
  • Zmienia tak bardzo bałagan. Powiedz, że chcę dodać zmienną do klasy, jeśli nie załaduję / nie zapiszę ponownie każdej mapy, później się zepsuje.

Pierwszym problemem jest trudność bez zmiany mojej techniki. Myślałem o przejściu na JSON, ale to dużo pracy. Myślę również, że wygląda to dość brzydko z atrybutami [DataContract] i [DataMember] wszędzie.

To pozostawia moją drugą troskę i zastanawiam się, jak sobie z tym poradzić? Czy tworzysz mały program, który przegląda wszystkie mapy i zapisujesz je ponownie z nową zmienną? Ponieważ teraz zaczynam otrzymywać kilka map i nadal robię to ręcznie. Sprawia, że ​​zastanawiam się dwa razy za każdym razem, gdy chcę wprowadzić zmiany, ponieważ powoduje to wiele dodatkowej pracy.

użytkownik1776562
źródło

Odpowiedzi:

5

Istnieje wiele sposobów radzenia sobie z problemem wersji; możesz to zrobić, mając jedną funkcję ładowania na wersję, możesz spróbować zautomatyzować proces, opisując (zwykle za pomocą atrybutów) transformację struktury zasobów w czasie, możesz przeprowadzać kontrole specyficzne dla wersji w funkcjach ładowania / zapisywania itp. .

Podoba mi się podejście „opisz zmiany”, ale stwierdzenie, że próba zrobienia tego za pomocą atrybutów staje się niezręczne szybko . Zamiast tego użyłbym funkcji; zaimplementuj funkcję, która przekształca dane w wersji Nna dane w wersji N + 1dla wszystkich odpowiednich wersji. Po załadowaniu sprawdź wersję pod kątem najnowszej wersji, a jeśli nie jest, uruchom dane przez wszystkie odpowiednie funkcje kontroli wersji. Zawsze zapisuj najnowszą wersję.

Działa to najlepiej, jeśli wykonujesz transformację, gdy dane są nadal w postaci klucz-wartość środowiska wykonawczego. Oznacza to, że prawdopodobnie będziesz chciał zaimplementować reprezentację dla swoich danych, która jest podejściem „zestawu właściwości środowiska wykonawczego”, ponieważ nie możesz użyć podstawowej formy klucz-wartość JSON lub XML, jeśli masz swój własny format binarny. Jeśli tego nie zrobisz, być może będziesz musiał zachować stare definicje klas, co staje się brzydkie. Możliwość posiadania zasobów w złym formacie tej właściwości jest również niezwykle przydatna przy tworzeniu edytora gier.

Podczas programowania podczas iteracji twoich danych naturalnie pojawi się bąbelek do najnowszej wersji i ostatecznie możesz usunąć stare funkcje wersjonowania. Jest to mniej więcej to samo podejście wysokiego poziomu, którego użyliśmy do wersjonowania zasobów graficznych (takich jak mapy) w Guild Wars 2.


Teraz to wszystko powiedziawszy, myślę, że warto obsługiwać zarówno serializację tekstową, jak i binarną dla zasobów. Podczas programowania przechowuj wszystkie dane w formacie czytelnym dla człowieka na podstawie XML lub JSON. Może to znacznie zwiększyć twoją zdolność do iteracji, ponieważ nie musisz budować tak złożonych narzędzi do edycji danych. Możesz wrócić do możliwości ręcznego wprowadzania prostych poprawek.

Po drugie, zakładając, że nadal potrzebujesz formatu binarnego do wysyłki gry (który może poprawić rozmiar pliku lub czasy operacji we / wy pliku, więc jest to słuszne pragnienie), zaprojektuj interfejsy API serializacji i deserializacji do obsługi wersji. Przechowywanie wersji jest nadal przydatne w kontekście wysyłki, ponieważ w pewnym momencie możesz chcieć wysłać aktualizacje lub poprawki błędów. Istnieje kilka dokumentów opisujących możliwości wersjonowania serializacji .NET i serializacji Boost, które mogą Cię zainteresować. Jeśli zamiar obsługiwać zarówno tekst jak i formaty binarne, upewnij się przetestować je od czasu do czasu (lub zbudować zautomatyzowanych testów, aby to zrobić, nawet lepiej).


źródło
Dzięki za komentarz, dałem mi pomysły, jak kontynuować.
user1776562,
1

Użyj języka znaczników z parami atrybut-wartość, takimi jak XML lub JSON.

Analizator składni może po prostu zignorować atrybuty, których nie rozumie, lub użyć wartości domyślnych dla tych, których nie znajdzie, co sprawia, że ​​zgodność z poprzednimi i następnymi wersjami jest dość łatwa. Ponadto format jest czytelny dla człowieka, dzięki czemu można go łatwo edytować za pomocą edytora tekstu.

Kiedy używasz ustalonego języka, takiego jak XML lub JSON, zauważysz również, że obsługuje go wiele języków skryptowych, więc kiedy będziesz musiał napisać skrypt do edycji dużej liczby plików, łatwiej ci będzie to zrobić.

Wadą większości tych języków jest to, że są dość gadatliwe. Oznacza to, że pliki wynikowe są znacznie większe niż w przypadku zoptymalizowanego formatu binarnego. W dzisiejszych czasach rozmiar pliku nie ma większego znaczenia w większości sytuacji. Ale tam, gdzie ma to znaczenie, rozmiar pliku można często znacznie zmniejszyć, kompresując plik za pomocą algorytmu podstawowego, takiego jak zip.

Języki znaczników często nie pozwalają na losowy dostęp, chyba że cały dokument zostanie odczytany z dysku twardego i przeanalizowany. Ale w praktyce nie ma to większego znaczenia, ponieważ dyski twarde są najszybsze z sekwencyjnymi odczytami. Losowe wyszukiwanie wielu razy w różnych częściach tego samego pliku może często być znacznie wolniejsze niż czytanie pliku za jednym razem, nawet jeśli oznacza to, że czytasz więcej danych, niż potrzebujesz.

Philipp
źródło
1

możesz użyć protobuf. https://code.google.com/p/protobuf/ Daje to zalety json / xml, które można łatwo rozszerzyć, zachowując zgodność wsteczną, a także zaletę binarności. Przepływ pracy polega na tym, że tworzysz opis formatu danych w języku protobuf, a następnie generujesz kod źródłowy do serializacji i deserializacji. Źródło można wygenerować dla kilku języków. Dużą zaletą jest także to, że masz wyraźną specyfikację danych zserializowanych, w przeciwieństwie do json, w którym specyfikacja jest wykonywana w sposób domyślny podczas odczytu / zapisu.

Arne
źródło
Wygląda fajnie, ale używam c #, wydaje się, że jest to dla c ++, python i java.
user1776562,
Istnieje wersja C #. Nie przetestowałem tego osobiście, ale jest jeden.
Arne