diff --git a/CodexForever.lua b/CodexForever.lua index abfc2fc..18aa0dd 100644 --- a/CodexForever.lua +++ b/CodexForever.lua @@ -125,7 +125,7 @@ function Forever.Load() local function Step() if not Forever.loading then return end -- zwischendurch ausgeschaltet local to = math.min(total, from + slice - 1) - Forever.count = Forever.count + Codex.Share.BuiltinAdd(list, from, to) + Forever.count = Forever.count + Codex.Share.BuiltinAdd(list, from, to, true) -- Startdaten sind geprueft from = to + 1 if from > total then Finish() diff --git a/CodexShare.lua b/CodexShare.lua index 059a294..4506af2 100644 --- a/CodexShare.lua +++ b/CodexShare.lua @@ -1511,14 +1511,38 @@ function Share.BuiltinBegin() builtin = { rec = {}, n = 0 } end -function Share.BuiltinAdd(list, from, to) +-- Startdaten sind schon geprueft (trusted = true): Kreaturen, Objekte und Quests werden ohne erneute Formatpruefung +-- und ohne Kopie uebernommen. Nur Datensaetze, bei denen die Pruefung etwas aendern wuerde (Leerzeichen am Rand, +-- Steuerzeichen, sehr lange Texte), gehen weiter durch Sanitize. +local CHECK_TEXT = { "n", "ne", "cen", "cde", "t" } +local function NeedsCheck(raw) + for i = 1, 5 do + local v = raw[CHECK_TEXT[i]] + if v ~= nil and (type(v) ~= "string" or #v > 40 or v:find("^%s") or v:find("%s$") or v:find("[|%c]")) then + return true + end + end + return false +end +Share.BuiltinTrusted = true + +function Share.BuiltinAdd(list, from, to, trusted) local accepted = 0 local P = Codex.Path for i = from or 1, to or #list do local raw = list[i] local key = type(raw) == "table" and type(raw.y) == "string" and type(raw.id) == "number" and (raw.y .. math.floor(raw.id)) or nil - local rec = key and Share.Sanitize(key, raw, raw.upd) + local rec + if key then + local y = raw.y + if trusted and (y == "u" or y == "o" or y == "q") and type(raw.upd) == "number" and raw.upd >= 1 + and raw.id >= 0 and raw.id == math.floor(raw.id) and not NeedsCheck(raw) then + rec = raw + else + rec = Share.Sanitize(key, raw, raw.upd) + end + end if rec then if rec.y == "p" then local cells = P and P.ParseChunk(rec.c) @@ -1542,9 +1566,9 @@ function Share.BuiltinDone() if Codex.Spots then Codex.Spots.Bump() end end -function Share.SetBuiltin(list) +function Share.SetBuiltin(list, trusted) Share.BuiltinBegin() - local accepted = Share.BuiltinAdd(list or {}, 1, #(list or {})) + local accepted = Share.BuiltinAdd(list or {}, 1, #(list or {}), trusted) Share.BuiltinDone() return accepted end @@ -1723,7 +1747,7 @@ local function MergeEditorFields(m, e) end end -local function MergeEntity(own, list) +local function MergeEntity(own, list, lazy) local m = {} local remoteK = 0 if own then @@ -1808,7 +1832,7 @@ local function MergeEntity(own, list) if next(m.ro) == nil then m.ro = nil end if next(m.wa) == nil then m.wa = nil end if next(m.tr) == nil then m.tr = nil end - if Codex.LearnPlanReset then Codex.LearnPlanReset() end + if not lazy and Codex.LearnPlanReset then Codex.LearnPlanReset() end if next(m.fl) == nil then m.fl = nil end if next(m.tt) == nil then m.tt = nil end if next(m.cells) == nil then m.cells = nil end @@ -1997,8 +2021,50 @@ local function BuildTTK() view.ttk = tk end +-- Reine Startdaten-Eintraege (keine eigenen und keine fremden Daten dazu) werden erst beim ersten Zugriff +-- zusammengefuehrt: in der Sicht steht bis dahin eine leere Huelle, die sich beim Lesen oder Schreiben eines Feldes +-- mit genau dem Ergebnis fuellt, das das Zusammenfuehren sofort geliefert haette. pairs() sieht alle Schluessel. +local pending = setmetatable({}, { __mode = "k" }) -- Huelle -> Startdatensatz (bleibt ueber Neuaufbauten bestehen) +local lazyMade, lazyTotal = 0, 0 +local STUB = {} + +local function Materialize(t) + local rec = pending[t] + if not rec then return end + pending[t] = nil + setmetatable(t, nil) + local list = { { s = BUILTIN, rec = rec } } + local m = rec.y == "q" and MergeQuest(nil, list) or MergeEntity(nil, list, true) + for k, v in pairs(m) do rawset(t, k, v) end + lazyMade = lazyMade + 1 +end + +STUB.__index = function(t, k) + Materialize(t) + return rawget(t, k) +end +STUB.__newindex = function(t, k, v) + Materialize(t) + rawset(t, k, v) +end + +local function NewStub(rec) + local t = setmetatable({}, STUB) + pending[t] = rec + lazyTotal = lazyTotal + 1 + return t +end + +-- Anzahl bisher zusammengefuehrter Huellen und Huellen insgesamt (seit dem letzten Neuaufbau) +function Share.LazyStats() + local waiting = 0 + for _ in pairs(pending) do waiting = waiting + 1 end + return lazyMade, lazyTotal, waiting +end + local function Rebuild() local db = Codex.db + lazyMade, lazyTotal = 0, 0 index = { u = {}, o = {}, q = {}, i = {} } xpRecs = {} ttkRecs = {} @@ -2036,8 +2102,16 @@ local function Rebuild() ttkRecs[#ttkRecs + 1] = rec elseif index[rec.y] then local bucket = index[rec.y] - bucket[rec.id] = bucket[rec.id] or {} - table.insert(bucket[rec.id], { s = BUILTIN, rec = rec }) + local cur = bucket[rec.id] + if cur == nil and rec.y ~= "i" and rec.bad == nil and rec.ed == nil and not db[KIND_OF[rec.y]][rec.id] then + bucket[rec.id] = rec -- nur Startdaten: erst beim Zugriff zusammenfuehren + else + if cur == nil then + cur = {} + bucket[rec.id] = cur + end + table.insert(cur, { s = BUILTIN, rec = rec }) + end end end view = { quests = {}, units = {}, objects = {}, ied = {}, xpb = db.xpb, names = db.names } @@ -2047,19 +2121,24 @@ local function Rebuild() out[id] = e.ed and Codex.ApplyEd(e, field) or e end for id, list in pairs(index[letter]) do - local merged - if letter == "q" then - merged = MergeQuest(db[field][id], list) + if list.y then + out[id] = NewStub(list) else - merged = MergeEntity(db[field][id], list) + local merged + if letter == "q" then + merged = MergeQuest(db[field][id], list) + else + merged = MergeEntity(db[field][id], list) + end + if merged.bad == true and not CanEditNames() then merged = nil end + if merged then merged = Codex.ApplyEd(merged, field, true) end + out[id] = merged end - if merged.bad == true and not CanEditNames() then merged = nil end - if merged then merged = Codex.ApplyEd(merged, field, true) end - out[id] = merged end end BuildXP() BuildTTK() + if Codex.LearnPlanReset then Codex.LearnPlanReset() end allDirty = false dirtyIds = {} end diff --git a/CodexUI.lua b/CodexUI.lua index ce1c2a5..d058879 100644 --- a/CodexUI.lua +++ b/CodexUI.lua @@ -15,11 +15,14 @@ local Util = FW.Util local LIST_W = 540 local ROW_H, ROW_GAP = 44, 4 -local DEFAULT_ROWS = 300 +local DEFAULT_ROWS, MIN_ROWS, MAX_ROWS_LIMIT = 100, 10, 100 local function MaxRows() local n = Codex.db and Codex.db.settings and tonumber(Codex.db.settings.listMax) - if not n or n < 50 then return DEFAULT_ROWS end - return math.floor(n) + if not n then return DEFAULT_ROWS end + n = math.floor(n) + if n < MIN_ROWS then return MIN_ROWS end + if n > MAX_ROWS_LIMIT then return MAX_ROWS_LIMIT end + return n end local LINE_H = 24 @@ -4419,7 +4422,7 @@ if UI.RegisterSettingsSection then local val = UI.CreateLabel(f, "", { size = 12 }) stack:Add(val, { fit = true, gap = 6 }) local slider = UI.CreateSlider(f, 240, { - min = 100, max = 6000, step = 100, + min = MIN_ROWS, max = MAX_ROWS_LIMIT, step = 10, get = function() return MaxRows() end, set = function(v) Codex.db.settings.listMax = v diff --git a/Freewood-OctoWoW-Codex.toc b/Freewood-OctoWoW-Codex.toc index 9099dcc..5fbc95e 100644 --- a/Freewood-OctoWoW-Codex.toc +++ b/Freewood-OctoWoW-Codex.toc @@ -3,7 +3,7 @@ ## Notes: Learns quests, creatures and drops while you play: who gives and takes a quest, rewards, objectives, drop chances. ## Notes-deDE: Lernt beim Spielen Quests, Kreaturen und Beute: wer eine Quest vergibt und annimmt, Belohnungen, Ziele, Drop-Chancen. ## Author: Lacustat -## Version: 0.1.170 +## Version: 0.1.171 ## Dependencies: Freewood-OctoWoW-Core ## OptionalDeps: Freewood-OctoWoW-CodexData, Freewood-OctoWoW-ForeverData diff --git a/Locales.lua b/Locales.lua index a7a149f..c5fe5ff 100644 --- a/Locales.lua +++ b/Locales.lua @@ -373,7 +373,7 @@ FW:AddLocale("enUS", { CODEX_GROUP_ROW = "%d open | %d active | %d done", CODEX_ZONE_UNKNOWN = "No area", CODEX_LISTMAX_HEADER = "Database list length", - CODEX_LISTMAX_NOTE = "How many rows the database list shows at most. Higher values show more entries but can slow the window down; the list refreshes the next time it is built.", + CODEX_LISTMAX_NOTE = "How many rows the database list shows at most. Fewer rows make the window faster (10 to 100); use the search to find other entries. The list refreshes the next time it is built.", CODEX_LISTMAX_VALUE = "Up to %d rows", CODEX_HINT_HEADER = "Learning hints", CODEX_HINT_NOTE = "After a level up (out of combat) or a new profession rank, a short hint in the middle of the screen shows what you can now learn from a trainer. Based on the trainers you or others have visited.", @@ -917,7 +917,7 @@ FW:AddLocale("deDE", { CODEX_GROUP_ROW = "%d offen | %d aktiv | %d erledigt", CODEX_ZONE_UNKNOWN = "Ohne Gebiet", CODEX_LISTMAX_HEADER = "Länge der Datenbank-Liste", - CODEX_LISTMAX_NOTE = "Wie viele Zeilen die Datenbank-Liste höchstens zeigt. Höhere Werte zeigen mehr Einträge, können das Fenster aber verlangsamen; die Liste übernimmt den Wert beim nächsten Aufbau.", + CODEX_LISTMAX_NOTE = "Wie viele Zeilen die Datenbank-Liste höchstens zeigt. Weniger Zeilen machen das Fenster schneller (10 bis 100); weitere Einträge findest du über die Suche. Die Liste übernimmt den Wert beim nächsten Aufbau.", CODEX_LISTMAX_VALUE = "Bis zu %d Zeilen", CODEX_HINT_HEADER = "Lern-Hinweise", CODEX_HINT_NOTE = "Nach einem Stufenaufstieg (außerhalb des Kampfes) oder einer neuen Berufsstufe zeigt ein kurzer Hinweis in der Bildschirmmitte, was du jetzt beim Lehrer lernen kannst. Grundlage sind die Lehrer, die du oder andere besucht haben.",