• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

Castro AAC

I cant reproduce your bug with this computer, I will try tomorrow at home, you can get the latest compiled version from appveyor until we figure this out tho
 
It's good too, but heavy with all the features it comes with. From my experience, the only thing you would need is text formatting, tables, image upload / display, colors and linking.

Almost every WYSIWYG editor (except for Froala) is good. In Froala, if you set all the options that says "don't touch HTML" or something along this, it still will modify the final output, plus it's heavy, and in these times - page speed loading is very important for users.
 
It's good too, but heavy with all the features it comes with. From my experience, the only thing you would need is text formatting, tables, image upload / display, colors and linking.

Almost every WYSIWYG editor (except for Froala) is good. In Froala, if you set all the options that says "don't touch HTML" or something along this, it still will modify the final output, plus it's heavy, and in these times - page speed loading is very important for users.
Most users wont notice it since only admin options are the ones with the editor, however you are right, I might push towards another editor and forget about froala. Maybe Quill - Your powerful, rich text editor

Progress been bad these days as me and @forgee are busy these days, I have been trying to finish the admin shop stuff adding items, containers and soon storage values.

yE5tnQr.png
 
can you better instruct how to add a payment by paypal? in my account I did not find the part of the key.
What exactly you dont understand? I can add documentation about it on the page but its just creating a simple PayPal REST application (on developers.paypal website)
 
I followed exactly the tutorial in docs, except that on windows I had to go to the folders for the command to work (for example, dep init and dep ensure).

Before running the command "go build github.com/raggaer/castro", I ran "go get -u github.com/raggaer/castro", after attempting to run the build command, the error that I described occurred.

Sorry, I am a layman in GO, I saw your AAC and I was interested in using it to learn.

Edit:
I used the one provided in the appveyor, it works perfectly.
Well, I'm waiting for you to improve the documentation <3

Thanks

Sorry for the late reply, The limiter dependency got updated but I did not update dep, It should be working fine now ^^
 
How can it be manually configured? After (finally) installing golang, it's giving me this issue on the automatic installation:

Code:
Error! Error 1067: Invalid default value for 'updated_at'

Edit: fixed.
ERROR 1067 (42000): Invalid default value for 'created_at'

Beware, this is not linux-friendly app. Although, I will keep installing to see if it's really all that.

Edit #2: now getting when running castro
Code:
2017/11/06 02:19:47 html/template: pattern matches no files: `views/install/*.html`
nvm this was when not running from src dir

Code:
Castro - High performance content management system for Open Tibia servers

Running version:
Compiled at:

>> Encoded map is outdated. Generating new map data
2017/11/06 02:23:19 Fatal error encountered. Castro will now exit. For more information check logs/2017-November-6.txt

Getting this though.

after setup. I hope in the future this code is adaptable to users like me. Using Ubuntu 17.10

#Final edit#
Trying to re-do things, apparently I missed an environment variable (which the documents of golang say is optional). trying again then giving up.
 
Last edited:
How can it be manually configured? After (finally) installing golang, it's giving me this issue on the automatic installation:

Code:
Error! Error 1067: Invalid default value for 'updated_at'

Edit: fixed.
ERROR 1067 (42000): Invalid default value for 'created_at'

Beware, this is not linux-friendly app. Although, I will keep installing to see if it's really all that.

Edit #2: now getting when running castro
Code:
2017/11/06 02:19:47 html/template: pattern matches no files: `views/install/*.html`
nvm this was when not running from src dir

Code:
Castro - High performance content management system for Open Tibia servers

Running version:
Compiled at:

>> Encoded map is outdated. Generating new map data
2017/11/06 02:23:19 Fatal error encountered. Castro will now exit. For more information check logs/2017-November-6.txt

Getting this though.

after setup. I hope in the future this code is adaptable to users like me. Using Ubuntu 17.10

#Final edit#
Trying to re-do things, apparently I missed an environment variable (which the documents of golang say is optional). trying again then giving up.
Just check what the logs say, usually is something stupid you missing, its specified that you need to run castro on the same directory as the data folders.
You dont really need to have golang, check appveyor and get an already compiled version. I still need to finish the installation guide
 
Oh. I thought, since it was already looking for my data folder in the installation, I didn't need to do any extra stuff. Perhaps I'll give a try at it again later.
 
I sometimes still work on this, its done for the most part (missing a lua script for the shop) and I also keep updating the documentation page.

This was mainly a for-fun and learning project. I learned a lot over the course of this project and made a high quality product (with great documentation), but sadly I dont have high expectations on it beeing used since people are still using outdated gesior from 2010.
 
Just want to know if that "cloaka" means anything '-'

Testing on Windows x64.

There was an error on one of the installation files. castro_shop_checkout included a database name for some reason :oops:

You can remove the database name from the file or get the latest commit from github/appveyor should be fixed now

Thanks for testing
 
Here's a globalevent to get the shop running. It's not perfect but somewhat works.
Mind you that it doesn't work with containers yet.
Don't forget to report any bugs if you find any.

If you've already installed castro run these queries
Code:
ALTER TABLE `castro_shop_offers` ADD `charges` INT(11) DEFAULT 1;
ALTER TABLE `castro_shop_checkout` MODIFY `offer` VARCHAR(255);
ALTER TABLE `castro_shop_checkout` MODIFY `amount` VARCHAR(255);

Some edits found in this commit are required for the script to function properly

Code:
<globalevent name="castro shop" interval="20000" script="castroshop.lua"/>

castroshop.lua
Lua:
-- to be on the safe side add a mailbox that's unreachable for players
local mailboxPos = Position(x,y,z)

local function castroParcel(list, name)

    local container = Game.createItem(2595, 1)
    local label = container:addItem(2599, 1)
    label:setAttribute(ITEM_ATTRIBUTE_TEXT, name)

    -- available slots in parcel after label has been added
    local slots = 9

    for k,v in pairs(list) do

        local itemid = v[1]
        local amount = v[2]
        local itemType = ItemType(itemid)
      
        if itemType:isStackable() then
            if amount <= 100 then
                container:addItem(itemid, amount)
                slots = slots - 1
            else
                if amount % 100 > 0 then
                    container:addItem(itemid,amount%100)
                end

                amount = amount - amount%100
                local floor = math.floor(amount/100)

                -- since there's only 9 free slots in a parcel we shouldn't loop more than 9 times
                for a = 1, floor < 10 and floor or 9 do
                    container:addItem(itemid,100)
                    amount = amount - 100
                    slots = slots - 1
                    if slots == 0 then
                        v[2] = amount
                        container:moveTo(mailboxPos)
                        castroParcel(list, name)
                        return
                    end
                end
                -- if there's items left just send another parcel
                v[2] = amount
                if amount > 0 then
                    castroParcel(list, name)
                    container:moveTo(mailboxPos)
                    return
                end
            end
        else
            -- the previous 2 comments applies here as well
            for a = 1, amount < 10 and amount or 9 do
                container:addItem(itemid, v[3])
                amount = amount - 1
                slots = slots - 1
                if slots == 0 then
                    v[2] = amount
                    container:moveTo(mailboxPos)
                    castroParcel(list, name)
                    return
                end
            end
            v[2] = amount
            if amount > 0 then
                castroParcel(list, name)
                container:moveTo(mailboxPos)
                return
            end
        end
    end -- end for loop

    container:moveTo(mailboxPos)
end

function onThink(interval, lastExecution)

    local count = db.storeQuery("SELECT COUNT(*) FROM `castro_shop_checkout` WHERE `given` = 0;")
    if count == 0 then return true end

    local given = ""

    for i = 0,count do
        local checkout = db.storeQuery("SELECT * FROM `castro_shop_checkout` WHERE `given` = 0 LIMIT "..i..",1")
        if checkout ~= false then
            local name = result.getDataString(checkout, "player")
            local shop_ids = result.getDataString(checkout, "offer")
            local multipliers = result.getDataString(checkout, "amount")

            local offerList = string.split(shop_ids, ",")
            local amountList = string.split(multipliers, ",")

            -- itemlist example = {{itemid,amount,charges},{itemid,amount,charges}}
            local itemlist = {}

            if getPlayerByName(name) then
                for k,v in pairs(offerList) do  
                    local offers = db.storeQuery("SELECT * FROM `castro_shop_offers` WHERE id = "..tonumber(v).."")
                    local itemid = result.getDataInt(offers, "give_item")
                    local amount = result.getDataInt(offers, "give_item_amount")
                    local charges = result.getDataInt(offers, "charges")
                    itemlist[#itemlist+1] = {itemid,amount * amountList[k],charges}
                end

                castroParcel(itemlist, name)
                given = given .. result.getDataInt(checkout, "id") .. ", "
            end
        end
        result.free(offers)
        result.free(checkout)
    end

    result.free(count)

    if given ~= "" then
        given = string.sub(given, 1,-3)
        db.query("UPDATE `castro_shop_checkout` SET given = 1 WHERE `id` IN("..given..")")
    end

    return true
end

make sure you have the string.split function in global.lua if not add it
Lua:
string.split = function(str, sep)
    local res = {}
    for v in str:gmatch("([^" .. sep .. "]+)") do
        res[#res + 1] = v
    end
    return res
end

Thanks for the help. The proyect is kinda dead, but now it should have everything needed.
 
Here's a globalevent that instantly parcels orders to players inbox.
Don't forget to report bugs if you find any.

If you installed castro prior to this commit run these queries
Code:
ALTER TABLE `castro_shop_offers` ADD `charges` INT(11) DEFAULT 1;
ALTER TABLE `castro_shop_offers` ADD `container_give_charges` INT(11) DEFAULT 1;
ALTER TABLE `castro_shop_checkout` MODIFY `offer` VARCHAR(255);
ALTER TABLE `castro_shop_checkout` MODIFY `amount` VARCHAR(255);

Make sure your local castro aac is up to date with the one on github!

In case you're confused about how to make a shop offer with containers
k5VeOj2.gif

Code:
<globalevent name="castro shop" interval="1000" script="castroshop.lua"/>

castroshop.lua
Lua:
-- to be on the safe side add a mailbox that's unreachable for players
local mailboxPos = Position(x,y,z)

local function castroParcel(list, name)
    local container = Game.createItem(2595, 1)
    local label = container:addItem(2599, 1)
    label:setAttribute(ITEM_ATTRIBUTE_TEXT, name)
    -- available slots in parcel after label has been added
    local slots = 9

    for k,v in pairs(list) do

        local itemid = tonumber(v[1])
        local amount = tonumber(v[2])
        local itemType = ItemType(itemid)
    
        if itemType:isStackable() then
            if amount <= 100 then
                container:addItem(itemid, amount)
                slots = slots - 1
            else
                if amount % 100 > 0 then
                    container:addItem(itemid,amount%100)
                end

                amount = amount - amount%100
                local floor = math.floor(amount/100)

                -- since there's only 9 free slots in a parcel we shouldn't loop more than 9 times
                for a = 1, floor < 10 and floor or 9 do
                    container:addItem(itemid,100)
                    amount = amount - 100
                    slots = slots - 1
                    if slots == 0 then
                        v[2] = amount
                        container:moveTo(mailboxPos)
                        castroParcel(list, name)
                        return
                    end
                end
                -- if there's items left just send another parcel
                v[2] = amount
                if amount > 0 then
                    castroParcel(list, name)
                    container:moveTo(mailboxPos)
                    return
                end
            end
        else
            -- the previous 2 comments applies here as well
            for a = 1, amount < 10 and amount or 9 do

                -- the container stuff is mostly just copied from it's parent loop
                -- things that changed: "v" is now "value", "container:" is now "bp:"
                -- & "slots" has been removed since we specify how many items the bp should contain on the website.
                -- if you added more items on the website than the containers specified size in items.xml well... jokes on you HAHA.
                -- nah but seriously, people won't be happy if they receive less than what they paid for.
                if #v[4] > 0 then
                    local bp = Game.createItem(itemid, 1)

                    for key,value in pairs(v[4]) do

                        local itemid = tonumber(value[1])
                        local amount = tonumber(value[2])
                        local itemType = ItemType(itemid)

                        if itemType:isStackable() then
                            if amount <= 100 then
                                bp:addItem(itemid, amount)
                            else
                                if amount % 100 > 0 then
                                    bp:addItem(itemid,amount%100)
                                end

                                amount = amount - amount%100
                                local floor = math.floor(amount/100)

                                for a = 1,floor do
                                    bp:addItem(itemid,100)
                                    amount = amount - 100
                                end
                            end
                        else
                            for a = 1, amount do
                                bp:addItem(itemid, value[3])
                            end
                        end
                    end -- end for loop
                    container:addItemEx(bp)
                else  -- done with container shits
                    container:addItem(itemid, v[3])
                end
                amount = amount - 1
                slots = slots - 1
                if slots == 0 then
                    v[2] = amount
                    container:moveTo(mailboxPos)
                    castroParcel(list, name)
                    return
                end
            end
            v[2] = amount
            if amount > 0 then
                castroParcel(list, name)
                container:moveTo(mailboxPos)
                return
            end
        end
    end -- end for loop

    container:moveTo(mailboxPos)
end

function onThink(interval, lastExecution)

    local count = db.storeQuery("SELECT COUNT(*) FROM `castro_shop_checkout` WHERE `given` = 0;")
    count = result.getDataInt(count, "COUNT(*)")
    if count == 0 then return true end

    local given = ""

    for i = 0,count do
        local checkout = db.storeQuery("SELECT * FROM `castro_shop_checkout` WHERE `given` = 0 LIMIT "..i..",1")
        if checkout ~= false then
            local name = result.getDataString(checkout, "player")

            local shop_ids = result.getDataString(checkout, "offer")
            local multipliers = result.getDataString(checkout, "amount")

            local offerList = string.split(shop_ids, ",")
            local amountList = string.split(multipliers, ",")

            local itemlist = {}

            for k,v in pairs(offerList) do
                local offers = db.storeQuery("SELECT * FROM `castro_shop_offers` WHERE id = "..tonumber(v).."")
                local itemid = result.getDataInt(offers, "give_item")
                local amount = result.getDataInt(offers, "give_item_amount")
                local charges = result.getDataInt(offers, "charges")
            
                local c_list = {} -- container list
                if result.getDataString(offers, "container_give_item") ~= "" then

                    c_id = string.split(result.getDataString(offers, "container_give_item"), ",")
                    c_count = string.split(result.getDataString(offers, "container_give_amount"), ",")
                    c_charges = string.split(result.getDataString(offers, "container_give_charges"), ",")
                
                    for key,value in pairs(c_id) do
                        c_list[#c_list+1] = {value, c_count[key], c_charges[key]} -- join them into 1 table
                    end
            
                end
            
                itemlist[#itemlist+1] = {itemid,amount * amountList[k],charges,c_list}
            end

            castroParcel(itemlist, name)
            given = given .. result.getDataInt(checkout, "id") .. ", "
        end
        result.free(offers)
        result.free(checkout)
    end

    result.free(count)

    if given ~= "" then
        given = string.sub(given, 1,-3)
        db.query("UPDATE `castro_shop_checkout` SET given = 1 WHERE `id` IN("..given..")")
    end

    return true
end

make sure you have the string.split function in global.lua if not add it
Lua:
string.split = function(str, sep)
    local res = {}
    for v in str:gmatch("([^" .. sep .. "]+)") do
        res[#res + 1] = v
    end
    return res
end
 
Last edited:
NOW IT WORKS WITH CONTAINERS!
Here's a globalevent that instantly parcels orders to players inbox.
Don't forget to report bugs if you find any.

If you installed castro prior to this commit run these queries
Code:
ALTER TABLE `castro_shop_offers` ADD `charges` INT(11) DEFAULT 1;
ALTER TABLE `castro_shop_offers` ADD `container_give_charges` INT(11) DEFAULT 1;
ALTER TABLE `castro_shop_checkout` MODIFY `offer` VARCHAR(255);
ALTER TABLE `castro_shop_checkout` MODIFY `amount` VARCHAR(255);

Make sure your local castro aac is up to date with the one on github!
as the main repo has yet to be updated during the making of this post you can get the current latest version from my fork

In case you're confused about how to make a shop offer with containers
k5VeOj2.gif

Code:
<globalevent name="castro shop" interval="1000" script="castroshop.lua"/>

castroshop.lua
Lua:
-- to be on the safe side add a mailbox that's unreachable for players
local mailboxPos = Position(x,y,z)

local function castroParcel(list, name)
    local container = Game.createItem(2595, 1)
    local label = container:addItem(2599, 1)
    label:setAttribute(ITEM_ATTRIBUTE_TEXT, name)
    -- available slots in parcel after label has been added
    local slots = 9

    for k,v in pairs(list) do

        local itemid = tonumber(v[1])
        local amount = tonumber(v[2])
        local itemType = ItemType(itemid)
     
        if itemType:isStackable() then
            if amount <= 100 then
                container:addItem(itemid, amount)
                slots = slots - 1
            else
                if amount % 100 > 0 then
                    container:addItem(itemid,amount%100)
                end

                amount = amount - amount%100
                local floor = math.floor(amount/100)

                -- since there's only 9 free slots in a parcel we shouldn't loop more than 9 times
                for a = 1, floor < 10 and floor or 9 do
                    container:addItem(itemid,100)
                    amount = amount - 100
                    slots = slots - 1
                    if slots == 0 then
                        v[2] = amount
                        container:moveTo(mailboxPos)
                        castroParcel(list, name)
                        return
                    end
                end
                -- if there's items left just send another parcel
                v[2] = amount
                if amount > 0 then
                    castroParcel(list, name)
                    container:moveTo(mailboxPos)
                    return
                end
            end
        else
            -- the previous 2 comments applies here as well
            for a = 1, amount < 10 and amount or 9 do

                -- the container stuff is mostly just copied from it's parent loop
                -- things that changed: "v" is now "value", "container:" is now "bp:"
                -- & "slots" has been removed since we specify how many items the bp should contain on the website.
                -- if you added more items on the website than the containers specified size in items.xml well... jokes on you HAHA.
                -- nah but seriously, people won't be happy if they receive less than what they paid for.
                if #v[4] > 0 then
                    local bp = Game.createItem(itemid, 1)

                    for key,value in pairs(v[4]) do

                        local itemid = tonumber(value[1])
                        local amount = tonumber(value[2])
                        local itemType = ItemType(itemid)

                        if itemType:isStackable() then
                            if amount <= 100 then
                                bp:addItem(itemid, amount)
                            else
                                if amount % 100 > 0 then
                                    bp:addItem(itemid,amount%100)
                                end

                                amount = amount - amount%100
                                local floor = math.floor(amount/100)

                                for a = 1,floor do
                                    bp:addItem(itemid,100)
                                    amount = amount - 100
                                end
                            end
                        else
                            for a = 1, amount do
                                bp:addItem(itemid, value[3])
                            end
                        end
                    end -- end for loop
                    container:addItemEx(bp)
                else  -- done with container shits
                    container:addItem(itemid, v[3])
                end
                amount = amount - 1
                slots = slots - 1
                if slots == 0 then
                    v[2] = amount
                    container:moveTo(mailboxPos)
                    castroParcel(list, name)
                    return
                end
            end
            v[2] = amount
            if amount > 0 then
                castroParcel(list, name)
                container:moveTo(mailboxPos)
                return
            end
        end
    end -- end for loop

    container:moveTo(mailboxPos)
end

function onThink(interval, lastExecution)

    local count = db.storeQuery("SELECT COUNT(*) FROM `castro_shop_checkout` WHERE `given` = 0;")
    count = result.getDataInt(count, "COUNT(*)")
    if count == 0 then return true end

    local given = ""

    for i = 0,count do
        local checkout = db.storeQuery("SELECT * FROM `castro_shop_checkout` WHERE `given` = 0 LIMIT "..i..",1")
        if checkout ~= false then
            local name = result.getDataString(checkout, "player")

            local shop_ids = result.getDataString(checkout, "offer")
            local multipliers = result.getDataString(checkout, "amount")

            local offerList = string.split(shop_ids, ",")
            local amountList = string.split(multipliers, ",")

            local itemlist = {}

            for k,v in pairs(offerList) do 
                local offers = db.storeQuery("SELECT * FROM `castro_shop_offers` WHERE id = "..tonumber(v).."")
                local itemid = result.getDataInt(offers, "give_item")
                local amount = result.getDataInt(offers, "give_item_amount")
                local charges = result.getDataInt(offers, "charges")
             
                local c_list = {} -- container list
                if result.getDataString(offers, "container_give_item") ~= "" then

                    c_id = string.split(result.getDataString(offers, "container_give_item"), ",")
                    c_count = string.split(result.getDataString(offers, "container_give_amount"), ",")
                    c_charges = string.split(result.getDataString(offers, "container_give_charges"), ",")
                 
                    for key,value in pairs(c_id) do
                        c_list[#c_list+1] = {value, c_count[key], c_charges[key]} -- join them into 1 table
                    end
             
                end
             
                itemlist[#itemlist+1] = {itemid,amount * amountList[k],charges,c_list}
            end

            castroParcel(itemlist, name)
            given = given .. result.getDataInt(checkout, "id") .. ", "
        end
        result.free(offers)
        result.free(checkout)
    end

    result.free(count)

    if given ~= "" then
        given = string.sub(given, 1,-3)
        db.query("UPDATE `castro_shop_checkout` SET given = 1 WHERE `id` IN("..given..")")
    end

    return true
end

make sure you have the string.split function in global.lua if not add it
Lua:
string.split = function(str, sep)
    local res = {}
    for v in str:gmatch("([^" .. sep .. "]+)") do
        res[#res + 1] = v
    end
    return res
end

Very nice, my favorite aac :3
 
Back
Top