Skocz do zawartości

  • Zaloguj korzystając z Facebooka Zaloguj korzystając z Twittera Zaloguj przez Steam Zaloguj poprzez Google      Logowanie »   
  • Rejestracja

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

[Orpheu] Podstawowe zagadnienia.


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

#1 Owner123

    Wszechpomocny

  • Użytkownik

Reputacja: 144
Zaawansowany

  • Postów:331
  • Lokalizacja:Barty ;]
Offline

Napisano 23.09.2010 15:28

*
Popularny

W tym o to tutorialu postaram się przybliżyć potęgę oraz pomóc zrozumieć nieco ten moduł.

Orpheu, jest to moduł autorstwa joaquimandrade. Jest możliwy do pobrania stąd: Module: Orpheu2.3a - AlliedModders

No to lecimy !
Pierwsza rzecz, jaka jest potrzebna, to dekompilator Windowsowy/Linuxowy. Osobiście posiadam IDA Pro Advanced + Hex Rays Decompiler.
Wszystkie poniższe operacje będę przeprowadzał właśnie na tym programie.

Od czego zacząć?
Pierwszą operacje, jaką przeprowadzimy będzie dekompilacji biblioteki. Mamy 2 rodzaje bibliotek:
- engine - silnik gry (nie mylić z biblioteką HL!). Jest to podstawa każdego modu. Nazwa pliku: swds.dll(Windows)/hlds_engine*(Linux).
- mod - silnik moda np. Counter-Strike, Half-Life, Team Fortress etc. Nazwa pliku:(dla Cs'a) mp.dll(Windows)/cs_i386.so(Linux). Oba te pliki znajdują się w cstrike/dlls.

Po otwarciu IDA ukaże się takie o to okienko:
Dołączona grafika
Wybieramy "New".
Dołączona grafika
I tutaj mamy wybór. Możemy dekompilować biblioteke Windowsową albo Linuxową. Wybieramy Linuxową, dlaczego ? Ponieważ zdekompilowana biblioteka Windowsa jest nieczytelna :>
Dołączona grafika
Klikamy to co zaznaczyłem na screenie wyżej i szukamy odpowiedniej biblioteki.

Dołączona grafika

Aby otworzyć odpowiednią zakładkę, klikamy w Views>Open Subviews>Names.
Jak zapewne niektórzy zauważyli, są tu podane funkcje występujące w danej bibliotece.

Dobra mamy podstawę. Jak mam napisać z tego plugin !?
Aby móc korzystać z tych funkcji, potrzebna jest tzw. sygnatura.

Są 2 rodzaje sygnatur:
- do zwykłych funkcji, znacznie trudniej zrobić do nich sygaturę
- do funkcji wirtualnych, o wiele łatwiejsze do wykonania

Zwykłe funkcje
Każda funkcja posiada swój własny offset w bibliotece. W systemie Linux ten offset bardzo łatwo znaleść - jest to jego nazwa. W systemie Windows sprawa nie wygląda już tak pięknie i łatwo. Tutaj aby znaleść odpowiedni offset, trzeba mieć przedewszystkim cierpliwość.
No dobra, mamy funkcję InstallGameRules, o to jej 'pseudocode' z biblioteki Linuxowej:
int __cdecl InstallGameRules()
{
  int result; // eax@2
  int v1; // eax@2
  int v2; // eax@3

  (*(void (__cdecl **)(_DWORD))&g_engfuncs[156])("exec game.cfg\n");
  (*(void (**)(void))&g_engfuncs[160])();
  if ( *(float *)(gpGlobals + 20) == 0.0 )
  {
    v2 = __builtin_new(0x2C4u);
    result = __18CHalfLifeMultiplay(v2);
  }
  else
  {
    v1 = __builtin_new(0x2D8u);
    result = __17CHalfLifeTraining(v1);
  }
  return result;
}

Tutaj bardzo łatwo można zobaczyć szczególną cechę tej funkcji, string'a exec game.cfg\n. Skoro chcemy znaleść jej offset w Windowsie, dekompilujemy binarkę Windowsa i szukamy tego stringa w kodzie. Powinnyśmy znaleść coś w tym stylu:
//----- (10088530) --------------------------------------------------------
int __cdecl sub_10088530()
{
  long double v0; // fst7@1
  int v1; // eax@2
  int v3; // eax@4

  dword_101623DC("exec game.cfg\n");
  dword_101623E0();
  v0 = *(float *)(LODWORD(dword_101625B8) + 20);
  if ( v0 == 0.0 )
  {
    v1 = (int)operator new(0x2E8u);
    if ( v1 )
      return sub_100C5EF0(v1, v0);
  }
  else
  {
    v3 = (int)operator new(0x2D0u);
    if ( v3 )
      return sub_10093D80(v3, v0);
  }
  return 0;
}
Jak zapewne widać, oba kody różnią się od siebie. Naszym offsetem w Windowsie jest sub_10088530. Ponieważ jest wartość wyrażona w systemie szesnastwkowym, prawidłowy zapis wygląda w ten sposób: 0x88530.
Teraz możemy już napisać naszą sygnaturę, dla tej funkcji będzie ona wyglądać następująco:
{
    "name" : "InstallGameRules",
    "library" : "mod",
    "return" : 
    {
        "type" : "CHalfLifeMultiplay *",
	"info" : "Ten parametr jest opcjonalny. Jeśli chcemy przechwycić returna tej funkcji, to musimy uwzględnić tą zakladke u siebie"
    },
    "identifiers":
    [
        {
            "os" : "windows",
            "mod" : "cstrike",
            "value" : 0x88530
        },
	{
            "os" : "linux",
            "mod" : "cstrike",
            "value" : "InstallGameRules"
	}
    ]
}

Sygnaturę wrzucamy do configs/orpheu/functions.
W przypadku gdy funkcja należy do jakiejś klasy tworzymy dodatkowo folder z nazwą danej klasy. Np. dla funkcji CBaseEntity::Spawn ścieżka będzie następująca: configs/orpheu/functions/CBaseEntity.

Przykładowy kod z wykorzystaniem tej funkcji:
#include <amxmodx>
#include <orpheu>
#include <orpheu_stocks>

new g_pGameRules

public plugin_precache()
{
OrpheuRegisterHook(OrpheuGetFunction("InstallGameRules"),"OnInstallGameRules",OrpheuHookPost) // pobieramy uchwyt i rejestrujemy hooka
}
public OnInstallGameRules()
{
g_pGameRules = OrpheuGetReturn() // pobieramy wartość która jest zwracana przez daną funkcję
}


Funkcje wirtualne
Dla tych, którzy nie wiedzą co to są funckje wirtualne - krótkie wyjaśnienie.
Jak zapewne widzicie mamy klase CBaseEntity oraz CAWP. Jak zapewne wiadomo, każda broń jest bytem, ale nie każdy byt jest bronią. Klasa CAWP jest klasą pochodną od klasy CBaseEntity. Ponieważ klasa CBaseEntity posiada funkcje Spawn(id), klasa CAWP również posiada funkcję Spawn(id). I tutaj jest istota działania funkcji wirtualnych. Wystarczy że zrobimy sygnaturę dla CBaseEntity::Spawn i możemy przechwytywać tą funkcję niemal że dla każdego bytu !
Teraz możesz jeszcze nie rozumieć zabardzo tego, jednakże spójrz na ten przykład: chce przechwycić Spawn dla AWP. więc przy użyciu sygnatury dla CBaseEntity::Spawn jest to możliwe. Wystarczy skonkretyzować dla jakiego obiektu ma ta funkcja zostać przechwycona. W naszym przypadku dla CAWP.

Dobra, zajmijmy się tworzeniem sygnatur.
Otwieramy IDA, wybieramy bibliotekę Linuxa i szukamy.
Funkcje wirtualne są zawarte w <nazwa_klasy>::&#39;vtbl'.
Np. CBaseEntity::&#39;vtbl'.
W IDA wygląda to następująco:
Dołączona grafika
Dołączona grafika
Zapewne niektórzy się domyślają, jest to spis funkcji wirtualnych w danej klasie. Tutaj zamiast offsetów mamy id. ID Spawn w Windowsie wynosi 0, a w Linuxie 2. (zawsze +2)
Jeśli chcemy poznać id danej funkcji możemy liczyć, bądź zajrzeć do pliku addons/amxmodx/cofigs/hamdata.ini. W tym pliku mamy dokładnie podane id wszystkich (prawie) funkcji wirtualnych do wszystkich modów opartych na silniku HL. Zarówno na Linuxie jak i Windowsie.

Tutaj sygnatura za mocno się nie zmienia. Jedyna różnica jest taka, że zamiast "indentifiers" mamy "indexes".
Sygnatura funkcji wirtualnej Spawn będzie wyglądać następująco:
{
    "name" : "Spawn",
    "class" : "CBaseEntity",
    "library" : "mod",
    "indexes":
    [
        {
            "os" : "windows",
            "mod" : "cstrike",
            "value" : 0
        },
	{
            "os" : "linux",
            "mod" : "cstrike",
            "value" : 2
	}
    ]
}

Sygnaturę wrzucamy do folderu virtualFunctions zamiast do folderu functions. Reszta jest tak samo.

Kod będzie również wyglądać inaczej. zamiast użycia funkcji OrpheuGetFunction, używamy funkcji OrpheuGetFunctionFromClass. Dlaczego ? Jak już wcześniej powiedziałem, musimy "powiedzieć" kompilatorowi dla jakiej klasy ta funkcja ma zostać wykonana.
#include <amxmodx>
#include <orpheu>
new OrpheuFunction:g_pSpawn;

public plugin_init()
{
register_plugin("Orpheu Tutorial", "1.0.0", "Owner dla AMXX.PL");
g_pSpawn = OrpheuGetFunctionFromClass("weapon_awp", "Spawn", "CBaseEntity"); // pobieramy uchwyt dla funkcji CBaseEntity::Spawn
OrpheuRegisterHook(g_pSpawn, "on_AwpSpawn"); // rejetrujemy hooka
}

public OrpheuHookReturn:on_AwpSpawn(ent)
return OrpheuSupercede; // blokujemy respawn broni


No cóż, to chyba wszystko jeśli chodzi o podstawy. W przyszłości postaram się napisać coś więcej o Orpheu np. zmiana stringów, bądź edycja wybranych bajtów w biblioteki.
Zapraszam do komentowania oraz krytykowania. Każdy post mile widziany ;)

Użytkownik Owner123 edytował ten post 02.08.2011 12:52

  • +
  • -
  • 12

#2 G[o]Q

    I'm G[o]Q

  • Przyjaciel

Reputacja: 1339
Godlike

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

Napisano 23.09.2010 16:17

niezle :D ale grafike mozesz wrzucic w innym formacie i wrzucic ja do posta w [img] [./img] :D
  • +
  • -
  • 1
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

#3 mgr inż. Pavulon

    C35H60Br2N2O4

  • Przyjaciel

Reputacja: 1725
Godlike

  • Postów:6881
  • Steam:steam
  • Imię:Konrad
  • Lokalizacja:Koniecpol
Offline

Napisano 23.09.2010 16:34

No fakt. Z grafikami to niewypał. Bardzo dobra jakość png jest tu niepotrzebna - wystarczy jpg.
A klikanie każdego odnośnika żeby zobaczyć obrazek rozprasza/denerwuje.

Ogólnie wszystko fajnie, no ale nie ma przykładu na co to komu.
Na co mnie

Przykładowy kod z wykorzystaniem tej funkcji:

#include <amxmodx>
#include <orpheu>
#include <orpheu_stocks>

new g_pGameRules

public plugin_precache()
{
    OrpheuRegisterHook(OrpheuGetFunction("InstallGameRules"),"OnInstallGameRules",OrpheuHookPost)
}
public OnInstallGameRules()
{
    g_pGameRules = OrpheuGetReturn() 
}

Skoro nie wiem co robi ten kod ? :D
  • +
  • -
  • 0

#4 Owner123

    Wszechpomocny

  • Autor tematu
  • Użytkownik

Reputacja: 144
Zaawansowany

  • Postów:331
  • Lokalizacja:Barty ;]
Offline

Napisano 23.09.2010 16:48

Dobra poprawiłem to co napisaliście ;)
Format .png to sprawka imageshack, miało być .bmp :D

Użytkownik Owner123 edytował ten post 23.09.2010 16:48

  • +
  • -
  • 0

#5 G[o]Q

    I'm G[o]Q

  • Przyjaciel

Reputacja: 1339
Godlike

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

Napisano 23.09.2010 16:58

jak mozesz to tez troszku opisz co mozna zrobic uzywajac/modyfikujac powyzsze przyklady i ogolnie troszku teorii ale mimo to i tak tutek super :D
  • +
  • -
  • 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 Knopers

    Nie patrz tak na mnie !

  • Przyjaciel

Reputacja: 587
Wszechwiedzący

  • Postów:2013
  • GG:
  • Steam:steam
  • Imię:Mateusz
  • Lokalizacja:Cz-wa
Offline

Napisano 23.09.2010 17:02

No Owner good job, pewnie i tak nikt nie uwierzy jak powiem że masz 14 lat :D
Muszę się w końcu zacząć bawić w orpheu bo widzę że warto.


PS: mi to bardziej wygląda na deasemblacje jak na tego pierwszego screena z kodem :P
  • +
  • -
  • 0

#7 Ortega

    mów mi Orti

  • Power User

Reputacja: 361
Wszechpomocny

  • Postów:640
  • GG:
  • Steam:steam
  • Imię:Marcin
  • Lokalizacja:Sosnowiec
Offline

Napisano 23.09.2010 17:20

Ładny poradnik, na pewno się przyda przynajmniej w 'zaawansowanych podstawach'.

@Knopers, to jest deassembling ;)
  • +
  • -
  • 0

#8 Owner123

    Wszechpomocny

  • Autor tematu
  • Użytkownik

Reputacja: 144
Zaawansowany

  • Postów:331
  • Lokalizacja:Barty ;]
Offline

Napisano 23.09.2010 17:23

Pierwsze ukazanie się kodu to rzeczywiście deassembling.
Oczywiście że warto :D Orpheu to naprawdę coś niesamowitego. Z tego co widziałem na Alliedmodsie, to Exolent zrobił sv_airaccelerate dla pojedyńczego gracza (jedni mogą mieć 10, a inni 100, ale wszyscy domyślnie mają tyle, ile jest w tym cvarze).
Może wkrótce napisze o podmianie pamięci oraz stringów przy pomocu Orpheu.
Hah a co to za problem ? :P Wiek to przecież nie problem przy nauce :P

Użytkownik Owner123 edytował ten post 23.09.2010 17:28

  • +
  • -
  • 0

#9 Ortega

    mów mi Orti

  • Power User

Reputacja: 361
Wszechpomocny

  • Postów:640
  • GG:
  • Steam:steam
  • Imię:Marcin
  • Lokalizacja:Sosnowiec
Offline

Napisano 23.09.2010 17:28

No tak to prawda, Orpheu zmieni część środowiska amxmodx, w którym to zaawansowani modderzy nauczyli się dużo, a teraz stanie się to po prostu prostsze np. usuwanie limitów w grze.

Co do najprostszej podmiany stringu w pamięci można użyć z odpowiednia oczywiście sygnaturą, więc nie jest to takie zaś skomplikowane:
OrpheuMemoryReplace( "engineString", 0, "Error", "Blad" );

  • +
  • -
  • 0

#10 Owner123

    Wszechpomocny

  • Autor tematu
  • Użytkownik

Reputacja: 144
Zaawansowany

  • Postów:331
  • Lokalizacja:Barty ;]
Offline

Napisano 23.09.2010 17:42

Podmiana stringa to nie tylko podmiana tekstu, ale również modeli i dźwięków oraz innych plików (teoretycznie, nigdy tego nie sprawdzałem).
  • +
  • -
  • 0

#11 Ortega

    mów mi Orti

  • Power User

Reputacja: 361
Wszechpomocny

  • Postów:640
  • GG:
  • Steam:steam
  • Imię:Marcin
  • Lokalizacja:Sosnowiec
Offline

Napisano 23.09.2010 17:44

To sprawdź mój plugin Advanced File Replacer ;)
  • +
  • -
  • 0

#12 Vertricus

    Godlike

  • Przyjaciel

Reputacja: 426
Wszechobecny

  • Postów:1549
  • Lokalizacja:.
Offline

Napisano 23.09.2010 18:25

usuwanie limitów w grze.

Limity typu max ilość rzeczy które możemy precache też?:>
  • +
  • -
  • 0

#13 QTM. Peyote

    Wszechpomocny

  • Użytkownik

Reputacja: 997
Master

  • Postów:330
  • GG:
  • Steam:steam
  • Imię:Mateusz
  • Lokalizacja:Polska
Offline

Napisano 23.09.2010 18:33

Wydaje mi się, że miał na myśli rzeczy typu usuwanie czasu rundy.
  • +
  • -
  • 0

#14 Ortega

    mów mi Orti

  • Power User

Reputacja: 361
Wszechpomocny

  • Postów:640
  • GG:
  • Steam:steam
  • Imię:Marcin
  • Lokalizacja:Sosnowiec
Offline

Napisano 23.09.2010 18:43

@Verticus był gdzieś o tym wątek na allied, ale wydaje mi się że max precache jest zależne od clienta, poszukam w HLSDK jeszcze.
  • +
  • -
  • 0

#15 Jak się nazwać

    Wszechmogący

  • Power User

Reputacja: 170
Profesjonalista

  • Postów:617
  • Imię:a
  • Lokalizacja:a
Offline

Napisano 22.08.2011 03:45

moze mi ktos wyjasnic czemu e 1 register w prrcache a 2 init i czy to ma znaczenie jakies ?
  • +
  • -
  • 0
Pisze na zamówienie statystyki pod nvault. GG: 15600964

#16 Ortega

    mów mi Orti

  • Power User

Reputacja: 361
Wszechpomocny

  • Postów:640
  • GG:
  • Steam:steam
  • Imię:Marcin
  • Lokalizacja:Sosnowiec
Offline

Napisano 22.08.2011 10:08

Precache wykonuje się wcześniej niż init, a nie zawsze wiadomo czy podmiana czegoś da pożądany efekt bo może być już za późno aby to ustawić.
  • +
  • -
  • 1

#17 DarkGL

    Nie oddam ciasteczka !

  • Administrator

Reputacja: 6033
Godlike

  • Postów:10831
  • GG:
  • Steam:steam
  • Imię:Rafał
  • Lokalizacja:Warszawa
Offline

Napisano 31.03.2012 14:11

taka mała poprawka
CBaseEntity::'vtbl'
na
CBaseEntity::`vtbl'

  • +
  • -
  • 0




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

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