Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ require("CommunityAPIShared")
CommunityAPI.Client = {
ItemTooltip = require("ItemTooltipAPI/ItemTooltipAPIClient"),
Light = require("LightAPI/LightAPIClient"),
ModNews = require("ModNewsAPI/ModNewsAPIClient"),
ModSetting = require("ModSettingAPI/ModSettingAPIClient"),
Spawner = require("SpawnerAPI/SpawnerAPIClient"),
WorldSound = require("WorldSoundAPI/WorldSoundAPIClient"),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
local JsonAPI = require("CommunityAPI/JsonUtils")

---@class ModNewsAPI
local ModNewsAPI = {}
local Data = {}

--- Load the data
local function ModNewsAPILoadData()
local fileReader = getFileReader("CAPI_modNewsData.txt", true)
if not fileReader then return end
local line = fileReader:readLine()
local modNewsData = nil
if line ~= nil then
modNewsData = JsonAPI.Decode(line)
end
fileReader:close()

if modNewsData ~= nil and type(modNewsData) == "table" then
for modID, modData in pairs(modNewsData) do
for articleName, data in pairs(modData) do
if Data[modID] ~= nil and Data[modID][articleName] ~= nil then
if data.isViewed and data.lastUpdateDate == Data[modID][articleName].lastUpdateDate then
Data[modID][articleName].isViewed = true
end
end
end
end
end
end
Events.OnGameBoot.Add(ModNewsAPILoadData)

--- Add a new Article for your mod
---@param modID string The mod ID
---@param articleName string The article Name
---@param articleTextName string Article text name from Translate
---@param lastUpdateDate string String with date of last update. If you changed article and want to notify that article updated - change this param
---@return nil
function ModNewsAPI.AddArticle(modID, articleName, articleTextName, lastUpdateDate)
if Data[modID] == nil then
Data[modID] = {}
end
Data[modID][articleName] = {}
Data[modID][articleName].modID = modID
Data[modID][articleName].articleName = articleName
Data[modID][articleName].articleTextName = articleTextName
Data[modID][articleName].lastUpdateDate = lastUpdateDate
Data[modID][articleName].isViewed = false
end

--- Get all Data (readonly)
---@return table
function ModNewsAPI.GetAll()
return copyTable(Data)
end

--- Get a specific mod article (readonly)
---@param modID string The mod ID
---@param articleName string The article Name
---@return table
function ModNewsAPI.GetArticle(modID, articleName)
if Data[modID] and Data[modID][articleName] then
return copyTable(Data[modID][articleName])
end
end

--- Check if an article is viewed already
---@param modID string The mod ID
---@param articleName string The article Name
---@return boolean True if viewed
function ModNewsAPI.GetArticleIsViewed(modID, articleName)
if Data[modID] and Data[modID][articleName] then
return Data[modID][articleName].isViewed
end
end

--- Set an article as viewed
---@param modID string The mod ID
---@param articleName string The article Name
function ModNewsAPI.SetArticleAsViewed(modID, articleName)
if Data[modID] and Data[modID][articleName] then
Data[modID][articleName].isViewed = true
end
end

return ModNewsAPI
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
require("CommunityAPI")
local ModNewsAPI = CommunityAPI.Client.ModNews
local ModNewsPanel = require("ModNewsAPI/ModNewsPanel")

local FONT_HGT_MEDIUM = getTextManager():getFontHeight(UIFont.Medium)

local function renderModNewsButton(self)
ISButton.render(self)

local Data = ModNewsAPI.GetAll()
local isNewArticles = false
for _, modData in pairs(Data) do
for _, articleData in pairs(modData) do
if articleData.isViewed == false then
isNewArticles = true
end
end
end

if isNewArticles then
local x = - self.notifyIcon:getWidthOrig()/2 + self.width
local y = - self.notifyIcon:getHeightOrig()/2 - 2
self:drawTexture(self.notifyIcon, x, y, 1, 1, 1, 1)
end
end

local function onClickModNews(self)
local w = self.width * 0.8
local h = self.height * 0.8
local newsPanel = ModNewsPanel:new((self.width - w)/2, (self.height - h)/2, w, h)
newsPanel.backgroundColor = {r=0, g=0, b=0, a=0.95}
newsPanel.borderColor = {r=1, g=1, b=1, a=0.5}
newsPanel:initialise()
newsPanel:instantiate()
newsPanel:setCapture(true)
newsPanel:setAlwaysOnTop(true)
newsPanel:setAnchorRight(true)
newsPanel:setAnchorLeft(true)
newsPanel:setAnchorBottom(true)
newsPanel:setAnchorTop(true)
newsPanel:addToUIManager()
end

-- Hook
local defaultMainScreen_instantiate = MainScreen.instantiate
function MainScreen:instantiate()
defaultMainScreen_instantiate(self)

self.modNewsDetail = ISButton:new(self.width - 40 - 400, self.height - FONT_HGT_MEDIUM - 20, 120, FONT_HGT_MEDIUM + 1 * 2, getText("UI_modNews_button"), self, onClickModNews)
self.modNewsDetail.font = UIFont.Medium
self.modNewsDetail:initialise()
self.modNewsDetail.borderColor = {r=1, g=1, b=1, a=0.7}
self.modNewsDetail.textColor = {r=1, g=1, b=1, a=0.7}
self:addChild(self.modNewsDetail)
self.modNewsDetail:setAnchorLeft(false)
self.modNewsDetail:setAnchorTop(false)
self.modNewsDetail:setAnchorRight(true)
self.modNewsDetail:setAnchorBottom(true)
self.modNewsDetail.notifyIcon = getTexture("media/ui/ModNews/notifyIcon.png")
self.modNewsDetail.render = renderModNewsButton
end

-- Hook
local defaultMainScreen_setBottomPanelVisible = MainScreen.setBottomPanelVisible
function MainScreen:setBottomPanelVisible(visible)
defaultMainScreen_setBottomPanelVisible(self, visible)
if self.parent and self.parent.modNewsDetail then
self.parent.modNewsDetail:setVisible(visible)
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
require("CommunityAPI")
local ModNewsAPI = CommunityAPI.Client.ModNews
local JsonAPI = CommunityAPI.Utils.Json

local ModNewsPanel = ISPanelJoypad:derive("ModNewsPanel")

local FONT_HGT_SMALL = getTextManager():getFontHeight(UIFont.Small)
local FONT_HGT_MEDIUM = getTextManager():getFontHeight(UIFont.Medium)

function ModNewsPanel:createChildren()
self.modListBox = ISScrollingListBox:new(25, 50, self.width*0.2, self.height - 100)
self.modListBox:initialise()
self.modListBox:instantiate()
self.modListBox:setFont(UIFont.Medium, 2)
self.modListBox:setAnchorLeft(true)
self.modListBox:setAnchorRight(true)
self.modListBox:setAnchorTop(true)
self.modListBox:setAnchorBottom(true)
self.modListBox.doDrawItem = self.modListBoxItemDraw
self.modListBox.drawBorder = true
self.modListBox:setOnMouseDownFunction(self, self.onModListClick)
self:addChild(self.modListBox)

local lWid = getTextManager():MeasureStringX(UIFont.Medium, getText("UI_NewGame_Mods"))
self.modsLabel = ISLabel:new(25 + self.modListBox.width/2 - lWid/2, 16, FONT_HGT_MEDIUM, getText("UI_NewGame_Mods"), 1, 1, 1, 1, UIFont.Medium, true)
self.modsLabel:initialise()
self.modsLabel:instantiate()
self:addChild(self.modsLabel)

self.modArticleList = ISScrollingListBox:new(self.modListBox:getRight() + 25, 50, self.width*0.2, self.height - 100)
self.modArticleList:initialise()
self.modArticleList:instantiate()
self.modArticleList:setFont(UIFont.Medium, 2)
self.modArticleList:setAnchorLeft(true)
self.modArticleList:setAnchorRight(true)
self.modArticleList:setAnchorTop(true)
self.modArticleList:setAnchorBottom(true)
self.modArticleList.doDrawItem = self.modArticleItemDraw
self.modArticleList.drawBorder = true
self.modArticleList:setOnMouseDownFunction(self, self.onArcticleListClick)
self:addChild(self.modArticleList)

lWid = getTextManager():MeasureStringX(UIFont.Medium, getText("UI_modNews_articleLabel"))
self.articleLabel = ISLabel:new(self.modArticleList:getX() + self.modArticleList.width/2 - lWid/2, 16, FONT_HGT_MEDIUM, getText("UI_modNews_articleLabel"), 1, 1, 1, 1, UIFont.Medium, true)
self.articleLabel:initialise()
self.articleLabel:instantiate()
self:addChild(self.articleLabel)

local buttonHgt = FONT_HGT_SMALL + 3 * 2
self.backButton = ISButton:new(16, self.height - 10 - buttonHgt, 100, buttonHgt, getText("UI_btn_back"), self, self.onOptionMouseDown)
self.backButton.internal = "BACK"
self.backButton:initialise()
self.backButton:instantiate()
self.backButton:setAnchorLeft(true)
self.backButton:setAnchorTop(false)
self.backButton:setAnchorBottom(true)
self.backButton.borderColor = {r=1, g=1, b=1, a=0.1}
self:addChild(self.backButton)

self.articleText = ISRichTextPanel:new(self.modArticleList:getRight() + 50, 0, self.width - self.modArticleList:getRight() - 50, self.height)
self.articleText.marginRight = self.articleText.marginLeft
self.articleText:initialise()
self:addChild(self.articleText)
self.articleText:addScrollBars()

self.articleText.background = false
self.articleText.clip = true
self.articleText.autosetheight = false
self.articleText.text = ""
self.articleText:paginate()

self:populateModList()
end

function ModNewsPanel:onModListClick()
self:populateArticleList()
end

function ModNewsPanel:onArcticleListClick()
local item = self.modArticleList.items[self.modArticleList.selected].item
self:updateSettingView(item)
ModNewsAPI.SetArticleAsViewed(item.modID, item.articleName)
end

function ModNewsPanel:updateSettingView(item)
self.articleText.text = getText(item.articleTextName)
self.articleText:paginate()
end

function ModNewsPanel:populateArticleList()
local item = self.modListBox.items[self.modListBox.selected].item
self.modArticleList:clear()

for articleName, data in pairs(item) do
self.modArticleList:addItem(articleName, data)
end
end

function ModNewsPanel:populateModList()
self.modListBox:clear()

local Data = ModNewsAPI.GetAll()
for modID, modArticleData in pairs(Data) do
local modInfo = getModInfoByID(modID)
if modInfo == nil then
self.modListBox:addItem("IncorrectModID - " .. modID, modArticleData)
else
self.modListBox:addItem(modInfo:getName(), modArticleData)
end
end
end

function ModNewsPanel:modListBoxItemDraw(y, item)
local dy = (self.itemheight - FONT_HGT_MEDIUM) / 2
self:drawText(item.text, 16, y + dy, 1, 1, 1, 1, UIFont.Medium)
self:drawRectBorder(0, y, self:getWidth(), self.itemheight, 0.5, self.borderColor.r, self.borderColor.g, self.borderColor.b)

for _, data in pairs(item.item) do
local isViewed = ModNewsAPI.GetArticleIsViewed(data.modID, data.articleName)
if isViewed == false then
self:drawText("[!!!]", self.width - 50, y + dy, 0, 1, 0, 1, UIFont.Medium)
end
end
return y + self.itemheight
end

function ModNewsPanel:modArticleItemDraw(y, item)
local dy = (self.itemheight - FONT_HGT_MEDIUM) / 2
self:drawText(item.text, 16, y + dy, 1, 1, 1, 1, UIFont.Medium)
self:drawRectBorder(0, y, self:getWidth(), self.itemheight, 0.5, self.borderColor.r, self.borderColor.g, self.borderColor.b)

local isViewed = ModNewsAPI.GetArticleIsViewed(item.item.modID, item.item.articleName)
if isViewed == false then
self:drawText("[!!!]", self.width - 50, y + dy, 0, 1, 0, 1, UIFont.Medium)
end

return y + self.itemheight
end

function ModNewsPanel:onOptionMouseDown(button, x, y)
if button.internal == "BACK" then
self:setVisible(false)
self:removeFromUIManager()

local Data = ModNewsAPI.GetAll()
local fileWriter = getFileWriter("CAPI_modNewsData.txt", true, false)
fileWriter:write(JsonAPI.Encode(Data))
fileWriter:close()
end
end

function ModNewsPanel:instantiate()
self.javaObject = UIElement.new(self)
self.javaObject:setX(self.x)
self.javaObject:setY(self.y)
self.javaObject:setHeight(self.height)
self.javaObject:setWidth(self.width)
self.javaObject:setAnchorLeft(self.anchorLeft)
self.javaObject:setAnchorRight(self.anchorRight)
self.javaObject:setAnchorTop(self.anchorTop)
self.javaObject:setAnchorBottom(self.anchorBottom)
self:createChildren()
end

function ModNewsPanel:new(x, y, width, height)
local o = {}
o = ISPanelJoypad:new(x, y, width, height)
setmetatable(o, self)
self.__index = self

o.backgroundColor = {r=0, g=0, b=0, a=0.0}
o.borderColor = {r=1, g=1, b=1, a=0.0}
o.itemheightoverride = {}
o.anchorLeft = true
o.anchorRight = false
o.anchorTop = true
o.anchorBottom = false
o.colorPanel = {}

return o
end

return ModNewsPanel
39 changes: 39 additions & 0 deletions Contents/mods/CommunityAPI/media/lua/client/ModNewsAPI/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# ModNewsAPI
**Developer:** Aiteron
**Contributors:** -
**Package:** CommunityAPI.Client.ModNews

## Description
Add news article for your mod updates.

## Methods

### AddArticle(modID, articleName, articleTextName, lastUpdateDate)
Add a new Article for your mod

| Param | Type | Description |
|-----------------|--------|---------------------------------------------------------------------------------------------------------------------|
| modID | string | The mod ID |
| articleName | string | The article Name |
| articleTextName | string | Article text name from Translate |
| lastUpdateDate | string | String with date of last update. If you changed article and want to notify that article updated - change this param |

## Examples
```lua
require("CommunityAPI")
local ModNewsAPI = CommunityAPI.Client.ModNews

--- Add an article for your mod
ModNewsAPI.AddArticle(
"MyModId",
"The article name in the list",
"The article text here\nwith line breaks if desired",
"November 1st, 2021");

--- Add a translatable article for your mod
ModNewsAPI.AddArticle(
"MyModId",
getText("Translate_Article_Name"),
getText("Translate_Article_Text"),
"November 1st, 2021");
```
Loading