Word of Warcraft Private Server (MariaDB naar Oracle APEX Ontwikkelen)

Door stealthgun op dinsdag 26 mei 2020 16:00 - Reacties (11)
Categorie: Algemeen, Views: 3.648

Vanwege de Corona maatregelen heb ik de laatste tijd thuis wat meer tijd over. Dus het was weer eens tijd voor een uitzoek projectje.

Ik heb al wel vaker op Private Servers van World of Warcraft gespeeld, het is een grijs gebied. Maar dacht waarom het niet zelf eens proberen op te zetten. Dat is de Shattered Sun Sever geworden.

Ik kwam uit op de CMaNGOS core, wat je nodig hebt is een Server een database en je bent klaar. Alleen nu is het jammere dat mijn "hoofd" database een Oracle 18c (XE) database is.


Dus hoe verenig je dat? De CManNGOS database staat dus nu in een MariaDB database op mijn (Gentoo) Linux server. Maar mijn website(s) draaien op Oracle APEX. Een van deze websites is dus nu ook de website van de WoW server: https://tbc.gjdwebserver.nl.

Zelf vind ik Oracle heel fijn, dit omdat het mijn werk is maar ook omdat je vrijwel alles kan doen vanuit een Oracle database. Alle mails die verstuurd worden vanuit de website komen van de Oracle Database via de "utl_smtp" procedure. Hierdoor is het mogelijk om een procedure te maken die de email verstuurd.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
create or replace PROCEDURE PROC_SEND_MAIL (v_to varchar2, v_from varchar2, v_subject varchar2, v_body varchar2) AS 

smtp_conn utl_smtp.connection;

BEGIN
smtp_conn := utl_smtp.open_connection('smtp.example.com', 25); -- SMTP on port 25 
utl_smtp.helo(smtp_conn, 'smtp.example.com');
utl_smtp.mail(smtp_conn, v_from);
utl_smtp.rcpt(smtp_conn, v_to);

utl_smtp.data(smtp_conn,
'From: From Name <'||v_from||'>' || utl_tcp.crlf ||
'To: ' || v_to || utl_tcp.crlf ||
'Subject: ' ||v_subject||utl_tcp.crlf||
'MIME-Version: 1.0'||utl_tcp.crlf||
'Content-type:text/html;charset=iso-8859-1'||utl_tcp.crlf||
utl_tcp.crlf || v_body);

utl_smtp.quit(smtp_conn);

END PROC_SEND_MAIL;


Maar hoe krijg je nou de MariaDB informatie in je Oracle Database? Het antwoord is een database link aanmaken. Wat je hiervoor als eerste nodig hebt is een ODBC koppeling naar je MariaDB database.

Daarna moet je wat aanpassingen doen in je Oracle installatie namelijk wat config bestanden aanpassen zodat je de ODBC koppeling kan gebruiken. Een goede uitleg daarover kan je hier vinden.

Als je de koppeling werkend hebt kan je hele leuke dingen doen, want je kan namelijk de Logica vanuit je Oracle database gebruiken om data te manipuleren of uit de MariaDB database te halen. Een voorbeeld hiervan zijn ingame tickets, deze zet ik om in een zelf gemaakt ticket systeem in de Oracle Database met Oracle APEX als frontend.

Ik heb een view aangemaakt die de benodigede gegevens laad vanuit de MariaDB database, dit omdat je vanuit een Procdure (of functie) niet direct de DBLINK kan aanroepen.

code:
1
2
  CREATE OR REPLACE FORCE EDITIONABLE VIEW "TBC"."VIEW_INGAME_TICKETS_FIXED" ("id", "category", "state", "status", "level", "author_guid", "author_name", "locale", "mapid", "x", "y", "z", "o", "TEXT", "created", "updated", "seen", "answered", "closed", "assignee_guid", "assignee_name", "conclusion", "notes") DEFAULT COLLATION "USING_NLS_COMP"  AS 
  select "id","category","state","status","level","author_guid","author_name","locale","mapid","x","y","z","o","TEXT","created","updated","seen","answered","closed","assignee_guid","assignee_name","conclusion","notes" from VIEW_INGAME_TICKETS_FIXED@DBLINK_TBCCHARACTERS;


Hier na kan je de data dus opslaan en manipuleren zoals ik in deze procedure doe.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
create or replace PROCEDURE PROC_MIGRATE_TICKETS AS 
v_id number;
v_charid number;
v_ticketid number;
v_accountid number;

v_date number;

v_username varchar2(32767);
v_email varchar2(32767);

v_from varchar2(32000);
v_text varchar2(32000);
v_subject varchar2(32000);
v_text_temp1 varchar2(32000);
v_text_temp2 varchar2(32000);

--Get the open tickets into the cursor with their ID's
CURSOR c_opentickets IS 
        SELECT "id","author_guid" FROM VIEW_INGAME_TICKETS_FIXED WHERE "state" = 0 AND "closed" = 0;

BEGIN
    --INSERT THE TICKETS INTO THE SYSTEM
    INSERT INTO TBL_WEB_TICKETS (INGAMETID,USERMADE,TITLE,"DESCRIPTION",STATUS,ISSUETYPE) SELECT "id",FUNCTION_FIND_ACCOUNTID_FROM_CHARID("author_guid"),'Ingame ticket',TEXT,'New','Ticket' FROM VIEW_INGAME_TICKETS_FIXED WHERE "state" = 0 AND "closed" = 0;
    COMMIT;
    
    --Loop trough the cursor and see         
    OPEN c_opentickets;
    LOOP
    FETCH c_opentickets INTO v_id,v_charid;
    EXIT WHEN c_opentickets%notfound; 
    
    SELECT TID INTO v_ticketid FROM TBL_WEB_TICKETS WHERE INGAMETID = v_id;
    v_accountid := FUNCTION_FIND_ACCOUNTID_FROM_CHARID(v_charid);
    
    --Get the email from the databse
    SELECT "email" INTO v_email FROM VIEW_ACCOUNT WHERE "id" = v_accountid;
    SELECT "username" INTO v_username FROM VIEW_ACCOUNT WHERE "id" = v_accountid;
    
    --Send a mail to the ingame character with the web ticket id
     
    SELECT EMAILFROM INTO v_from FROM TBL_WEB_EMAILS WHERE EID = 2;
    SELECT EMAILHEADER INTO v_subject FROM TBL_WEB_EMAILS WHERE EID = 2;
    SELECT EMAILTEXT INTO v_text_temp1 FROM TBL_WEB_EMAILS WHERE EID = 2;
        
    v_text_temp2 := regexp_replace(v_text_temp1, '<<username>>', v_username);
    v_text := regexp_replace(v_text_temp2, '<<ticketid>>', v_ticketid);
        
    PROC_SEND_MAIL(v_email, v_from, v_subject, v_text);
                
    END LOOP;    
    CLOSE c_opentickets;    
    
    v_date := ROUND((SYSDATE - DATE '1970-01-01' ) * 86400);
    
    --Update the MySQL database so the tickets are now closed ingame
    UPDATE VIEW_INGAME_TICKETS SET "state" = 1, "closed" = v_date WHERE "state" = 0 AND "closed" = 0;
    COMMIT;
END PROC_MIGRATE_TICKETS;


De mogelijkheden zijn nu eindeloos. Kijken hoeveel spelers online zijn en dit op de website plaatsen? Maak een view aan en het werkt.

code:
1
2
3
4
5
6
7
8
  CREATE OR REPLACE FORCE EDITIONABLE VIEW "TBC"."VIEW_PLAYER_ONLINE_COUNT" ("REALMID", "PLAYERCOUNT", "PLAYERCOUNTALLIANCE", "PLAYERCOUNTHORDE") DEFAULT COLLATION "USING_NLS_COMP"  AS 
  SELECT RL."id" AS REALMID, count(CASE WHEN CH."online" = 1 THEN 1 END) AS PLAYERCOUNT, count(CASE WHEN CH."online" = 1 AND CH."race" IN (1,2,3,4,11) THEN 1 END) AS PLAYERCOUNTALLIANCE, count(CASE WHEN CH."online" = 1 AND CH."race" IN (5,6,7,8,9,10) THEN 1 END) AS PLAYERCOUNTHORDE
FROM "realmlist"@DBLINK_TBCREALMD RL
, "account"@DBLINK_TBCREALMD AC
, "characters"@DBLINK_TBCCHARACTERS CH
WHERE AC."active_realm_id"(+) =  RL."id"
AND AC."id" = CH."account"(+)
GROUP BY RL."id";


Mensen onderschatten wel eens wat de kracht is van een Database en leggen alles op het programmeren terwijl naar mijn idee je veel kan vanuit een goede database zonder dat je een regel code buiten de database hoeft te typen. Oracle APEX draait nu eenmaal ook in de database zelf, waardoor alle data die gebruikt wordt bijna niet over en weer hoeven te worden gestuurd.

Heb je intresse in de server of wil je meer informatie over hoe APEX of Oracle werkt? Je bent altijd welkom op de Discord Server: https://discord.com/invite/rASJru2