迁移后更改

This commit is contained in:
HKXluo
2025-11-12 12:06:16 +08:00
parent c02cf496e1
commit 65ba29bdca
18 changed files with 1493239 additions and 1493328 deletions

View File

@@ -1,54 +1,54 @@
<a href=#en>English</a> <a href=#zh>中文</a>
<div id="en"></div>
## Introduction
A pixel-based UTF-8 printing program
![image1](https://github.com/user-attachments/assets/82b2e002-77cf-4805-a326-62ae01ecabc2)
> $\color{red} \bf Note:$
> The CC compiler reads UTF-8 characters as '?',
> `print("Hello World")` has the same effect as `print("????")`.
> To fix this, read files in `"rb"` mode for proper input handling.
## How to Create Fonts
- Font files should return a table where keys are UTF-8 code points, and values are corresponding character bitmaps.
- Each bitmap is a table of equal-length strings representing a 2x3 pixel grid defined by Computer Craft. To use the bottom-right pixel, subtract 128 from the char code to invert `backgroundColor` and `textColor`.
- A single font file may contain bitmaps of different sizes, but it **must** include a bitmap for 'H' (ASCII:72) to indicate the maximum height of the font.
- The final output uses the maximum bitmap height in the FontFamily as the baseline for bottom-aligned text.
- The FontFamily **must** include a '-' (ASCII:45) bitmap for potential word splitting during auto-wrapping.
## Technical Details
- `require` a fusion-pixel-12px font consumes approximately **10.5MB** of memory.
- `require` a fusion-pixel-8px font consumes approximately **6MB** of memory.
- 8px characters occupy 3 rows vertically, while 12px characters occupy 4 rows.
- Fonts are sourced from <a href="https://github.com/TakWolf/fusion-pixel-font/releases">fusion-pixel-font</a>.
<div id="zh"></div>
## 介绍
一个基于像素打印的utf8打印程序
![image1](https://github.com/user-attachments/assets/82b2e002-77cf-4805-a326-62ae01ecabc2)
> $\color{red} \bf 注意:$
> CC 编译器会把utf8字符读作 '?',
> `print("你好世界")``print("????")` 的效果相同, 可以`"rb"`模式读取文件以设置输入
## 如何制作Font
- 字体文件返回一个table键值为utf8编码值为和对应字体的bitmap。
- bitmap为一个包含等长string的tablestring中的char属于computer craft定义的2*3像素点阵如需使用右下角像素将char的码值减128表示反转backgroundColor 和 textColor
- 单个字体文件中可以有不同尺寸的bitmap且**需要**有'H'(ascII:72)的bitmap表示该文件中最大bitmap高度
- 会以FontFamily出现的最大bitmap高度为基准最终输出下对齐的文本
- FontFamily中**需要**'-'(ascII:45)的bitmap以供自动换行时可能的切断单词使用
## 技术细节
- `require`一个fusion-pixel-12px字体大约消耗**10.5MB**内存
- `require`一个fusion-pixel-8px字体大约消耗**6MB**内存
- 8px字符实际占用3格高的字符数, 12px字符实际占用4格高
- 字体来自 <a href="https://github.com/TakWolf/fusion-pixel-font/releases"> fusion-pixel-font </a>
<a href=#en>English</a> <a href=#zh>中文</a>
<div id="en"></div>
## Introduction
A pixel-based UTF-8 printing program
![image1](https://github.com/user-attachments/assets/82b2e002-77cf-4805-a326-62ae01ecabc2)
> $\color{red} \bf Note:$
> The CC compiler reads UTF-8 characters as '?',
> `print("Hello World")` has the same effect as `print("????")`.
> To fix this, read files in `"rb"` mode for proper input handling.
## How to Create Fonts
- Font files should return a table where keys are UTF-8 code points, and values are corresponding character bitmaps.
- Each bitmap is a table of equal-length strings representing a 2x3 pixel grid defined by Computer Craft. To use the bottom-right pixel, subtract 128 from the char code to invert `backgroundColor` and `textColor`.
- A single font file may contain bitmaps of different sizes, but it **must** include a bitmap for 'H' (ASCII:72) to indicate the maximum height of the font.
- The final output uses the maximum bitmap height in the FontFamily as the baseline for bottom-aligned text.
- The FontFamily **must** include a '-' (ASCII:45) bitmap for potential word splitting during auto-wrapping.
## Technical Details
- `require` a fusion-pixel-12px font consumes approximately **10.5MB** of memory.
- `require` a fusion-pixel-8px font consumes approximately **6MB** of memory.
- 8px characters occupy 3 rows vertically, while 12px characters occupy 4 rows.
- Fonts are sourced from <a href="https://github.com/TakWolf/fusion-pixel-font/releases">fusion-pixel-font</a>.
<div id="zh"></div>
## 介绍
一个基于像素打印的utf8打印程序
![image1](https://github.com/user-attachments/assets/82b2e002-77cf-4805-a326-62ae01ecabc2)
> $\color{red} \bf 注意:$
> CC 编译器会把utf8字符读作 '?',
> `print("你好世界")``print("????")` 的效果相同, 可以`"rb"`模式读取文件以设置输入
## 如何制作Font
- 字体文件返回一个table键值为utf8编码值为和对应字体的bitmap。
- bitmap为一个包含等长string的tablestring中的char属于computer craft定义的2*3像素点阵如需使用右下角像素将char的码值减128表示反转backgroundColor 和 textColor
- 单个字体文件中可以有不同尺寸的bitmap且**需要**有'H'(ascII:72)的bitmap表示该文件中最大bitmap高度
- 会以FontFamily出现的最大bitmap高度为基准最终输出下对齐的文本
- FontFamily中**需要**'-'(ascII:45)的bitmap以供自动换行时可能的切断单词使用
## 技术细节
- `require`一个fusion-pixel-12px字体大约消耗**10.5MB**内存
- `require`一个fusion-pixel-8px字体大约消耗**6MB**内存
- 8px字符实际占用3格高的字符数, 12px字符实际占用4格高
- 字体来自 <a href="https://github.com/TakWolf/fusion-pixel-font/releases"> fusion-pixel-font </a>

View File

@@ -0,0 +1,30 @@
## 介绍
此仓库克隆自https://github.com/AAAB60/computer-craft-programs/tree/main
对其进行修改以共liulikeji程序使用
## 以下为原本介绍
一个基于像素打印的utf8打印程序
> $\color{red} \bf 注意:$
> CC 编译器会把utf8字符读作 '?',
> `print("你好世界")` 与 `print("????")` 的效果相同, 可以`"rb"`模式读取文件以设置输入
## 如何制作Font
- 字体文件返回一个table键值为utf8编码值为和对应字体的bitmap。
- bitmap为一个包含等长string的tablestring中的char属于computer craft定义的2*3像素点阵如需使用右下角像素将char的码值减128表示反转backgroundColor 和 textColor
- 单个字体文件中可以有不同尺寸的bitmap且**需要**有'H'(ascII:72)的bitmap表示该文件中最大bitmap高度
- 会以FontFamily出现的最大bitmap高度为基准最终输出下对齐的文本
- FontFamily中**需要**'-'(ascII:45)的bitmap以供自动换行时可能的切断单词使用
## 技术细节
- `require`一个fusion-pixel-12px字体大约消耗**10.5MB**内存
- `require`一个fusion-pixel-8px字体大约消耗**6MB**内存
- 8px字符实际占用3格高的字符数, 12px字符实际占用4格高
- 字体来自 <a href="https://github.com/TakWolf/fusion-pixel-font/releases"> fusion-pixel-font </a>

View File

@@ -1,74 +1,74 @@
---@module "cctAPI"
local monitor = peripheral.find("monitor")
local computer = term.redirect(monitor)
-- suggested
monitor.setTextScale(0.5)
term.setBackgroundColor(colors.black)
term.setTextColor(colors.white)
term.clear()
term.setCursorPos(1, 1)
local function pirntBorderNum()
local termWidth, termHeight = term.getSize()
local n = math.floor((termWidth - 1) / 10) + 1
local str = "0123456789"
local tc = string.rep("48", 5)
local bc = string.rep("84", 5)
term.setCursorPos(1, 1)
for i = 1, n do
term.blit(str, tc, bc)
end
local num = 1
local colorToggle = false
term.setCursorPos(1, 2)
for y = 2, termHeight do
term.setCursorPos(1, y)
if colorToggle then
term.setBackgroundColor(colors.lightGray)
term.setTextColor(colors.yellow)
colorToggle = false
else
term.setBackgroundColor(colors.yellow)
term.setTextColor(colors.lightGray)
colorToggle = true
end
term.write(tostring(num))
num = num + 1
if num == 10 then
num = 0
end
end
term.setCursorPos(2, 2)
term.setBackgroundColor(colors.black)
term.setTextColor(colors.white)
end
pirntBorderNum()
local M = require("utf8textutils")
-- NOTION:
-- CC compiler reads utf8 code as '?'
-- "print("你好世界")" will act the same as "print("????")"
-- read file in "rb" mode instead
local file = fs.open("text", "rb")
M.printUtf8(file.readLine())
local cfg1 = M.getCfg()
cfg1.fontFamily = M.getFontFamily("fonts/fusion-pixel-8px-proportional-zh_hans")
cfg1.textColor = colors.blue
cfg1.backgroundColor = colors.green
cfg1.autoWrapMode = "b"
M.printUtf8(M.sub(file.readLine(), 3, -1), cfg1)
local samplestr = "abcdefghijklmnopqrstuvwxyz"
local samplestr2 = samplestr:upper()
local samplestr1 = "0123456789"
cfg1.fontFamily = M.getFontFamily("fonts/fusion-pixel-12px-proportional-zh_hans")
--only if no utf8 character in str
M.printUtf8(samplestr, cfg1)
M.printUtf8(samplestr2, cfg1)
---@module "cctAPI"
local monitor = peripheral.find("monitor")
local computer = term.redirect(monitor)
-- suggested
monitor.setTextScale(0.5)
term.setBackgroundColor(colors.black)
term.setTextColor(colors.white)
term.clear()
term.setCursorPos(1, 1)
local function pirntBorderNum()
local termWidth, termHeight = term.getSize()
local n = math.floor((termWidth - 1) / 10) + 1
local str = "0123456789"
local tc = string.rep("48", 5)
local bc = string.rep("84", 5)
term.setCursorPos(1, 1)
for i = 1, n do
term.blit(str, tc, bc)
end
local num = 1
local colorToggle = false
term.setCursorPos(1, 2)
for y = 2, termHeight do
term.setCursorPos(1, y)
if colorToggle then
term.setBackgroundColor(colors.lightGray)
term.setTextColor(colors.yellow)
colorToggle = false
else
term.setBackgroundColor(colors.yellow)
term.setTextColor(colors.lightGray)
colorToggle = true
end
term.write(tostring(num))
num = num + 1
if num == 10 then
num = 0
end
end
term.setCursorPos(2, 2)
term.setBackgroundColor(colors.black)
term.setTextColor(colors.white)
end
pirntBorderNum()
local M = require("utf8textutils")
-- NOTION:
-- CC compiler reads utf8 code as '?'
-- "print("你好世界")" will act the same as "print("????")"
-- read file in "rb" mode instead
local file = fs.open("text", "rb")
M.printUtf8(file.readLine())
local cfg1 = M.getCfg()
cfg1.fontFamily = M.getFontFamily("fonts/fusion-pixel-8px-proportional-zh_hans")
cfg1.textColor = colors.blue
cfg1.backgroundColor = colors.green
cfg1.autoWrapMode = "b"
M.printUtf8(M.sub(file.readLine(), 3, -1), cfg1)
local samplestr = "abcdefghijklmnopqrstuvwxyz"
local samplestr2 = samplestr:upper()
local samplestr1 = "0123456789"
cfg1.fontFamily = M.getFontFamily("fonts/fusion-pixel-12px-proportional-zh_hans")
--only if no utf8 character in str
M.printUtf8(samplestr, cfg1)
M.printUtf8(samplestr2, cfg1)
M.printUtf8(samplestr1, cfg1)

View File

@@ -1,49 +1,49 @@
---@module "cctAPI"
local monitor = peripheral.find("monitor")
local computer = term.redirect(monitor)
-- suggested
monitor.setTextScale(0.5)
term.clear()
term.setCursorPos(1, 1)
local M = require("utf8textutils")
---@param str string
---@param fps number films per second
local function pirntScrolling(str, fps)
str = str .. " "
local termWidth = term.getSize()
local cfg1 = M.getCfg("noauto")
cfg1.masking = { 2, 2, termWidth - 1, cfg1.fontFamily.maxHeight + 1 }
local spf = 1 / fps
---@type FontFamily
local fontFamily = cfg1.fontFamily
local wid = 0
for _, code in M.codes(str) do
local bm = M.getCharMap(code, fontFamily)
wid = wid + #bm[1]
end
local cursorX = 2
local cursorY = 2
local maskingWidth = cfg1.masking[3] - cfg1.masking[1]
local repeatNum = math.max(maskingWidth, wid)
while true do
cursorX = 2
for i = 1, repeatNum do
term.setCursorPos(cursorX, cursorY)
M.printUtf8(str, cfg1)
term.setCursorPos(cursorX + repeatNum, cursorY)
M.printUtf8(str, cfg1)
cursorX = cursorX - 1
os.sleep(spf)
end
end
end
pirntScrolling("hello -- by AAAB60", 5)
---@module "cctAPI"
local monitor = peripheral.find("monitor")
local computer = term.redirect(monitor)
-- suggested
monitor.setTextScale(0.5)
term.clear()
term.setCursorPos(1, 1)
local M = require("utf8textutils")
---@param str string
---@param fps number films per second
local function pirntScrolling(str, fps)
str = str .. " "
local termWidth = term.getSize()
local cfg1 = M.getCfg("noauto")
cfg1.masking = { 2, 2, termWidth - 1, cfg1.fontFamily.maxHeight + 1 }
local spf = 1 / fps
---@type FontFamily
local fontFamily = cfg1.fontFamily
local wid = 0
for _, code in M.codes(str) do
local bm = M.getCharMap(code, fontFamily)
wid = wid + #bm[1]
end
local cursorX = 2
local cursorY = 2
local maskingWidth = cfg1.masking[3] - cfg1.masking[1]
local repeatNum = math.max(maskingWidth, wid)
while true do
cursorX = 2
for i = 1, repeatNum do
term.setCursorPos(cursorX, cursorY)
M.printUtf8(str, cfg1)
term.setCursorPos(cursorX + repeatNum, cursorY)
M.printUtf8(str, cfg1)
cursorX = cursorX - 1
os.sleep(spf)
end
end
end
pirntScrolling("hello -- by AAAB60", 5)

View File

@@ -1,494 +1,494 @@
---@module "cctAPI"
---example:
---```
---for pos, code in codes("你好world") do
--- print(pos, code)
---end
------>
---1 20320
---4 22909
---7 119
---8 111
---9 114
---10 108
---11 100
---```
---@param str string
---@return fun():pos:integer, code:integer
local function codes(str)
local len = #str
local i = 0
local function illegalChar()
error("Illegal UTF-8 character at position " .. tostring(i))
end
return function()
i = i + 1
---@diagnostic disable-next-line
if i > len then return end
local pos = i
local byte = string.byte(str, i)
-- Single-byte character
if byte < 0x80 then
return pos, byte
-- Multi-byte sequences
elseif byte >= 0xC0 then
local bytes_remaining, code = 0, 0
if byte < 0xE0 then -- 2-byte sequence
bytes_remaining = 1
code = byte - 0xC0
elseif byte < 0xF0 then -- 3-byte sequence
bytes_remaining = 2
code = byte - 0xE0
elseif byte < 0xF8 then -- 4-byte sequence
bytes_remaining = 3
code = byte - 0xF0
else
illegalChar()
end
-- Validate remaining bytes
if i + bytes_remaining > len then
illegalChar()
end
-- Calculate code point
for j = 1, bytes_remaining do
i = i + 1
local next_byte = string.byte(str, i)
if next_byte < 0x80 or next_byte >= 0xC0 then
illegalChar()
end
code = code * 0x40 + (next_byte - 0x80)
end
return pos, code
else
illegalChar()
---@diagnostic disable-next-line
end
end
end
---@type FontFamily
local defaultFontFamily = {
maxHeight = 4,
[1] = require("fonts/fusion-pixel-12px-proportional-zh_hans")
}
---@param str string read in `"rb"` mode from file
---@param nStartPos integer? 1~n, -n~-1 to represent pos reverse
---@param nEndPos integer? 1~n, -n~-1 to represent pos reverse
---@return string substring sub string of utf8 character from `nStartPos` to `nEndPos`
local function sub(str, nStartPos, nEndPos)
local charPos = 0
local utf8charPosToStr = {}
for pos, _ in codes(str) do
charPos = charPos + 1
utf8charPosToStr[charPos] = pos
end
nStartPos = nStartPos or 1
nEndPos = nEndPos or charPos
nStartPos = nStartPos < 0 and math.max(1, charPos + nStartPos + 1) or math.min(charPos, nStartPos)
nEndPos = nEndPos < 0 and math.max(1, charPos + nEndPos + 1) or math.min(charPos, nEndPos)
local startByte = utf8charPosToStr[nStartPos]
local endByte = utf8charPosToStr[nEndPos + 1] and utf8charPosToStr[nEndPos + 1] - 1 or #str
return string.sub(str, startByte, endByte)
end
---@class FontFamily
---@field maxHeight integer
---@diagnostic disable-next-line
---@field [integer] Font get from `require(font_name)`
---@param ... string module names of font, font should be
---@return FontFamily
local function getFontFamily(...)
local fonts = { maxHeight = 0 }
for i, path in ipairs({ ... }) do
if not fs.exists(path .. ".lua") then
error("Font module not found: " .. path)
end
local font = require(path)
if not font[72] then
error("'H'(ascII:72) not found in font " .. path)
end
fonts[i] = font
fonts.maxHeight = math.max(fonts.maxHeight, #font[72])
end
return fonts
end
---@alias bitmap string[] the bitmap of a character
---@param code integer
---@param fontFamily FontFamily
---@return bitmap
local function getCharMap(code, fontFamily)
local cm
for _, font in ipairs(fontFamily) do
cm = font[code]
if cm then
return cm
end
end
error(("char of utf8 %d is not supported"):format(code))
end
---@class Config
---@field fontFamily FontFamily?
---@field textColor number?
---@field backgroundColor number?
---@field masking [integer, integer, integer, integer]?
---@field autoScroll boolean
---@field autoNewLine boolean
---@field autoWrapMode "n"|"b"|"-"?
---@field autoWrapLen integer?
---@field avoidBorder boolean
---@field tabLen integer?
---@see Config
---@param preset "noauto"?
---@return Config
local function getCfg(preset)
---@type Config
local base = {
fontFamily = defaultFontFamily,
textColor = nil,
backgroundColor = nil,
masking = nil,
autoScroll = true,
autoNewLine = true,
autoWrapMode = "b",
autoWrapLen = nil,
avoidBorder = true,
tabLen = 2
}
if preset == "noauto" then
base.autoScroll = false
base.autoNewLine = false
base.autoWrapMode = "n"
end
return base
end
---`str` should be read in `"rb"` mode from file <br>
---`cfg` see [`getCfg()`](lua://Config)
---### Config
---- **textColor**
---- **backgroundColor**
---- **fontFamily** use [`getFontFamily()`](lua://FontFamily) to modify
---- **masking** representing x1, y1, x2, y2 of 2 coordinates, concent out of the rectange range won't print
---- **autoScroll** if true, if next line is over-height, [`term.scroll()`](https://tweaked.cc/module/term.html#v:scroll) will be called, masking will also be scrolled
---- **autoNewLine** if true, the output will be like a `\n` added to the end
---- **autoWrapMode** <br>
----- `"n"` do not auto wrap<br>
----- `"b"` English letter will not be broken<br>
----- `"-"` English letter will be broken by a `'-'`<br>
---here 'letter' matches regex `(?<![a-zA-Z'])[a-zA-Z']+-?`<br>
---actually realized avoid using `luautf8` or regex matching
---- **autoWrapLen** the maximum distance a line goes from the terminal's left
---- **avoidBorder** if true, autoScroll and autoWrap will avoid printing border pixels, which have render issue<br>
---for example, autoWrap will start new line at pos (2, y) instead of (1, y)
---- **tabLen** the count of `' '` to replace `'\t'`
---@param str string
---@param cfg Config?
local function printUtf8(str, cfg)
local cursorX, cursorY = term.getCursorPos()
local termWidth, termHeight = term.getSize()
local cfg = cfg or getCfg()
local oriTextColor, oriBackgroundColor = term.getTextColor(), term.getBackgroundColor()
local textColor = cfg.textColor or oriTextColor
local backgroundColor = cfg.backgroundColor or oriBackgroundColor
local masking = cfg.masking
local autoScroll = cfg.autoScroll or true
local autoNewLine = cfg.autoNewLine
local autoWrapMode = cfg.autoWrapMode or "b"
local autoWrapLen = cfg.autoWrapLen or termWidth
local avoidBorder = cfg.avoidBorder
local fontFamily = cfg.fontFamily or defaultFontFamily
local tabLen = cfg.tabLen or 2
str = string.gsub(str, '\t', string.rep(" ", tabLen))
local fontHeight = fontFamily.maxHeight
if avoidBorder and autoWrapMode ~= "n" then
autoWrapLen = math.min(termWidth - 1, autoWrapLen)
cursorX = math.max(2, cursorX)
cursorY = math.max(2, cursorY)
end
local maxHeight = avoidBorder and termHeight - 1 or termHeight
---@type integer[]
local letterBuffer = {}
local dashWidth = #getCharMap(45, fontFamily)[1]
---@type { pos: [integer, integer], code: integer }[]
local charBuffer = {}
---@param x integer
---@param y integer
---@return boolean
local function bInMasking(x, y)
---@diagnostic disable-next-line
return x >= masking[1] and x <= masking[3] and y >= masking[2] and y <= masking[4]
end
---add new line to charBuffer
local function posNewLine()
cursorX = avoidBorder and 2 or 1
if autoScroll and cursorY + fontHeight > maxHeight then
-- scroll term and masking
term.scroll(fontHeight)
for _, char in ipairs(charBuffer) do
char.pos[2] = char.pos[2] - fontHeight
end
if masking then
masking[2] = masking[2] - fontHeight
masking[4] = masking[4] - fontHeight
end
else
cursorY = cursorY + fontHeight
end
end
---print char in charBuffer
local function printChar()
local bIsLastReversed = false
term.setTextColor(textColor)
term.setBackgroundColor(backgroundColor)
for _, char in ipairs(charBuffer) do
---@type bitmap
local charMap
local code = char.code
for _, font in ipairs(fontFamily) do
if font[code] then
charMap = font[code]
break
end
end
local width, height = #charMap[1], #charMap
local cursorX, cursorY = unpack(char.pos)
if height < fontHeight then
if bIsLastReversed then
bIsLastReversed = false
term.setTextColor(textColor)
term.setBackgroundColor(backgroundColor)
end
for _ = 1, fontHeight - height do
term.setCursorPos(cursorX, cursorY)
term.write(string.rep(" ", width))
cursorY = cursorY + 1
end
end
for y = 1, height do
local posY = cursorY + y - 1
term.setCursorPos(cursorX, posY)
local sCharMapBuffer = charMap[y]
for x = 1, width do
if not masking or bInMasking(cursorX + x - 1, posY) then
local code = string.byte(sCharMapBuffer, x)
if code < 128 then
code = code + 128
if not bIsLastReversed then
bIsLastReversed = true
term.setTextColor(backgroundColor)
term.setBackgroundColor(textColor)
end
else
if bIsLastReversed then
bIsLastReversed = false
term.setTextColor(textColor)
term.setBackgroundColor(backgroundColor)
end
end
term.write(string.char(code))
else
term.setCursorPos(cursorX + x, posY)
end
end
end
end
term.setTextColor(oriTextColor)
term.setBackgroundColor(oriBackgroundColor)
if autoNewLine then
term.setCursorPos(1, cursorY + fontHeight)
else
term.setCursorPos(cursorX, cursorY)
end
end
local bIsLetter = false
local function releaseLetter()
if bIsLetter then
if autoWrapMode == "-" then
local widthSum = cursorX - 1
local widthBuffer = {}
for index, letter in ipairs(letterBuffer) do
widthBuffer[index] = #getCharMap(letter, fontFamily)[1]
end
local ind = 1
local letterBufferLen = #letterBuffer
local lastDashPos = 1
while ind <= letterBufferLen do
widthSum = widthSum + widthBuffer[ind]
if widthSum > autoWrapLen then
while widthSum + dashWidth > autoWrapLen do
if ind == lastDashPos then
-- when have to insert dash in the first character, posNewLine() or throw
if ind == 1 and cursorX ~= (avoidBorder and 2 or 1) then
widthSum = 0
else
error("dash too wide or autoWrapLen too small")
end
end
widthSum = widthSum - widthBuffer[ind]
ind = ind - 1
end
-- pos letters before dash
for i = lastDashPos, ind do
charBuffer[#charBuffer + 1] = {
pos = { cursorX, cursorY },
code = letterBuffer[i]
}
cursorX = cursorX + widthBuffer[i]
end
if widthSum >= 0 then
-- add dash
charBuffer[#charBuffer + 1] = {
pos = { cursorX, cursorY },
code = 45
}
end
-- reset
widthSum = 0
lastDashPos = ind + 1
posNewLine()
end
ind = ind + 1
end
-- pos letters after dash
for i = lastDashPos, letterBufferLen do
charBuffer[#charBuffer + 1] = {
pos = { cursorX, cursorY },
code = letterBuffer[i]
}
cursorX = cursorX + widthBuffer[i]
end
elseif autoWrapMode == "b" then
local widthSum = cursorX - 1
local widthBuffer = {}
local ind = 1
local letterBufferLen = #letterBuffer
while ind <= letterBufferLen do
local charMapWidth = #getCharMap(letterBuffer[ind], fontFamily)[1]
widthBuffer[ind] = charMapWidth
widthSum = widthSum + charMapWidth
ind = ind + 1
end
local forceNewLineFlag = false
if widthSum > autoWrapLen then
if cursorX == (avoidBorder and 2 or 1) then
forceNewLineFlag = true
else
widthSum = widthSum - cursorX + 1
if widthSum > autoWrapLen then
forceNewLineFlag = true
else
posNewLine()
end
end
end
if forceNewLineFlag then
for i = 1, letterBufferLen do
if cursorX + widthBuffer[i] > autoWrapLen then
posNewLine()
end
charBuffer[#charBuffer + 1] = {
pos = { cursorX, cursorY },
code = letterBuffer[i]
}
cursorX = cursorX + widthBuffer[i]
end
else
for i = 1, letterBufferLen do
charBuffer[#charBuffer + 1] = {
pos = { cursorX, cursorY },
code = letterBuffer[i]
}
cursorX = cursorX + widthBuffer[i]
end
end
elseif autoWrapMode == "n" then
for _, letter in ipairs(letterBuffer) do
charBuffer[#charBuffer + 1] = {
pos = { cursorX, cursorY },
code = letter
}
cursorX = cursorX + #getCharMap(letter, fontFamily)[1]
end
end
letterBuffer = {}
bIsLetter = false
end
end
local lastLR = false
for _, code in codes(str) do
-- handle break line, \r, \n and \r\n will be transferred
if code == 13 then
releaseLetter()
lastLR = true
posNewLine()
elseif code == 10 and not lastLR then
lastLR = false
releaseLetter()
posNewLine()
-- record letter for break line
elseif code == 45 and bIsLetter then
lastLR = false
letterBuffer[#letterBuffer + 1] = code
releaseLetter()
elseif code >= 65 and code <= 90 or (code >= 97 and code <= 122) or code == 39 then
lastLR = false
letterBuffer[#letterBuffer + 1] = code
bIsLetter = true
-- pos char
else
lastLR = false
releaseLetter()
local charMapWidth = #getCharMap(code, fontFamily)[1]
if autoWrapMode ~= "n" and cursorX + charMapWidth - 1 > autoWrapLen then
posNewLine()
end
charBuffer[#charBuffer + 1] = {
pos = { cursorX, cursorY },
code = code
}
cursorX = cursorX + charMapWidth
end
end
releaseLetter()
printChar()
end
return {
codes = codes,
printUtf8 = printUtf8,
getFontFamily = getFontFamily,
sub = sub,
getCfg = getCfg,
getCharMap = getCharMap
}
---@module "cctAPI"
---example:
---```
---for pos, code in codes("你好world") do
--- print(pos, code)
---end
------>
---1 20320
---4 22909
---7 119
---8 111
---9 114
---10 108
---11 100
---```
---@param str string
---@return fun():pos:integer, code:integer
local function codes(str)
local len = #str
local i = 0
local function illegalChar()
error("Illegal UTF-8 character at position " .. tostring(i))
end
return function()
i = i + 1
---@diagnostic disable-next-line
if i > len then return end
local pos = i
local byte = string.byte(str, i)
-- Single-byte character
if byte < 0x80 then
return pos, byte
-- Multi-byte sequences
elseif byte >= 0xC0 then
local bytes_remaining, code = 0, 0
if byte < 0xE0 then -- 2-byte sequence
bytes_remaining = 1
code = byte - 0xC0
elseif byte < 0xF0 then -- 3-byte sequence
bytes_remaining = 2
code = byte - 0xE0
elseif byte < 0xF8 then -- 4-byte sequence
bytes_remaining = 3
code = byte - 0xF0
else
illegalChar()
end
-- Validate remaining bytes
if i + bytes_remaining > len then
illegalChar()
end
-- Calculate code point
for j = 1, bytes_remaining do
i = i + 1
local next_byte = string.byte(str, i)
if next_byte < 0x80 or next_byte >= 0xC0 then
illegalChar()
end
code = code * 0x40 + (next_byte - 0x80)
end
return pos, code
else
illegalChar()
---@diagnostic disable-next-line
end
end
end
---@type FontFamily
local defaultFontFamily = {
maxHeight = 4,
[1] = require("fonts/fusion-pixel-12px-proportional-zh_hans")
}
---@param str string read in `"rb"` mode from file
---@param nStartPos integer? 1~n, -n~-1 to represent pos reverse
---@param nEndPos integer? 1~n, -n~-1 to represent pos reverse
---@return string substring sub string of utf8 character from `nStartPos` to `nEndPos`
local function sub(str, nStartPos, nEndPos)
local charPos = 0
local utf8charPosToStr = {}
for pos, _ in codes(str) do
charPos = charPos + 1
utf8charPosToStr[charPos] = pos
end
nStartPos = nStartPos or 1
nEndPos = nEndPos or charPos
nStartPos = nStartPos < 0 and math.max(1, charPos + nStartPos + 1) or math.min(charPos, nStartPos)
nEndPos = nEndPos < 0 and math.max(1, charPos + nEndPos + 1) or math.min(charPos, nEndPos)
local startByte = utf8charPosToStr[nStartPos]
local endByte = utf8charPosToStr[nEndPos + 1] and utf8charPosToStr[nEndPos + 1] - 1 or #str
return string.sub(str, startByte, endByte)
end
---@class FontFamily
---@field maxHeight integer
---@diagnostic disable-next-line
---@field [integer] Font get from `require(font_name)`
---@param ... string module names of font, font should be
---@return FontFamily
local function getFontFamily(...)
local fonts = { maxHeight = 0 }
for i, path in ipairs({ ... }) do
if not fs.exists(path .. ".lua") then
error("Font module not found: " .. path)
end
local font = require(path)
if not font[72] then
error("'H'(ascII:72) not found in font " .. path)
end
fonts[i] = font
fonts.maxHeight = math.max(fonts.maxHeight, #font[72])
end
return fonts
end
---@alias bitmap string[] the bitmap of a character
---@param code integer
---@param fontFamily FontFamily
---@return bitmap
local function getCharMap(code, fontFamily)
local cm
for _, font in ipairs(fontFamily) do
cm = font[code]
if cm then
return cm
end
end
error(("char of utf8 %d is not supported"):format(code))
end
---@class Config
---@field fontFamily FontFamily?
---@field textColor number?
---@field backgroundColor number?
---@field masking [integer, integer, integer, integer]?
---@field autoScroll boolean
---@field autoNewLine boolean
---@field autoWrapMode "n"|"b"|"-"?
---@field autoWrapLen integer?
---@field avoidBorder boolean
---@field tabLen integer?
---@see Config
---@param preset "noauto"?
---@return Config
local function getCfg(preset)
---@type Config
local base = {
fontFamily = defaultFontFamily,
textColor = nil,
backgroundColor = nil,
masking = nil,
autoScroll = true,
autoNewLine = true,
autoWrapMode = "b",
autoWrapLen = nil,
avoidBorder = true,
tabLen = 2
}
if preset == "noauto" then
base.autoScroll = false
base.autoNewLine = false
base.autoWrapMode = "n"
end
return base
end
---`str` should be read in `"rb"` mode from file <br>
---`cfg` see [`getCfg()`](lua://Config)
---### Config
---- **textColor**
---- **backgroundColor**
---- **fontFamily** use [`getFontFamily()`](lua://FontFamily) to modify
---- **masking** representing x1, y1, x2, y2 of 2 coordinates, concent out of the rectange range won't print
---- **autoScroll** if true, if next line is over-height, [`term.scroll()`](https://tweaked.cc/module/term.html#v:scroll) will be called, masking will also be scrolled
---- **autoNewLine** if true, the output will be like a `\n` added to the end
---- **autoWrapMode** <br>
----- `"n"` do not auto wrap<br>
----- `"b"` English letter will not be broken<br>
----- `"-"` English letter will be broken by a `'-'`<br>
---here 'letter' matches regex `(?<![a-zA-Z'])[a-zA-Z']+-?`<br>
---actually realized avoid using `luautf8` or regex matching
---- **autoWrapLen** the maximum distance a line goes from the terminal's left
---- **avoidBorder** if true, autoScroll and autoWrap will avoid printing border pixels, which have render issue<br>
---for example, autoWrap will start new line at pos (2, y) instead of (1, y)
---- **tabLen** the count of `' '` to replace `'\t'`
---@param str string
---@param cfg Config?
local function printUtf8(str, cfg)
local cursorX, cursorY = term.getCursorPos()
local termWidth, termHeight = term.getSize()
local cfg = cfg or getCfg()
local oriTextColor, oriBackgroundColor = term.getTextColor(), term.getBackgroundColor()
local textColor = cfg.textColor or oriTextColor
local backgroundColor = cfg.backgroundColor or oriBackgroundColor
local masking = cfg.masking
local autoScroll = cfg.autoScroll or true
local autoNewLine = cfg.autoNewLine
local autoWrapMode = cfg.autoWrapMode or "b"
local autoWrapLen = cfg.autoWrapLen or termWidth
local avoidBorder = cfg.avoidBorder
local fontFamily = cfg.fontFamily or defaultFontFamily
local tabLen = cfg.tabLen or 2
str = string.gsub(str, '\t', string.rep(" ", tabLen))
local fontHeight = fontFamily.maxHeight
if avoidBorder and autoWrapMode ~= "n" then
autoWrapLen = math.min(termWidth - 1, autoWrapLen)
cursorX = math.max(2, cursorX)
cursorY = math.max(2, cursorY)
end
local maxHeight = avoidBorder and termHeight - 1 or termHeight
---@type integer[]
local letterBuffer = {}
local dashWidth = #getCharMap(45, fontFamily)[1]
---@type { pos: [integer, integer], code: integer }[]
local charBuffer = {}
---@param x integer
---@param y integer
---@return boolean
local function bInMasking(x, y)
---@diagnostic disable-next-line
return x >= masking[1] and x <= masking[3] and y >= masking[2] and y <= masking[4]
end
---add new line to charBuffer
local function posNewLine()
cursorX = avoidBorder and 2 or 1
if autoScroll and cursorY + fontHeight > maxHeight then
-- scroll term and masking
term.scroll(fontHeight)
for _, char in ipairs(charBuffer) do
char.pos[2] = char.pos[2] - fontHeight
end
if masking then
masking[2] = masking[2] - fontHeight
masking[4] = masking[4] - fontHeight
end
else
cursorY = cursorY + fontHeight
end
end
---print char in charBuffer
local function printChar()
local bIsLastReversed = false
term.setTextColor(textColor)
term.setBackgroundColor(backgroundColor)
for _, char in ipairs(charBuffer) do
---@type bitmap
local charMap
local code = char.code
for _, font in ipairs(fontFamily) do
if font[code] then
charMap = font[code]
break
end
end
local width, height = #charMap[1], #charMap
local cursorX, cursorY = unpack(char.pos)
if height < fontHeight then
if bIsLastReversed then
bIsLastReversed = false
term.setTextColor(textColor)
term.setBackgroundColor(backgroundColor)
end
for _ = 1, fontHeight - height do
term.setCursorPos(cursorX, cursorY)
term.write(string.rep(" ", width))
cursorY = cursorY + 1
end
end
for y = 1, height do
local posY = cursorY + y - 1
term.setCursorPos(cursorX, posY)
local sCharMapBuffer = charMap[y]
for x = 1, width do
if not masking or bInMasking(cursorX + x - 1, posY) then
local code = string.byte(sCharMapBuffer, x)
if code < 128 then
code = code + 128
if not bIsLastReversed then
bIsLastReversed = true
term.setTextColor(backgroundColor)
term.setBackgroundColor(textColor)
end
else
if bIsLastReversed then
bIsLastReversed = false
term.setTextColor(textColor)
term.setBackgroundColor(backgroundColor)
end
end
term.write(string.char(code))
else
term.setCursorPos(cursorX + x, posY)
end
end
end
end
term.setTextColor(oriTextColor)
term.setBackgroundColor(oriBackgroundColor)
if autoNewLine then
term.setCursorPos(1, cursorY + fontHeight)
else
term.setCursorPos(cursorX, cursorY)
end
end
local bIsLetter = false
local function releaseLetter()
if bIsLetter then
if autoWrapMode == "-" then
local widthSum = cursorX - 1
local widthBuffer = {}
for index, letter in ipairs(letterBuffer) do
widthBuffer[index] = #getCharMap(letter, fontFamily)[1]
end
local ind = 1
local letterBufferLen = #letterBuffer
local lastDashPos = 1
while ind <= letterBufferLen do
widthSum = widthSum + widthBuffer[ind]
if widthSum > autoWrapLen then
while widthSum + dashWidth > autoWrapLen do
if ind == lastDashPos then
-- when have to insert dash in the first character, posNewLine() or throw
if ind == 1 and cursorX ~= (avoidBorder and 2 or 1) then
widthSum = 0
else
error("dash too wide or autoWrapLen too small")
end
end
widthSum = widthSum - widthBuffer[ind]
ind = ind - 1
end
-- pos letters before dash
for i = lastDashPos, ind do
charBuffer[#charBuffer + 1] = {
pos = { cursorX, cursorY },
code = letterBuffer[i]
}
cursorX = cursorX + widthBuffer[i]
end
if widthSum >= 0 then
-- add dash
charBuffer[#charBuffer + 1] = {
pos = { cursorX, cursorY },
code = 45
}
end
-- reset
widthSum = 0
lastDashPos = ind + 1
posNewLine()
end
ind = ind + 1
end
-- pos letters after dash
for i = lastDashPos, letterBufferLen do
charBuffer[#charBuffer + 1] = {
pos = { cursorX, cursorY },
code = letterBuffer[i]
}
cursorX = cursorX + widthBuffer[i]
end
elseif autoWrapMode == "b" then
local widthSum = cursorX - 1
local widthBuffer = {}
local ind = 1
local letterBufferLen = #letterBuffer
while ind <= letterBufferLen do
local charMapWidth = #getCharMap(letterBuffer[ind], fontFamily)[1]
widthBuffer[ind] = charMapWidth
widthSum = widthSum + charMapWidth
ind = ind + 1
end
local forceNewLineFlag = false
if widthSum > autoWrapLen then
if cursorX == (avoidBorder and 2 or 1) then
forceNewLineFlag = true
else
widthSum = widthSum - cursorX + 1
if widthSum > autoWrapLen then
forceNewLineFlag = true
else
posNewLine()
end
end
end
if forceNewLineFlag then
for i = 1, letterBufferLen do
if cursorX + widthBuffer[i] > autoWrapLen then
posNewLine()
end
charBuffer[#charBuffer + 1] = {
pos = { cursorX, cursorY },
code = letterBuffer[i]
}
cursorX = cursorX + widthBuffer[i]
end
else
for i = 1, letterBufferLen do
charBuffer[#charBuffer + 1] = {
pos = { cursorX, cursorY },
code = letterBuffer[i]
}
cursorX = cursorX + widthBuffer[i]
end
end
elseif autoWrapMode == "n" then
for _, letter in ipairs(letterBuffer) do
charBuffer[#charBuffer + 1] = {
pos = { cursorX, cursorY },
code = letter
}
cursorX = cursorX + #getCharMap(letter, fontFamily)[1]
end
end
letterBuffer = {}
bIsLetter = false
end
end
local lastLR = false
for _, code in codes(str) do
-- handle break line, \r, \n and \r\n will be transferred
if code == 13 then
releaseLetter()
lastLR = true
posNewLine()
elseif code == 10 and not lastLR then
lastLR = false
releaseLetter()
posNewLine()
-- record letter for break line
elseif code == 45 and bIsLetter then
lastLR = false
letterBuffer[#letterBuffer + 1] = code
releaseLetter()
elseif code >= 65 and code <= 90 or (code >= 97 and code <= 122) or code == 39 then
lastLR = false
letterBuffer[#letterBuffer + 1] = code
bIsLetter = true
-- pos char
else
lastLR = false
releaseLetter()
local charMapWidth = #getCharMap(code, fontFamily)[1]
if autoWrapMode ~= "n" and cursorX + charMapWidth - 1 > autoWrapLen then
posNewLine()
end
charBuffer[#charBuffer + 1] = {
pos = { cursorX, cursorY },
code = code
}
cursorX = cursorX + charMapWidth
end
end
releaseLetter()
printChar()
end
return {
codes = codes,
printUtf8 = printUtf8,
getFontFamily = getFontFamily,
sub = sub,
getCfg = getCfg,
getCharMap = getCharMap
}

View File

@@ -1,6 +1,30 @@
all codes have a demostration video on my **bilibili** cannel
## catalyst
- for mod pack: **create:above and beyond**
- automatically test and form the catalyst formula
- finnal output numbers represent the magnet in the corresponding slot of the crate
- using four different containers to simplify`peripheral.find`
## 介绍
此仓库克隆自https://github.com/AAAB60/computer-craft-programs/tree/main
对其进行修改以共liulikeji程序使用
## 以下为原本介绍
一个基于像素打印的utf8打印程序
> $\color{red} \bf 注意:$
> CC 编译器会把utf8字符读作 '?',
> `print("你好世界")` 与 `print("????")` 的效果相同, 可以`"rb"`模式读取文件以设置输入
## 如何制作Font
- 字体文件返回一个table键值为utf8编码值为和对应字体的bitmap。
- bitmap为一个包含等长string的tablestring中的char属于computer craft定义的2*3像素点阵如需使用右下角像素将char的码值减128表示反转backgroundColor 和 textColor
- 单个字体文件中可以有不同尺寸的bitmap且**需要**有'H'(ascII:72)的bitmap表示该文件中最大bitmap高度
- 会以FontFamily出现的最大bitmap高度为基准最终输出下对齐的文本
- FontFamily中**需要**'-'(ascII:45)的bitmap以供自动换行时可能的切断单词使用
## 技术细节
- `require`一个fusion-pixel-12px字体大约消耗**10.5MB**内存
- `require`一个fusion-pixel-8px字体大约消耗**6MB**内存
- 8px字符实际占用3格高的字符数, 12px字符实际占用4格高
- 字体来自 <a href="https://github.com/TakWolf/fusion-pixel-font/releases"> fusion-pixel-font </a>

View File

@@ -1,352 +0,0 @@
mags = peripheral.find("create:adjustable_crate")
bottler = peripheral.find("minecraft:trapped_chest")
shovel = peripheral.find("minecraft:barrel")
loader = peripheral.find("minecraft:chest")
unloader = peripheral.find("minecraft:hopper")
analyser = peripheral.find("thermal:machine_centrifuge")
table1 = {["Andesite Reagent"]=1,["Diorite Reagent"]=2,["Granite Reagent"]=3,["Stone Reagent"]=4,["Basalt Reagent"]=5,["Gabbro Reagent"]=6,
["Crimson Reagent"]=1,["Orange Reagent"]=2,["Goldenrod Reagent"]=3,["Olive Reagent"]=4,["Azure Reagent"]=5,["Fuchsia Reagent"]=6,
["Blazing Reagent"]=1,["Slime Reagent"]=2,["Nether Reagent"]=3,["Obsidian Reagent"]=4,["Gunpowder Reagent"]=5,["Aquatic Reagent"]=6,
["Arcane Reagent"]=1,["Apatite Reagent"]=2,["Sulfuric Reagent"]=3,["Nitric Reagent"]=4,["Certus Quartz Reagent"]=5,["Nether Quartz Reagent"]=6,
["Zinc Reagent"]=1,["Copper Reagent"]=2,["Iron Reagent"]=3,["Nickel Reagent"]=4,["Lead Reagent"]=5,["Gold Reagent"]=6,
["Cinnabar Reagent"]=1,["Lapis Lazuli Reagent"]=2,["Sapphire Reagent"]=3,["Emerald Reagent"]=4,["Ruby Reagent"]=5,["Diamond Reagent"]=6}
function tableCopy(b)
local a = {}
for i ,j in pairs(b) do
if type(j) == "table" then
local jundge = nil
for m,n in pairs(j) do --{} ~= {}
jundge = true
break
end
if jundge then
a[i] = tableCopy(j)
else a[i] = {}
end
else
a[i] = j
end
end
return a
end
function tableCompare(a,b)
local jundge = true
for i = 1,#a do
if type(a[i]) == "table" then
if #a[i] ~= 0 and not tableCompare(a[i],b[i]) then
jundge = false
break
elseif #a == 0 and #b[i] ~= 0 then
jundge = false
break
end
elseif a[i] ~= b[i] then
jundge = false
break
end
end
return jundge
end
function tableCompare1(a,b)
local jundge = false
for i = 1,#a do
if tableCompare(a[i],b) then
jundge = true
break
end
end
return jundge
end
local function push(container,receive,count,toslot,nameDisplay)--(dirt,dirt/"minecraft:chest_0")
local num,receiveName = 0,""
if type(receive) == "string" then
receiveName = receive
else
receiveName = peripheral.getName(receive)
end
--negelect modle
if nameDisplay == nil then
if count ~= nil then
for i,j in pairs(container.list()) do
num = num + j["count"]
container.pushItems(receiveName,i,count - num + j["count"],toslot)
if num >= count then break end
end
else
for i,j in pairs(container.list()) do
container.pushItems(receiveName,i,nil,toslot)
end
end
else
if count ~= nil then
for i,j in pairs(container.list()) do
if container.getItemDetail(i).displayName == nameDisplay then
num = num + j["count"]
container.pushItems(receiveName,i,count - num + j["count"],toslot)
if num >= count then break end
end
end
else
for i,j in pairs(container.list()) do
if container.getItemDetail(i).displayName == nameDisplay then
container.pushItems(receiveName,i,nil,toslot)
end
end
end
end
end
local function push1(container,outPutRules)--{{"Dirt","minecraft:chest_1",[num],toslot},{"Dirt","cobblesStone"}}
for i,j in pairs(container.list()) do
local displayName1,receiveName = container.getItemDetail(i).displayName,""
for m,n in pairs(outPutRules) do
if type(n[2]) == "string" then
receiveName = n[2]
else
receiveName = peripheral.getName(n[2])
end
if displayName1 == n[1] then
container.pushItems(receiveName,i,n[3],n[4])
break
end
end
end
end
function hop(num)
local time = {0.1,0.5,0.9,1.3,1.7}
redstone.setOutput("top",true)--0.1,0.5,1,1.5,2
sleep(time[num])
redstone.setOutput("top",false)
end
function input(numbers,c)--({1,1,3,5},rc/gc)
for o = 1, 4 do
for i = 1, 4 - o do
shovel.pushItems(peripheral.getName(loader),i,1,i)
end
mags.pushItems(peripheral.getName(loader),numbers[5-o],1,5-o)
hop(4 - o)
sleep(0.4)
end
if c == "rc" then
mags.pushItems(peripheral.getName(loader),7,1,5)
elseif c == "gc" then
mags.pushItems(peripheral.getName(loader),8,1,5)
end
end
function stop()
sleep(10)
for i = 1 ,6 do
if mags.list()[i]["count"] <= 6 then
stop()
end
end
end
function step(simulateAnswer1,numbers1,c) --return mutiple results
local b,numbers,simulateAnswer = {0,0,0}
numbers = tableCopy(numbers1)
simulateAnswer = tableCopy(simulateAnswer1)
local jundge = nil
for i = 1, 4 do
if simulateAnswer[i] == numbers[i] then
b[3] = b[3] + 1
simulateAnswer[i] = nil
numbers[i] = nil
end
end
for i = 1 ,4 do
if simulateAnswer[i] then
for j = 1 ,4 do
if simulateAnswer[i] == numbers[j] then
b[2] = b[2] + 1
simulateAnswer[i] = 7
numbers[j] = 7
break
end
end
end
end
b[1] = 4 - b[2] - b[3]
local d = {b}
local count = 1
if c == "gc" then
for i =1,4 do
if not simulateAnswer[i] then
d[count] = tableCopy(b)
d[count][4] = simulateAnswer1[i]
count = count + 1
end
end
elseif c == "rc" then
for i = 1,4 do
if simulateAnswer[i] == 7 then
d[count] = tableCopy(b)
d[count][4] = simulateAnswer1[i]
count = count + 1
end
end
end
return d
end
local function answerFilter(log,answers1)
local answers,count,jundge,answers2 = {},1,true,{}
if not answers1 then
for i1 = 1,6 do
for i2 = 1,6 do
for i3 = 1,6 do
for i4 = 1,6 do
answers[count] = {i1,i2,i3,i4}
count = count+1
end end end end
answers2 = tableCopy(answerFilter(log,answers))
else
answers = tableCopy(answers1)
for i,j in pairs(answers) do
for i6 = 1,#log do
if log[i6]["stepNumber"] and not tableCompare1(step(j,log[i6]["stepNumber"],"rc"),log[i6]["result"]) then
jundge = nil
break
end
end
if jundge then
answers2[count] = j
count = count+1
else jundge = true
end
end
end
return answers2
end
function translate(table)
local b = {0,0,0}
--output table b{[ash],[minecraft:redstone],[minecraft:glowstone_dust],[catalysed number]}
if analyser.list()[2]["name"] == "darkerdepths:ash" then
b[1] = analyser.list()[2]["count"]
if analyser.list()[3] then
if analyser.list()[3]["name"] == "minecraft:redstone" then
b[2] = analyser.list()[3]["count"]
if analyser.list()[4] then
b[3] = analyser.list()[4]["count"]
else b[3] = 0
end
elseif analyser.list()[3]["name"] == "minecraft:glowstone_dust" then
b[2] = 0
b[3] = analyser.list()[3]["count"]
else
print("analyser_trash")
end
end
elseif analyser.list()[2]["name"] == "minecraft:redstone" then
b[1] = 0
b[2] = analyser.list()[2]["count"]
if analyser.list()[3] then
b[3] = analyser.list()[3]["count"]
end
else
print("analyser_trash")
end
if shovel.list()[5] then
b[4] = table[shovel.getItemDetail(5).displayName]
end
return b
end
function suggestedInfoValue(a)
if a == 1 then print("error a == 1") end
local b = {2,6,12,20,30}
if a <= 6 then
return b[a-1]
elseif a <= 16 then
return 0.8809*a^2 - 1.158*a + 1
else
return 0.7435*a^2 + 3.3087*a + 1
end
end
function stepInstruct(log1,answers1)
local log = tableCopy(log1)
local answers,infoValue,count = nil,0,#log+1
if answers1 then
answers = tableCopy(answers1)
end
answers = answerFilter(log,answers)
if #answers == 1 then
return {answers[1],answers}
end
local sInfoV = suggestedInfoValue(#answers)
for k =1,80 do
log[count] = {["stepNumber"] = {math.random(1,6),math.random(1,6),math.random(1,6),math.random(1,6)}}
for i,j in pairs(answers) do
local temporary = step(j,log[count]["stepNumber"],"rc")
for m,n in pairs(temporary) do
log[count]["result"] = tableCopy(j)
infoValue = infoValue + (#answers - #answerFilter(log,answers))/#temporary
end
end
if infoValue >= sInfoV then
return {log[count]["stepNumber"],answers}
end
end
printTable("sInfo "..tostring(sInfoV).." too bigger than "..tostring(infoValue))
print("#answers = "..tostring(#answers))
error("please restart the program",0)
end
function printTable(a)
if type(a) == "string" then
io.write(a)
elseif type(a) == "number" then
io.write(tostring(a))
elseif type(a) == "table" then
local count,jundge = 1,nil
io.write("{")
for i,j in pairs(a) do
if jundge then
io.write(",")
else
jundge = true
end
if i == count then
count = count + 1
elseif type(i) == "string" then
io.write( '["'..i..'"]=')
else io.write( '['..i..']=') end
printTable(j)
end
io.write("}")
end
end
function main()
local table = {}
for i=1,6 do
table[mags.getItemDetail(i).displayName] = i
end
local log,count,answers = {{["stepNumber"] = {1,2,3,4}}},0,nil
--local read = io.read()
if true then
repeat
count = count + 1
print("the number "..count.." round")
input(log[count]["stepNumber"],"rc")
redstone.setOutput("right",true)
sleep(0.2)
redstone.setOutput("right",false)
sleep(5)
hop(3)
sleep(0.5)
shovel.pushItems(peripheral.getName(analyser),4,1)
repeat sleep(1) until analyser.list()[2]
log[count]["result"] = translate(table)
for i = 2 ,4 do
analyser.pushItems(peripheral.getName(bottler),i,64)
end
shovel.pushItems(peripheral.getName(mags),5,1)
local temporary = stepInstruct(log,answers)
answers = tableCopy(temporary[2])
log[count+1] = {["stepNumber"] = tableCopy(temporary[1])}
if #answers == 1 then
print("finish")
printTable(answers[1])
print(" ")
break
end
until nil
end
end
main()

209
utf8ptrint.lua Normal file
View File

@@ -0,0 +1,209 @@
--这是一个简单的打印字符的程序他使用下方url的字体进行显示
--因为字体文件超过cc存储大小所以使用网络加载字体
--通过printUtf8("字符",文字颜色,背景颜色)来达到类似 print的效果
--示例printUtf8("你好世界! Hello Word!",colors.white,colors.lightGray)
-- 从网络加载字库
local function loadRemoteFont(url)
local response = http.get(url)
if not response then
error("无法连接到字体服务器")
end
if response.getResponseCode() ~= 200 then
error("字体服务器返回错误: " .. response.getResponseCode())
end
local content = response.readAll()
response.close()
-- 使用沙箱环境安全加载字体
local sandbox = {}
local chunk, err = load(content, "=remoteFont", "t", sandbox)
if not chunk then
error("加载字体失败: " .. err)
end
local success, result = pcall(chunk)
if not success then
error("执行字体脚本失败: " .. result)
end
return sandbox.font or sandbox[1] or result
end
-- 字体URL
local fontUrl = "https://git.liulikeji.cn/xingluo/ComputerCraft-Utf8/raw/branch/main/fonts/fusion-pixel-8px-proportional-zh_hans.lua"
local font = loadRemoteFont(fontUrl)
-- 显示单个字符的函数
local function displayChar(charMap, x, y, textColor, backgroundColor)
-- 保存原始终端颜色设置
local origTextColor = term.getTextColor()
local origBackgroundColor = term.getBackgroundColor()
-- 设置新颜色
term.setTextColor(textColor)
term.setBackgroundColor(backgroundColor)
-- 遍历字符位图的每一行
for row = 1, #charMap do
term.setCursorPos(x, y + row - 1)
local line = charMap[row]
-- 遍历行中的每个像素
for col = 1, #line do
local byte = string.byte(line, col)
-- 处理像素颜色
if byte < 128 then
-- 背景色像素:反转颜色设置
term.setTextColor(backgroundColor)
term.setBackgroundColor(textColor)
term.write(string.char(byte + 128)) -- 转换为可打印字符
else
-- 前景色像素:正常颜色设置
term.setTextColor(textColor)
term.setBackgroundColor(backgroundColor)
term.write(string.char(byte))
end
end
end
-- 恢复原始颜色设置
term.setTextColor(origTextColor)
term.setBackgroundColor(origBackgroundColor)
end
-- 显示UTF-8字符串的函数
local function displayUtf8String(str, font, x, y, textColor, backgroundColor)
-- UTF-8解码器简化版
local function utf8codes(str)
local i = 1
return function()
if i > #str then return end
local b1 = string.byte(str, i)
i = i + 1
-- 单字节字符 (ASCII)
if b1 < 0x80 then
return b1
-- 双字节字符
elseif b1 >= 0xC0 and b1 < 0xE0 then
local b2 = string.byte(str, i) or 0
i = i + 1
return (b1 - 0xC0) * 64 + (b2 - 0x80)
-- 三字节字符(中文)
elseif b1 >= 0xE0 and b1 < 0xF0 then
local b2 = string.byte(str, i) or 0
i = i + 1
local b3 = string.byte(str, i) or 0
i = i + 1
return (b1 - 0xE0) * 4096 + (b2 - 0x80) * 64 + (b3 - 0x80)
else
-- 不支持的编码,返回空格
return 32
end
end
end
local cursorX = x
-- 遍历字符串中的所有字符
for code in utf8codes(str) do
-- 获取字符位图
local charMap = font[code]
if not charMap then
-- 如果字库中没有该字符,使用空格代替
charMap = font[32] or {{"\x80"}} -- 空格字符
end
-- 显示字符
displayChar(charMap, cursorX, y, textColor, backgroundColor)
-- 移动到下一个字符位置
cursorX = cursorX + #charMap[1]
end
end
local cursorX, cursorY = 1, 1
local fontHeight = #font[32] -- 获取字体高度(使用空格字符)
-- 自定义打印函数(带自动换行和滚动)
local function printUtf8(str, textColor, backgroundColor)
local width, screenHeight = term.getSize() -- 获取终端尺寸
-- UTF-8解码器
local function utf8codes(str)
local i = 1
return function()
if i > #str then return end
local b1 = string.byte(str, i)
i = i + 1
if b1 < 0x80 then
return b1
elseif b1 >= 0xC0 and b1 < 0xE0 then
local b2 = string.byte(str, i) or 0
i = i + 1
return (b1 - 0xC0) * 64 + (b2 - 0x80)
elseif b1 >= 0xE0 and b1 < 0xF0 then
local b2 = string.byte(str, i) or 0
i = i + 1
local b3 = string.byte(str, i) or 0
i = i + 1
return (b1 - 0xE0) * 4096 + (b2 - 0x80) * 64 + (b3 - 0x80)
else
return 32 -- 不支持的字符显示为空格
end
end
end
-- 处理字符串中的每个字符
for code in utf8codes(str) do
-- 处理换行符
if code == 10 then -- \n 的 ASCII
cursorX = 1
cursorY = cursorY + fontHeight
else
local charMap = font[code] or font[32]
local charWidth = #charMap[1]
-- 检查是否需要换行
if cursorX + charWidth - 1 > width then
cursorX = 1
cursorY = cursorY + fontHeight
end
-- 检查是否需要滚动屏幕
if cursorY + fontHeight - 1 > screenHeight then
term.scroll(fontHeight)
cursorY = cursorY - fontHeight
end
-- 显示字符
displayChar(charMap, cursorX, cursorY, textColor, backgroundColor)
cursorX = cursorX + charWidth
end
end
-- 自动换行(处理完字符串后)
cursorX = 1
-- 光标应该位于下一行的顶部,而不是底部
cursorY = cursorY + fontHeight
-- 检查滚动(换行后)
if cursorY > screenHeight then
term.scroll(fontHeight)
cursorY = screenHeight - fontHeight + 1
end
end
return printUtf8