Skocz do zawartości

Witamy w Nieoficjalnym polskim support'cie AMX Mod X

Witamy w Nieoficjalnym polskim support'cie AMX Mod X, jak w większości społeczności internetowych musisz się zarejestrować aby móc odpowiadać lub zakładać nowe tematy, ale nie bój się to jest prosty proces w którym wymagamy minimalnych informacji.
  • Rozpoczynaj nowe tematy i odpowiedaj na inne
  • Zapisz się do tematów i for, aby otrzymywać automatyczne uaktualnienia
  • Dodawaj wydarzenia do kalendarza społecznościowego
  • Stwórz swój własny profil i zdobywaj nowych znajomych
  • Zdobywaj nowe doświadczenia

Dołączona grafika Dołączona grafika

Guest Message by DevFuse
 

Zdjęcie

Forwardyreakcja na zdarzenia


  • Nie możesz napisać tematu
  • Zaloguj się, aby dodać odpowiedź
10 odpowiedzi w tym temacie

#1 R3X

    Godlike

  • Przyjaciel

Reputacja: 2 987
Godlike

  • Postów:4 248
  • Lokalizacja:Nie
Offline

Napisano 14.07.2010 17:05

*
Popularny

Forwardy1. Opis
Działają odwrotnie do natywów. Funkcja natywna jest udostępniana innym pluginom. Forwardy to abstrakcyjne funkcje, które biblioteka próbuje wywołać. Wykonując forward dajemy sygnał, że nastąpiło jakieś zdarzenie i plugin może na nie zareagować. Można to lepiej zrozumieć biorąc pod uwagę forwardy samego AMXX, takie jak:
forward plugin_init();
forward client_putinserver(id);
stąd powinieneś się domyślić je rozpowszechniać.

W pliku .inc podajemy nagłówek
forward nazwa(Float:para, met, ry[]);
a w pliku .sma
public nazwa(Float:para, met, ry[]){
	//nasz kod
}
Dalej tę funkcji publiczną nazywam 'funkcją oczekującą'.

O tym jak zaprojektować czytaj dalej ->

2. Tworzenie
Po pierwsze musimy zarejestrować forward.

MultiForward
Gdy użyjemy poniższej, oczekująca funkcja będzie wywoływana w każdym pluginie, który z niej korzysta.
/**
* Rejestruje forward dostępny dla wszystkich pluginów
*
* @param name[] Nazwa publicznej funkcji
* @param stop_type Typ zatrzymania
* @param ... Parametry
* @return Uchwyt (liczba całkowita)
*/
CreateMultiForward ( const name[], stop_type, ... )


Jako name[] podajemy nazwę, Typ zatrzymania określa sposób realizacji:
#define ET_IGNORE		0	//ignoruj zwracaną wartość
#define ET_STOP			1	//zatrzymuje przy PLUGIN_HANDLED
#define ET_STOP2		2	//to samo,tylko nie zwraca największej wartości
#define ET_CONTINUE		3	//bez stopu, zwraca największą wartość
forward z typem ingore i continue będzie wywołany zawsze we wszystkich pluginach
opcje stopu (STOP i STOP2) zatrzymują rozsyłanie forwardu po otrzymaniu PLUGIN_HANDLED

Jeśli na tym skończymy to powstaje forward bez parametrów, jak:
//sma biblioteki
CreateMultiForward ( "nic_sie_nie_stalo", ET_IGNORE);

//w pliku .inc
forward nic_sie_nie_stalo();


Aby dodać jakieś argumenty trzeba rozwinąć rejestrowanie o dodatkowe wartości. Do określenia typu parametru służą stałe (nazwy są sugestywne)
#define FP_CELL			0
#define FP_FLOAT		1
#define FP_STRING		2
#define FP_ARRAY		4
Dodanie argumentu forwardu polega na dopisniu jego typu po przecinku
//sma biblioteki
CreateMultiForward ( "nic_sie_nie_stalo", ET_IGNORE, FP_CELL, FP_FLOAT);

//w pliku .inc
forward nic_sie_nie_stalo(id, Float:fTime);


MultiForwardEx
Jest to wersja kompatybilna z pluginami AMX. Nie będę się tym zajmował, szczegóły w pliku amxmodx.inc.

OneForward
Druga możliwość to forward przeznaczony wyłącznie dla jednego pluginu.
/**
* Rejestruje forward dostępny dla pojedynczego pluginu
*
* @param plugin_id Id pluginu
* @param name[] Nazwa publicznej funkcji
* @param ... Parametry
* @return uchwyt (liczba całkowita)
*/
CreateOneForward ( plugin_id, const name[], ... )

Nie ma tu opcji stopu, bo tylko jeden, konkretny plugin może wykonać forward i zwróci on równie konkretną wartość.

plugin_id to id zwrócone przez funkcję
find_plugin_byfile(const pname[]);
albo....

Ciekawym rozwiązaniem jest połączenie funkcji natywnej z forwardem w ten sposób. Wyobraźmy sobie rdzeń modu, który pozwala dodawać itemy w osobnych pluginach. Rdzeń ten udostępnia natywną funkcję
register_item( /*parametry*/)
, która zapisuje informacje i tworzy właśnie pojedynczy forward powiedzmy:
forward get_item(id)
ten osobny plugin będzie czekał na sygnał, gdy gracz zdobędzie ten przedmiot. Wygodne prawda? Zwłaszcza, że id pluginu to jeden z parametrów funkcji obsługującej natyw.

Parametry jak przy MultiForward↵

3. Wywołanie
Pora wysłać sygnał wywołania forwardu.
/**
* Wywołuje wskazany forward
*
* @param forward_handle Wartość zwrócona przez Create(One|Multi)Forward
* @param &ret Wartość zwrócona przez wywołane forwardy przekazana przez referencję
* @param ... Dokładnie tyle parametrów i takich typów jak podaliśmy przy tworzeniu
* Dane zostaną przekazane do funkcji oczekujących na forward
* @return 1 jeśli wywołano jakąś funkcję oczekującą, 0 jeśli nie
*/
ExecuteForward ( forward_handle, &ret, ... )


Przykład:
new gFW;
public plugin_init(){
	gFW = CreateMultiForward("jakies_zdarzenie", ET_CONTINUE, FP_FLOAT, FP_CELL, FP_STRING);
}
public plugin_cfg(){
	new iRet;
	ExecuteForward(gFW, iRet, 3.14, -5, "Pi");
}
Tak podane parametry są jak najbardziej w porządku. Inaczej ma się sprawa z type FP_ARRAY. Nie podajemy bezpośrednio tablicy, ale rezultat funkcji
/**
* Przygotowuje tablicę do przekazania do forwardu
*
* @param array[] Tablica wejściowa
* @param size Ilość komórek
* @param copyback Czy tablica zmieniona przez funkcje oczekującą ma wrócić
*/
PrepareArray(array[], size, copyback=0 )


Ostatni parametr jest dosyć ciekawy. Wynika z niego, że oprócz podania danych do forwardu możemy także z niego uzyskać. Ustawiając 0 mamy normalne przekazanie, podając 1 funkcje oczekujące będą pracować niejako na tej tablicy.
 
new gFW;
public plugin_init(){
	gFW = CreateMultiForward("jakies_zdarzenie", ET_CONTINUE, FP_CELL, FP_ARRAY);
}
public plugin_cfg(){
	new data[2];
	data[0] = 0;
	data[1] = 1;	

	new iRet;
	ExecuteForward(gFW, iRet, 0, PrepareArray(data, 2, 1));
	
	//data[0] == 0? możliwe, że już nie!
}
4. Przykłady
w załączniku xD
plik udostępniający i korzystający z forwardu w jednym pliku odzielone kreskami

ex1 - tylko wywołanie
ex2 - z analizą z wyniku (istotne co funkcje oczekujące zwracają)
ex3 - przekazywanie tablicy
ex4 - przekazywanie tablicy i powrót wyniku

Załączone pliki

  • Załączony plik  ex.rar   2,48 KB  323 Ilość pobrań

Użytkownik glut edytował ten post 25.02.2014 21:56
Mutli na Multi

  • +
  • -
  • 18

#2 Miczu

    Godlike

  • Przyjaciel

Reputacja: 657
Wszechmogący

  • Postów:2 862
Offline

Napisano 14.07.2010 17:35

R3X, ja robiłem jakiś czas temu test, że nie trzeba nic oprócz CreateMutliForward i można wywołać dowolną funkcje "public" dowolnego pluga, bez .inc czy coś :F

Poza tym się zastanawiam, czy wszystkie funkcje typu set_task... co maja nazwę funkcji w " " nie używają w jakiś sposób forwarda... Co ty na to? :&
  • +
  • -
  • 0

#3 R3X

    Godlike

  • Autor tematu
  • Przyjaciel

Reputacja: 2 987
Godlike

  • Postów:4 248
  • Lokalizacja:Nie
Offline

Napisano 14.07.2010 18:10

Testowałeś callfunc`em czy jak? Nie sądzę, żeby kompilator tolerował takie wybiegi wprost
funkcja(parametry);
:)

Budowę set_task można sprawdzić w źródłach amxmodx i się okaże co za bajery ma, to co mówisz wydaje się rozsądne.
  • +
  • -
  • 0

#4 Miczu

    Godlike

  • Przyjaciel

Reputacja: 657
Wszechmogący

  • Postów:2 862
Offline

Napisano 14.07.2010 18:16

Spoiler

i
Spoiler


Działa jak natura chciała :F

Nazwa pluga nie ma znaczenia, robiłem szybkie testy dla siebie :F

Użytkownik benio101 edytował ten post 05.12.2012 13:55
Dodanie znacznika SMA

  • +
  • -
  • 1

#5 G[o]Q

    I'm G[o]Q

  • Przyjaciel

Reputacja: 1 344
Godlike

  • Postów:3 563
  • Steam:steam
  • Imię:Krzysiek
  • Lokalizacja:C: / program Files / Valve / Cstrike / G[o]Q.dem
Offline

Napisano 14.07.2010 18:22

czyli miczu wystarczy
mutliforward z nazwa funkcji z innego pluginu i potem execute uchwytu do forwardu i funkcja sie wykona tak :?:
  • +
  • -
  • 0
Manual ponad wszystko, konsola ponad manual :D :&

Chcesz wysłać do mnie PW ? użyj nazwy GoQ zamiast G[o]Q
Chcesz Kupić moduł płatności via Pukawka,Tserwery, Gamesol, Zabijaka do mojego sklepu? napisz PW cena to tylko 10 zł/sztuka

GG:6022845 (nie pomagam za free osobom ponizej rangi MoD) :D

#6 Miczu

    Godlike

  • Przyjaciel

Reputacja: 657
Wszechmogący

  • Postów:2 862
Offline

Napisano 14.07.2010 22:05

Tak, np tak się można włamać do każdego publika, np. zrobiłem test z kopaniem piłki w SJ i działa :)
  • +
  • -
  • 0

#7 R3X

    Godlike

  • Autor tematu
  • Przyjaciel

Reputacja: 2 987
Godlike

  • Postów:4 248
  • Lokalizacja:Nie
Offline

Napisano 15.07.2010 13:46

Z tego co Miczu piszesz wynika, że deklaracja forward funkcja(); rzeczywiście nie jest konieczna do działania. Fajna sprawa :)

Sprawdziłem i set_task rzeczywiście używa forwardu, ale w sposób OneForward. Tak samo funkcje sortujące z callbackiem czy query_client_cvar i pewnie cała reszta. Nie ma więc obawy, że 2 takie same set_taski w 2 różnych pluginach się pogryzą.
  • +
  • -
  • 0

#8 Miczu

    Godlike

  • Przyjaciel

Reputacja: 657
Wszechmogący

  • Postów:2 862
Offline

Napisano 15.07.2010 15:37

Dobrze wiedzieć, że moja intuicja nie zawodzi :)

Może zbadasz ten callback bo używanie innych plugów i dostawać wynik z nich jest bardzo interesujące, a może nawet przydatne :)
  • +
  • -
  • 0

#9 R3X

    Godlike

  • Autor tematu
  • Przyjaciel

Reputacja: 2 987
Godlike

  • Postów:4 248
  • Lokalizacja:Nie
Offline

Napisano 15.07.2010 16:31

Można dostać wynik z powrotem z typem array tylko, tak jak pisałem. Pewnie wygląda na przypuszczenie bo dałem '?' na końcu, ale to dotyczy wątpliwości czy funkcja oczekująca zmienia tablicę. W załączniku ex4.txt dotyczy właśnie powracania kopii array`a.

tylko przekazanie
PrepareArray(array, size)

przekazanie + kopia wraca
PrepareArray(array, size, 1 )

FP_STRING jest zawsze tylko przekazywane, ale przecież można użyć także typu FP_ARRAY dla tekstów :D
  • +
  • -
  • 0

#10 Fili:P

    Godlike

  • Power User

Reputacja: 754
Guru

  • Postów:1 679
  • Imię:Darek
  • Lokalizacja:Warszawa
Offline

Napisano 19.01.2012 19:58

Jest literówka mała:

gFW = CreateMutliForward("jakies_zdarzenie", ET_CONTINUE, FP_FLOAT, FP_CELL, FP_STRING);

Powinno być:

gFW = CreateMultiForward("jakies_zdarzenie", ET_CONTINUE, FP_FLOAT, FP_CELL, FP_STRING);

Chodzi że było Mutli zamiast Multi.
  • +
  • -
  • 0

#11 dasisdas

    Pomocny

  • Użytkownik

Reputacja: 7
Nowy

  • Postów:58
  • Imię:Sebastian
  • Lokalizacja:Polska
Offline

Napisano 19.01.2012 21:10

Fajny poradnik,dużo ciekawych rzeczy można się z niego dowiedzieć
  • +
  • -
  • 0




Użytkownicy przeglądający ten temat: 0

0 użytkowników, 0 gości, 0 anonimowych