Skocz do zawartości
KoPcIu

GameMode oparty o MySQL - Część 1

Rekomendowane odpowiedzi

GameMode oparty o MySQL - Część 1

 

 

Wstęp
Na forum znajduje się wiele problemów dotyczących podstaw tworzenia map. Od czego zacząć, jak użyć systemu MySQL, jak prawidłowo skonfigurować połączenie z bazą danych. Postanowiłem pomóc wielu z tych osób i stworzyć poradnik dotyczący napisania prostego GameMode wykorzystującego system zapisu do bazy danych.
 
Cały poradnik będzie w kilku częściach, a po zakończeniu zostanie utworzona wersja OffLine, wersja HTML do pobrania. W poradniku nie będę opisywał szczegółowo funkcji, czy jej parametrów, tylko jej działanie, szczegóły znajdują się w polskiej wersji WIKI jak i angielskiej.

 

 

Wprowadzenie
Wykorzystamy system zapisu danych w bazie dlatego pierwszym etapem, będzie zdobycie takiej bazy. Mamy na to kilka sposobów.

  • Utworzenie lokalnej bazy danych, wykorzystując XAMPP .
  • Użycie bazy danych hostingu WWW (tutaj należy pamiętać, aby odblokowane było połączenie z zewnątrz) .
  • Wykorzystanie bazy danych ze stron oferujących serwery SA-Mp (oczywiście jeśli zezwalają na zewnętrzne połączanie).
  • Ostatnia opcja, użycie darmowej bazy danych, które oferuje Pawno.PL swoim użytkownikom.

Nie ważne z jakiej opcji skorzystaliśmy, musimy posiadać kilka podstawowych danych, takich jak:

  • Host bazy danych,
  • Nazwa użytkownika,
  • Hasło bazy
  • Nazwa bazy danych
  • Dodatkowo, bardzo przydatne może być narzędzie PHPMyAdmin.

W mapie wykorzystamy kilka ciekawych pluginów, które pomogą nam w tworzeniu Naszego GameMode.

Przydatny również będzie nieco lepszy program do pisania, ponieważ standardowe Pawno, jest nieco kłopotliwe, jeśli chodzi o używanie kilku plików w jednym momencie. Ja posługiwał się będę Notepad++ Wraz z kilkoma dodatkami, które opisane są w tym temacie.

 

Dodatkowo cała mapa zostanie podzielona na moduły, przedstawiam jak będzie to wyglądać na samym początku:

 

1.png

 

Katalog source zawierał będzie wszystkie elementy dotyczące naszego GameMode. Includes zawiera wszystkie zewnętrzne include, jakie dołączymy do projektu, pozwoli nam to po dłuższym okresie czasu skompilować Nasz gamemode, bez potrzeby dopasowywania odpowiednich include.

  • core.inc - plik zawierający wszystkie tablice, funkcje dotyczące walidacji serwera podczas uruchomienia, czy wyłączenia.
  • header.inc - jedyny plik, który będziemy dołączać do Naszego głównego pliku z mapą, w nim znajdziemy ładowanie pozostałych include.
  • mysql.inc - wszystkie funkcje dotyczące połączenia z bazą danych, rozłączenia jak i przydatne funkcje dla operacji na bazie.
  • settings.inc - wszystko co dotyczy konfiguracji Naszego GameMode, czyli ładowanie danych z config, czy z pliku konfiguracyjnego.
  • tutorial.pwn - główny plik mapy, w którym nie znajdziemy wiele ;)
  • config.xml - plik konfiguracji połączenia, autora itd.

 

Podstawy

Utwórzmy teraz podstawowy szkielet naszej mapy, plik tutorial.pwn

#include <a_samp>

#include "source/header.inc"

main() {}

public OnGameModeInit() {

	return true;
}

public OnGameModeExit() {
	
	return true;
}

Znamy już wygląd naszego gamemode, więc następnym krokiem będzie edycja header.inc , jak pamiętamy w tym pliku znajdzie się ładowanie wszystkich include, więc tym się zajmijmy.

#include "source/includes/foreach.inc"
#include "source/includes/mysql.inc"
#include "source/includes/sscanf2.inc"
#include "source/includes/xml.inc"

#include "source/core.inc"
#include "source/settings.inc"
#include "source/mysql.inc"

W tym momencie, możemy pierwszy raz skompilować Naszą mapę z pozytywnym wynikiem ;) Jednak, po co nam gamemode, który nie wykonuje żadnej akcji? Czas to zmienić.

 

 

Tworzenie config.xml

Zawartość pliku konfiguracyjnego jest bardzo prosta, główna sekcja to settings, która dzieli się na kilka innych.

<?xml version="1.0"?>
<settings>
	<gm>
		<name>tutMap</name> 			<!-- Nazwa mapy -->
		<author>KoPcIu</author> 		<!-- Autor mapy -->
		<version>1.0 Beta</version> 		<!-- Wersja mapy -->
	</gm>
	<server>
		<name>Serwer tutMap!</name> 		<!-- Nazwa serwera w HostName -->
		<mode>tutMap 1.0 Beta</mode> 		<!-- Nazwa w kolumnie Mode -->
		<map>Las Venturas</map> 		<!-- Nazwa w kolumnie Map -->
	</server>
	<db>
		<host>46.4.177.235</host> 		<!-- Host bazy danych -->
		<user>KoPcIu</user> 			<!-- Nazwa użytkownika bazy -->
		<pass>NIE_PODAM_;)</pass> 		<!-- Hasło użytkownika bazy -->
		<name>KoPcIu</name> 			<!-- Nazwa bazy danych -->
		<prefix>Tut_</prefix> 			<!-- Prefix bazy danych -->
	</db>
</settings>

Ładowanie config.xml

Jako pierwsze zdefiniujmy lokalizacje pliku config, u mnie będzie on się znajdować bezpośrednio w katalogu scriptfiles co oznacza, że ścieżka to po prostu nazwa pliku z rozszerzeniem.

 

Dodamy do naszego pliku core.inc definicje tej ścieżki:

#define PATH_CONFIG "config.xml"

Dodatkowo w tym samym pliku utwórzmy tablicę do przechowywania danych pobranych z pliku config.

enum e_Setting {
	gmName[64],		// Nazwa mapy,
	gmAuthor[32],	        // Autor mapy,
	gmVersion[16],	        // Wersja mapy

	servName[64],	        // Nazwa serwera w HostName
	servMode[32],	        // Nazwa w kolumnie Mode
	servMap[32],	        // Nazwa w kolumnie Map

	dbHost[32],		// Host bazy danych
	dbUser[32],		// Nazwa użytkownika bazy
	dbPass[32],		// Hasło użytkownika bazy
	dbName[32],		// Nazwa bazy danych
	dbPrefix[8]		// Prefix bazy danych
}
new Settings[e_Setting];

W pliku settings.inc utwórzmy funkcje ładującą podstawową konfigurację

stock Settings_Load(file_name[]) {
	new XML:xml_file = xml_open(file_name); // Ładujemy plik konfiguracji, ścieżke pobieramy jako argument

	if(xml_file) { // Sprawdzamy czy plik został otwary
	
		/*
			Funkcje poniżej ładują poszczególne dane z pliku konfiguracyjnego, po więcej szczegółów zapraszam na stronę pluginu XML
			Dodatkowo, pamiętajmy o podaniu jako ostatni argument funkcji xml_get_string wielkości danej tablicy
		*/
		xml_get_string(xml_file, "settings/gm/name", Settings[gmName], sizeof(Settings[gmName]));
		xml_get_string(xml_file, "settings/gm/author", Settings[gmAuthor], sizeof(Settings[gmAuthor]));
		xml_get_string(xml_file, "settings/gm/version", Settings[gmVersion], sizeof(Settings[gmVersion]));
		
		xml_get_string(xml_file, "settings/server/name", Settings[servName], sizeof(Settings[servName]));
		xml_get_string(xml_file, "settings/server/mode", Settings[servMode], sizeof(Settings[servMode]));
		xml_get_string(xml_file, "settings/server/map", Settings[servMap], sizeof(Settings[servMap]));
		
		xml_get_string(xml_file, "settings/db/host", Settings[dbHost], sizeof(Settings[dbHost]));
		xml_get_string(xml_file, "settings/db/user", Settings[dbUser], sizeof(Settings[dbUser]));
		xml_get_string(xml_file, "settings/db/pass", Settings[dbPass], sizeof(Settings[dbPass]));
		xml_get_string(xml_file, "settings/db/name", Settings[dbName], sizeof(Settings[dbName]));
		xml_get_string(xml_file, "settings/db/prefix", Settings[dbPrefix], sizeof(Settings[dbPrefix]));

		xml_close(xml_file); // Zamykamy plik
		return true; // Zwracamy poprawne załadowanie pliku konfiguracyjnego
	}
	return false; // Zwracamy problem przy ładowaniu pliku
}

Następnie musimy wykonać kod wczytywania danych. Oczywiście najlepsze rozwiązanie to start gamemode, czyli otwieramy plik tutorial.pwn . Wkleimy tam kod zawierający nie tylko ładowanie, ale i odwołanie się do funkcji wyłączającej serwer gdy tylko konfiguracja nie zostanie wczytana.

 

W OnGameModeInit

	new check = 0;
	
	check = Settings_Load(PATH_CONFIG); // Oczywiście pamiętamy o podaniu ścieżki
	if(!check)
		return Core_Stop(REASON_CONFIGFILE);

Jak widać kod wykonuje się przy problemie z odczytaniem pliku konfiguracyjnego i odwołuje się do funkcji Core_Stop z parametrem REASON_CONFIGFILE .

 

 

Funkcja Core_Stop

Jak pamiętami funkcjami serwera zajmuje się plik core.inc dlatego funkcja wyłączająca serwer znajduje się w nim.

 

Na początku zdefiniujmy error REASON_CONFIGFILE . Przyjmijmy, że będzie to error o ID 1 . Oczywiście z czasem pojawi się więcej tego typu błędów, więc nie ma sensu tworzyć kilku funkcji do wyłączania serwera, a jedną i identyfikować błąd.

#define REASON_CONFIGFILE			1

Sam kod funkcji:

stock Core_Stop(reason) {
	switch(reason) {
		case REASON_CONFIGFILE:
			print("[ERROR] Problemy przy zaladowaniu pliku config. Plik: "PATH_CONFIG" .");
	}
	SendRconCommand("exit");
	return true;
}

Zakończenie

Myślę że w tym momencie zakończymy pierwszą część poradnika o własnym gamemode. Mamy podstawy mapy jak i ładowanie pliku config. Już w następnej wersji dołączymy do tego połączenie z bazą danych jak i po raz pierwszy wejdziemy na swój serwer ;)

 

W załączniku znajduje się projekt, który do tej pory utworzyliśmy  :)

 

Pozdrawiam i czekam na opinie!

 

Druga część poradnika.

Tutorial_#1.zip

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Takie małe wyprostowanie od ColeMiner'a (to jest "legalne" multikonto Y_Less'a na forum SA:MP) odnośnie używania stock:

People who use "stock" at all. If you are writing a mode, there is ZERO need to use "stock" - just make a normal function!

Cytat pochodzi stąd. Edytowane przez Shiny

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Według mnie, stock jest dobrym rozwiązaniem gdy nie chcesz mieć zaśmieconej konsoli od ostrzeżeń dotyczących nieużytych funkcji w kodzie, lecz łatwo wtedy można zapomnieć, że napisało się już jakąś funkcję i sobie ona nadal jest w skrypcie - dlatego ja ich (stock) nie używam. ;) Co do poradnika, bardzo dobry gdy ktoś nie rozumie podstaw korzystania z MySQL, mam nadzieję, że druga część będzie trochę bardziej rozbudowana (mam na myśli kod). ;) A więc - powodzenia życzę i zapału do dalszej pracy!

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Bardzo ładny poradnik. :)

 

Troszkę się nawet poduczyłem, ciekaw jestem co w części drugiej będzie.

 

 

Pozdrawiam.

Edytowane przez Wojtek020699

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

RTX6Amr.png

Czy jest sens tworzenia takich samych poradników od początku? nie lepiej było by zrobić coś w stylu "GameMode oparty o MySQL - Część 1"? bo tak to nowi teraz będą czytać poradniki "Część 1" dodatkowo ten od poradnika poprzedniego różni się system plików :P 

 

9/10

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Takie małe wyprostowanie od ColeMiner'a (to jest "legalne" multikonto Y_Less'a na forum SA:MP) odnośnie używania stock:Cytat pochodzi stąd.

 

Ehhh... Dla mnie liczy się osoba, która wstawiała skrypt na forum. Nie pisał że autorem jest ktoś inny, dlatego uważam, że to on jest autorem i nie będę wnikał w to dalej.

 

 

RTX6Amr.png

Czy jest sens tworzenia takich samych poradników od początku? nie lepiej było by zrobić coś w stylu "GameMode oparty o MySQL - Część 1"? bo tak to nowi teraz będą czytać poradniki "Część 1" dodatkowo ten od poradnika poprzedniego różni się system plików :P

 

9/10

 

Hmm... Poradnik autora promsters jak widać posiada datę 25 listopad... Dnia 3 grudnia pisał o następnej części jednak ja jej nie widzę? Kontaktowałem się z nim czy będzie następna część gdzieś w marcu, powiedział, że tak jednak do tej pory ja jej nie widzę, dlatego sam przeniosłem ten temat do działu oczekujące. Dlatego właśnie powstał mój poradnik, bo on miał dobry pomysł, jednak go nie wykorzystał.

 

Poradniki są te same, bo nie mają co zawierać innej treści, każdy z nich opisuje to samo. Podział na moduły, ładowanie configu. Co miało by być inne, jak w końcu to jest najważniejszą rzeczą jak na razie?

 

Aktualnie oba tematy znajdują się w dziale oczekujące, dziś mogę już stwierdzić, że nikt nie wyszukał się większych błędów, dlatego przenoszę go do działu poradniki i zabieram się za kolejną część.

 

Pozdrawiam!

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Ehhh... Dla mnie liczy się osoba, która wstawiała skrypt na forum. Nie pisał że autorem jest ktoś inny, dlatego uważam, że to on jest autorem i nie będę wnikał w to dalej.

KoPcIu, ale ja pisałem o stocku i o tym, że jest zbędny oraz że sam Y_Less proponuje tworzyć funkcje zamiast stałych. Nie pisałem o tym, kto wstawia skrypt na forum i czy ktoś inny jest autorem.

A o poradniku nic nie powiem, bo nie mam żadnych zastrzeżeń. :D

Edytowane przez Shiny

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Kilka literówek jest w tym poradniku, ale można przymknąć na to oko.

Warto dodać, że deklaracja main'a w poniższy sposób:

main() {}
Spowoduje, że callback OnGameModeInit wykona się dwa razy. Mozna to naprawic - zwracajac falsz.

A co do stocka, bo widzę, że zrobiła się tutaj taka drobna dyskusja...

Z tego co słyszałem i doświadczylem, użycie przedrostka stock powoduje, ze kompilator nie wywala warninga, o tym, ze funkcja nie zostala nigdzie uzyta.

Także, żeby rozwiać wszelkie negatywy - stosowanie tego przedrostka jest obojętnym czynnikiem.

PS. Ktos jeszcze w tych czasach uzywa tego syfu zwanego foreachem? O.o

Pozdrowki.

@mrdrifter y tak. Bez powodu tego nie pisze. Kiedys mialem przypadek, gdy dwukrotnie wykonal mi sie ten callback.

Edytowane przez l0nger

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Kilka literówek jest w tym poradniku, ale można przymknąć na to oko.

Warto dodać, że deklaracja main'a w poniższy sposób:

main() {}
Spowoduje, że callback OnGameModeInit wykona się dwa razy. Mozna to naprawic - zwracajac falsz.

 

Yyy nie?

#include a_samp

main(){
}
public OnGameModeInit() return printf("... __.__ ..."),0;

wykonalo sie raz. 

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

KoPcIu, ale ja pisałem o stocku i o tym, że jest zbędny oraz że sam Y_Less proponuje tworzyć funkcje zamiast stałych. Nie pisałem o tym, kto wstawia skrypt na forum i czy ktoś inny jest autorem.

A o poradniku nic nie powiem, bo nie mam żadnych zastrzeżeń. :D

 

Wybacz, źle przeczytałem.

 

Kilka literówek jest w tym poradniku, ale można przymknąć na to oko.

Warto dodać, że deklaracja main'a w poniższy sposób:

main() {}
Spowoduje, że callback OnGameModeInit wykona się dwa razy. Mozna to naprawic - zwracajac falsz.

A co do stocka, bo widzę, że zrobiła się tutaj taka drobna dyskusja...

Z tego co słyszałem i doświadczylem, użycie przedrostka stock powoduje, ze kompilator nie wywala warninga, o tym, ze funkcja nie zostala nigdzie uzyta.

Także, żeby rozwiać wszelkie negatywy - stosowanie tego przedrostka jest obojętnym czynnikiem.

PS. Ktos jeszcze w tych czasach uzywa tego syfu zwanego foreachem? O.o

Pozdrowki.

@mrdrifter y tak. Bez powodu tego nie pisze. Kiedys mialem przypadek, gdy dwukrotnie wykonal mi sie ten callback.

 

 

Bardzo chętnie poznam je, podeślij je tutaj, czy na PW :) Jestem tylko człowiekiem i mam prawo do błędu, jednak jeśli jest możliwość to poprawię.

 

KoPciu, będzie jeszcze część twojego poradnika, jak zrobić logowanie w mysql, system grup itp?

 

Aktualnie mam dylemat. Ponieważ ma to być tutorial jak stworzyć gamemode, jednak problemem jest fakt jaki typ? Na pewno nie będzie tutaj poradnika od A do Z, jednak pokarzę np jak stworzyć jedną zabawę, jak korzystać z dialogów itd. Po prostu wszystkiego po trochę.

 

Pozdrawiam!

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Nieeee. Ja nie chce gotowca bo sie gówno naucze. Tylko nie zrozumiałem poradnika dokładnie. I sie pytam czy ten jego tutorial - gm To ma być nazwa naszego gm'a chodzi o to czy to wszystko mam robić w swoim Gm

Edytowane przez Bartek_TI

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

ok, a czekam jeszcze na odpowiedź odnośnie pierwszego pytania:


Ja zamiast mysql.inc mam a_mysql.inc - może tak byc? Pobrałem stąd, skąd pokazałeś.



//2: co to jest prefix? Edytowane przez Winnetou

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

  • Przeglądający   0 użytkowników

    Brak zarejestrowanych użytkowników przeglądających tę stronę.

×