Autor Wątek: [Lua] Połączenie serwera/multiplayera z bazą.  (Przeczytany 4391 razy)

Offline nowofresh

  • Użytkownik

# Grudzień 14, 2010, 00:42:44
Przerobiony:
local connection = nil
local connection = nil
local null = nil
local results = { }
local max_results = 128

-- connection functions
local function connect( )
-- retrieve the settings
local server = get( "localhost" ) or "localhost"
local user = get( "piotrvx_xlor" ) or "root"
local password = get( "haslo" ) or ""
local db = get( "piotrvx_xlor" ) or "mta"
local port = get( "3306" ) or 3306
local socket = get( "nil" ) or nil

-- connect
connection = mysql_connect ( server, user, password, db, port, socket )
if connection then
if user == "root" then
setTimer( outputDebugString, 100, 1, "Connecting to your MySQL as 'root' is strongly discouraged.", 2 )
end
return true
else
outputDebugString ( "Connection to MySQL Failed.", 1 )
return false
end
end

local function disconnect( )
if connection and mysql_ping( connection ) then
mysql_close( connection )
end
end

local function checkConnection( )
if not connection or not mysql_ping( connection ) then
return connect( )
end
return true
end

addEventHandler( "onResourceStart", resourceRoot,
function( )
if not mysql_connect then
if hasObjectPermissionTo( resource, "function.shutdown" ) then
shutdown( "MySQL module missing." )
end
cancelEvent( true, "MySQL module missing." )
elseif not hasObjectPermissionTo( resource, "function.mysql_connect" ) then
if hasObjectPermissionTo( resource, "function.shutdown" ) then
shutdown( "Insufficient ACL rights for mysql resource." )
end
cancelEvent( true, "Insufficient ACL rights for mysql resource." )
elseif not connect( ) then
if connection then
outputDebugString( mysql_error( connection ), 1 )
end

if hasObjectPermissionTo( resource, "function.shutdown" ) then
shutdown( "MySQL failed to connect." )
end
cancelEvent( true, "MySQL failed to connect." )
else
null = mysql_null( )
end
end
)

addEventHandler( "onResourceStop", resourceRoot,
function( )
for key, value in pairs( results ) do
mysql_free_result( value.r )
outputDebugString( "Query not free()'d: " .. value.q, 2 )
end

disconnect( )
end
)

--

function escape_string( str )
if type( str ) == "string" then
return mysql_escape_string( connection, str )
elseif type( str ) == "number" then
return tostring( str )
end
end

local function query( str, ... )
checkConnection( )

if ( ... ) then
local t = { ... }
for k, v in ipairs( t ) do
t[ k ] = escape_string( tostring( v ) ) or ""
end
str = str:format( unpack( t ) )
end

local result = mysql_query( connection, str )
if result then
for num = 1, max_results do
if not results[ num ] then
results[ num ] = { r = result, q = str }
return num
end
end
mysql_free_result( result )
return false, "Unable to allocate result in pool"
end
return false, mysql_error( connection )
end

function query_free( str, ... )
if sourceResource == getResourceFromName( "runcode" ) then
return false
end

checkConnection( )

if ( ... ) then
local t = { ... }
for k, v in ipairs( t ) do
t[ k ] = escape_string( tostring( v ) ) or ""
end
str = str:format( unpack( t ) )
end

local result = mysql_query( connection, str )
if result then
mysql_free_result( result )
return true
end
return false, mysql_error( connection )
end

function free_result( result )
if results[ result ] then
mysql_free_result( results[ result ].r )
results[ result ] = nil
end
end

function query_assoc( str, ... )
if sourceResource == getResourceFromName( "runcode" ) then
return false
end

local t = { }
local result, error = query( str, ... )
if result then
for result, row in mysql_rows_assoc( results[ result ].r ) do
local num = #t + 1
t[ num ] = { }
for key, value in pairs( row ) do
if value ~= null then
t[ num ][ key ] = tonumber( value ) or value
end
end
end
free_result( result )
return t
end
return false, error
end

function query_assoc_single( str, ... )
if sourceResource == getResourceFromName( "runcode" ) then
return false
end

local t = { }
local result, error = query( str, ... )
if result then
local row = mysql_fetch_assoc( results[ result ].r )
if row then
for key, value in pairs( row ) do
if value ~= null then
t[ key ] = tonumber( value ) or value
end
end
free_result( result )
return t
end
free_result( result )
return false
end
return false, error
end

function query_insertid( str, ... )
if sourceResource == getResourceFromName( "runcode" ) then
return false
end

local result, error = query( str, ... )
if result then
local id = mysql_insert_id( connection )
free_result( result )
return id
end
return false, error
end

function query_affected_rows( str, ... )
if sourceResource == getResourceFromName( "runcode" ) then
return false
end

local result, error = query( str, ... )
if result then
local rows = mysql_affected_rows( connection )
free_result( result )
return rows
end
return false, error
end

Oryginalny:


local connection = nil
local connection = nil
local null = nil
local results = { }
local max_results = 128

-- connection functions
local function connect( )
-- retrieve the settings
local server = get( "server" ) or "localhost"
local user = get( "user" ) or "root"
local password = get( "password" ) or ""
local db = get( "database" ) or "mta"
local port = get( "port" ) or 3306
local socket = get( "socket" ) or nil

-- connect
connection = mysql_connect ( server, user, password, db, port, socket )
if connection then
if user == "root" then
setTimer( outputDebugString, 100, 1, "Connecting to your MySQL as 'root' is strongly discouraged.", 2 )
end
return true
else
outputDebugString ( "Connection to MySQL Failed.", 1 )
return false
end
end

local function disconnect( )
if connection and mysql_ping( connection ) then
mysql_close( connection )
end
end

local function checkConnection( )
if not connection or not mysql_ping( connection ) then
return connect( )
end
return true
end

addEventHandler( "onResourceStart", resourceRoot,
function( )
if not mysql_connect then
if hasObjectPermissionTo( resource, "function.shutdown" ) then
shutdown( "MySQL module missing." )
end
cancelEvent( true, "MySQL module missing." )
elseif not hasObjectPermissionTo( resource, "function.mysql_connect" ) then
if hasObjectPermissionTo( resource, "function.shutdown" ) then
shutdown( "Insufficient ACL rights for mysql resource." )
end
cancelEvent( true, "Insufficient ACL rights for mysql resource." )
elseif not connect( ) then
if connection then
outputDebugString( mysql_error( connection ), 1 )
end

if hasObjectPermissionTo( resource, "function.shutdown" ) then
shutdown( "MySQL failed to connect." )
end
cancelEvent( true, "MySQL failed to connect." )
else
null = mysql_null( )
end
end
)

addEventHandler( "onResourceStop", resourceRoot,
function( )
for key, value in pairs( results ) do
mysql_free_result( value.r )
outputDebugString( "Query not free()'d: " .. value.q, 2 )
end

disconnect( )
end
)

--

function escape_string( str )
if type( str ) == "string" then
return mysql_escape_string( connection, str )
elseif type( str ) == "number" then
return tostring( str )
end
end

local function query( str, ... )
checkConnection( )

if ( ... ) then
local t = { ... }
for k, v in ipairs( t ) do
t[ k ] = escape_string( tostring( v ) ) or ""
end
str = str:format( unpack( t ) )
end

local result = mysql_query( connection, str )
if result then
for num = 1, max_results do
if not results[ num ] then
results[ num ] = { r = result, q = str }
return num
end
end
mysql_free_result( result )
return false, "Unable to allocate result in pool"
end
return false, mysql_error( connection )
end

function query_free( str, ... )
if sourceResource == getResourceFromName( "runcode" ) then
return false
end

checkConnection( )

if ( ... ) then
local t = { ... }
for k, v in ipairs( t ) do
t[ k ] = escape_string( tostring( v ) ) or ""
end
str = str:format( unpack( t ) )
end

local result = mysql_query( connection, str )
if result then
mysql_free_result( result )
return true
end
return false, mysql_error( connection )
end

function free_result( result )
if results[ result ] then
mysql_free_result( results[ result ].r )
results[ result ] = nil
end
end

function query_assoc( str, ... )
if sourceResource == getResourceFromName( "runcode" ) then
return false
end

local t = { }
local result, error = query( str, ... )
if result then
for result, row in mysql_rows_assoc( results[ result ].r ) do
local num = #t + 1
t[ num ] = { }
for key, value in pairs( row ) do
if value ~= null then
t[ num ][ key ] = tonumber( value ) or value
end
end
end
free_result( result )
return t
end
return false, error
end

function query_assoc_single( str, ... )
if sourceResource == getResourceFromName( "runcode" ) then
return false
end

local t = { }
local result, error = query( str, ... )
if result then
local row = mysql_fetch_assoc( results[ result ].r )
if row then
for key, value in pairs( row ) do
if value ~= null then
t[ key ] = tonumber( value ) or value
end
end
free_result( result )
return t
end
free_result( result )
return false
end
return false, error
end

function query_insertid( str, ... )
if sourceResource == getResourceFromName( "runcode" ) then
return false
end

local result, error = query( str, ... )
if result then
local id = mysql_insert_id( connection )
free_result( result )
return id
end
return false, error
end

function query_affected_rows( str, ... )
if sourceResource == getResourceFromName( "runcode" ) then
return false
end

local result, error = query( str, ... )
if result then
local rows = mysql_affected_rows( connection )
free_result( result )
return rows
end
return false, error
end

Błąd:
http://img153.imageshack.us/img153/9229/zrzutb.png



« Ostatnia zmiana: Grudzień 14, 2010, 16:54:23 wysłana przez Xirdus »

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline wolfenstein

  • Użytkownik

# Grudzień 14, 2010, 00:44:52
Adrian, ogarnij tego screena...

Offline Karol

  • Użytkownik

# Grudzień 14, 2010, 02:18:52
Co dokładnie robi
local server = get( "server" ) or "localhost"?
Bo wydaje mi się, że funkcja get pobiera z configa wartość "server" i wpisuje ją do odpowiedniej zmiennej, a jeżeli tego w configu nie ma to domyślnie jest to localhost. Jeżeli tak jest to wpisywanie danych do bazy jako parametrów tej funkcji nie jest raczej dobrym wyjściem, jak już to wpisz to w części "or cośtam", ale to zda tylko egzamin jeżeli nie wczyta zmiennej z configa.

Offline ropuch

  • Użytkownik

# Grudzień 14, 2010, 02:30:00
Jakim cudem napisałeś ten kod nie mając ku?

Offline Lerhes

  • Użytkownik

# Grudzień 14, 2010, 11:35:14
Offtop:
Jakim cudem napisałeś ten kod nie mając ku?
Ja kiedyś miałem podobną sytuację, to kopiowałem "q" ze stron internetowych. Redagując posta mógł zrobić tak samo, albo klawiatury systemowej użyć. Teraz mam AutoHotkey, świetny program do mapowania klawiszy (w laptopie małe kuzynki urwały mi ctrl, to mam teraz go na znaczku windows, zdumiewające jak szybko się przystosowałem).

Offtop out:
nowofresh a ten skrypt  oryginalny, działa ci poprawnie ? Uruchomiłeś go?

Lerhes
« Ostatnia zmiana: Grudzień 14, 2010, 11:37:31 wysłana przez Lerhes »

Offline nowofresh

  • Użytkownik

# Grudzień 14, 2010, 12:42:52
local connection = nil
local connection = nil
local null = nil
local results = { }
local max_results = 128

local function connect( )

connection = mysql_connect ( "localhost", "piotrvx_xlor", "haslo", "piotrvx_xlor", 3306)

if connection then
if user == "root" then
setTimer( outputDebugString, 100, 1, "Connecting to your MySQL as 'root' is strongly discouraged.", 2 )
end

Znów, kurde błąd. Tylko teraz wyskakuje, ze nie można się połączyć z localhostem.
Robie to na komputerze swoim na Lanie jakby co, ale baza stoi na VPSie.

Offline Lerhes

  • Użytkownik

# Grudzień 14, 2010, 12:47:04
No to może najpierw przydało by się doprowadzić do działania ten kod oryginalny? A potem go przerabiać? Karol ci napisał rozwiązanie, zobacz sobie dokładnie co zawiera plik config. Czy jest tam pole serwer i gdzie pokazuje. Po logu który wkleiłeś, widać że jednak nie ma tam nic ciekawego, bo wkleja sobie localhost przy próbie połączenia. No to jeszcze nie jest błąd, pod warunkiem, że na twojej maszynie (czyli lokalnej) faktycznie jest uruchomiona baza MySQL. Jest? No chyba jednak nie.
Sprawdź sql\mysql.lua jak dokładnie łączy się z tą bazą, jak ona się ma nazywać, jaki jest użytkownik hasło itd. Starasz się uruchomić ten serwer z jakiegoś tutoriala? Prawdopodobnie pominąłeś jakiś ważny krok, albo źle zrobiłeś.

Btw: To już nie masz ciekawszych rzeczy do robienia tylko stawianie serwera na ten badziew? I chyba z tym pytaniem powinieneś raczej skierować się na forum GTA::SA, albo na forum twórców tego multiplayer'a.

Edit: Wcześniej też ci wyskakiwało, że nie można połączyć z localhostem.

Lerhes
« Ostatnia zmiana: Grudzień 14, 2010, 12:49:56 wysłana przez Lerhes »

Offline nowofresh

  • Użytkownik

# Grudzień 14, 2010, 12:51:08
Na ich forum to więcej pro elo skrypterów niż programistów...
Pisałem po trzy razy i każdy mówi, że źle wpisuje -.-'

Patrzcie na instrukcje instalacji tego.

## MySQL configuration

### Creating the database.
Create a new database, the server should automatically create all required tables if it can login and the needed privilegies are granted.

### Configuring the server
To make your server use your MySQL database, edit your *settings.xml* to at least contain the following settings - of course, replace the example values with the MySQL data to connect to the server.

    <settings>
        <!-- MySQL Configuration -->
        <setting name="@sql.user" value="username"/>
        <setting name="@sql.password" value="password"/>
        <setting name="@sql.database" value="database"/>
        <setting name="@sql.hostname" value="localhost"/>
        <setting name="@sql.port" value="3306"/>
        <!-- Only use this on Linux if the normal connection does fail even though using the correct username & password. -->
        <setting name="@sql.socket" value="/var/run/mysqld/mysqld.sock"/>
       
        <!-- Registration -->
        <setting name="@players.allow_registration" value="1"/><!-- Change to 0 to disable registration and show an error message -->
        <setting name="@players.registration_error_message" value="Edit this to show the user a message when registration is disabled"/>
    </settings>

## MTA Server configuration

### Obtaining the resources
To get started, clone either the [main repository](git://github.com/marcusbauer/mta-paradise.git) or your fork into *mods/deathmatch*. It should already come with all configuration files required.

### Linux
If you are using a linux server, edit your *mods/deathmatch/mtaserver.conf* and replace

        <module src="mta_mysql.dll"/>

with

        <module src="mta_mysql.so"/>

### Windows
You need to copy the file *mods/deathmatch/modules/libmysql.dll* to your *MTA Server* directory (the one with MTA Server.exe in it)

### Ready to go!

Assuming your MySQL connection details are correctly set up, all left to do is to start the MTA server. Otherwise, the server will keep shutting down on startup, look at *mods/deathmatch/logs/server.log* for a detailed error message.

Ja zrobiłem tak:
-Wrzuciłem zasoby do folderu rescources
-Folder Modules i Web tam gdzie jest folder rescource oraz plik libmysql.dll do folderu gdzie jest urchumanianie serwera MTA server
-Nadpisałem ACL.xml
-A settings.xml mój wygląda tak:
    <settings>
        <!-- MySQL Configuration -->
        <setting name="@sql.user" value="piotrvx_xlor"/>
        <setting name="@sql.password" value="haslo"/>
        <setting name="@sql.database" value="piotrvx_xlor"/>
        <setting name="@sql.hostname" value="localhost"/>
        <setting name="@sql.port" value="3306"/>

       
        <!-- Registration -->
        <setting name="@players.allow_registration" value="1"/><!-- Change to 0 to disable registration and show an error message -->
        <setting name="@players.registration_error_message" value="Edit this to show the user a message when registration is disabled"/>
    </settings>

Innym za to działa bez grzebania w plikach *LUA.

Jeżeli zna tu ktoś LUA to proszę o kontakt. Na forum to długo strasznie trwa...
GG: 314162y1 y=5
Pozdrawiam
« Ostatnia zmiana: Grudzień 14, 2010, 12:58:25 wysłana przez nowofresh »

Offline Karol

  • Użytkownik

# Grudzień 14, 2010, 13:30:46
Czyli chcesz się połączyć poprzez adres localhost z bazą danych, której na localhoście nie ma, bo jest na vpsie? I jak to ma zrobić? Telepatycznie?

Offline nowofresh

  • Użytkownik

# Grudzień 14, 2010, 13:43:19
W danych do bazy mam jako adres localhost, a więc...

Offline Karol

  • Użytkownik

# Grudzień 14, 2010, 14:02:39
W danych do bazy mam jako adres localhost, a więc...
Owszem, i gdy korzystają z niego skrypty PHP leżące na serwerze to działa, prawda? A skrypty PHP są uruchamiane na serwerze i dla nich localhost = serwer, dla Ciebie localhost = twój komputer. Jeżeli na swoim komputerze nie masz zainstalowanej bazy danych to się nie połączysz.

Dodatkowo o połączeniu z bazą na vpsie możesz raczej zapomnieć, mało który hosting pozwala na zewnętrzne połączenia z bazą, a nawet jeżeli już to tylko ze stałych ip i za specjalną prośbą.

Zalecam więc ściągnąć MySQL Server Community Edition + SQLyog.

Offline nowofresh

  • Użytkownik

# Grudzień 14, 2010, 14:05:06
Ahaa.
Zaraz spróbuje :)

Ale jak odpalałem na zakupionym serwerze gdzie baza była przydzielona do mojego serwera to i tak ten sam błąd był xD

A nie ma jakich co się ściągają te serwery mniej niż 2 godziny ?
Albo nie można się połączyć z bazą na VPSie :( ?
« Ostatnia zmiana: Grudzień 14, 2010, 14:08:12 wysłana przez nowofresh »

Offline Karol

  • Użytkownik

# Grudzień 14, 2010, 14:12:53
A nie ma jakich co się ściągają te serwery mniej niż 2 godziny ?
Z modemu korzystasz? To ma mniej niż 40MB.

Albo nie można się połączyć z bazą na VPSie :( ?
Dużo zależy od operatora, czy zezwala na zewnętrzne połączenia czy nie -  musisz się go zapytać.

Offline nowofresh

  • Użytkownik

# Grudzień 14, 2010, 14:17:36
38.9 mb = 45 minut.

Ze skryptami i pisaniem w LUA i MTA daje rade ale mam problem z nawiązaniem stałego połączenia z bazą z poziomu serwera. Nawet jak baza i serwer są u tego samego dostawcy.

Chodzi o to, że do tej bazy musi się odnieść ok. 30 plików *lua.
A ja chce tak by było kilka plików *lua związanych z bazą, które to połączenie nawiążą zamiast pozostałych.
« Ostatnia zmiana: Grudzień 14, 2010, 16:53:01 wysłana przez Xirdus »