-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinit.lua
More file actions
165 lines (139 loc) · 5.67 KB
/
Copy pathinit.lua
File metadata and controls
165 lines (139 loc) · 5.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
-- mods/unicode_viewer/init.lua
local player_pages = {}
-- formspec画面を描画・表示する関数
local function show_unicode_formspec(player_name)
local start_code = player_pages[player_name] or 0
-- 表示被りを防ぐため、上位バイトの16進数2桁のみを抽出 (例: 0x3000 なら "30")
local page_hex = string.format("%02X", math.floor(start_code / 256))
-- 【重要】formspec_version[4] を文字列の先頭で結合
local formspec = "formspec_version[4]" ..
"size[10,11]" ..
"real_coordinates[true]" ..
"bgcolor[#00000000;true]"
-- 窓のサイズ 8.5x8.5(X:0.5〜9.0, Y:0.5〜9.0)の中に綺麗に収まるよう配置を厳密に計算
-- 1セルの幅・高さ = 0.45, 隙間 = 0.05
-- 計算: 0.45 * 16 + 0.05 * 15 = 7.2 + 0.75 = 7.95 (8.5 の内側に余裕を持って確実に収まります)
local cell_w = 0.45
local cell_h = 0.45
local spacing = 0.05
local start_x = 0.5
local start_y = 0.5
for row = 0, 15 do
for col = 0, 15 do
local code = start_code + (row * 16) + col
-- UnicodeコードポイントをUTF-8文字列に変換
local success, char = pcall(utf8.char, code)
-- 有効な文字に変換できなかった場合や制御文字の対策
if not success or code < 32 or (code >= 127 and code <= 159) then
char = "."
else
-- ボタンのテキスト部分でformspec構文を破壊しないよう、最低限のエスケープ処理
if char == "[" then char = "("
elseif char == "]" then char = ")"
elseif char == ";" then char = ":"
end
end
-- ボタン名を「uni_16進数」にする (例: "uni_3042")
local hex_str = string.format("%04X", code)
local btn_name = "uni_" .. hex_str
-- 各マスの正確なX, Y座標を計算
local x = start_x + (col * (cell_w + spacing))
local y = start_y + (row * (cell_h + spacing))
-- 【修正】formspec_version[4] 以降で安全にパースされる標準的な引数フォーマット
formspec = formspec .. string.format("button[%f,%f;%f,%f;%s;%s]",
x, y, cell_w, cell_h, btn_name, char)
end
end
-- 2. パネル背景 (下部コントロールエリア用)
local panel_bg = "#222222FF"
formspec = formspec .. string.format("box[0,9.0;10,2.0;%s]", panel_bg)
-- 3. UIパーツ (1行目: ページインジケータとナビゲーションボタン)
formspec = formspec .. string.format("label[0.4,9.6;Page: %s]", page_hex)
formspec = formspec .. "button[2.0,9.3;0.8,0.6;btn_prev16;-16]"
formspec = formspec .. "button[2.9,9.3;0.8,0.6;btn_prev1;-1]"
formspec = formspec .. "button[3.8,9.3;0.8,0.6;btn_reset;0]"
formspec = formspec .. "button[4.7,9.3;0.8,0.6;btn_next1;+1]"
formspec = formspec .. "button[5.6,9.3;0.8,0.6;btn_next16;+16]"
-- 4. 2行目: 16進数ジャンプ
formspec = formspec .. "label[0.5,10.4;Hex Jump:]"
formspec = formspec .. "field[2.0,10.1;2.0,0.6;jump_code;;]"
formspec = formspec .. "button[4.1,10.1;1.2,0.6;btn_jump;Jump]"
-- 5. 閉じるボタン
formspec = formspec .. "button_exit[7.5,10.1;2.0,0.6;quit;Close]"
minetest.show_formspec(player_name, "unicode_viewer:viewer", formspec)
end
-- 3. イベント処理
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= "unicode_viewer:viewer" then return false end
if fields.quit == "true" then
return true
end
local player_name = player:get_player_name()
local current_code = player_pages[player_name] or 0
local refresh = false
-- 敷き詰めた 256 個のボタンのいずれかがクリックされたかの判定
for k, v in pairs(fields) do
if string.sub(k, 1, 4) == "uni_" then
local hex_code = string.sub(k, 5) -- "uni_3042" から "3042" を切り出す
local num_code = tonumber(hex_code, 16)
local char = utf8.char(num_code)
-- チャット欄に結果を通知
minetest.chat_send_player(player_name, string.format("Selected Character: %s (U+%s)", char, hex_code))
break
end
end
-- ページ操作ロジック(1ページ=256文字、16ページ=4096文字として計算)
if fields.btn_next16 then
player_pages[player_name] = math.min(0xFF00, current_code + 4096)
refresh = true
elseif fields.btn_next1 then
player_pages[player_name] = math.min(0xFF00, current_code + 256)
refresh = true
elseif fields.btn_prev16 then
player_pages[player_name] = math.max(0, current_code - 4096)
refresh = true
elseif fields.btn_prev1 then
player_pages[player_name] = math.max(0, current_code - 256)
refresh = true
elseif fields.btn_reset then
player_pages[player_name] = 0
refresh = true
-- 「Jump」ボタンまたはEnterキーでのジャンプ
elseif fields.btn_jump or (fields.key_enter == "true" and fields.key_enter_field == "jump_code") then
local input = fields.jump_code or ""
local num = tonumber(input, 16)
if num then
if num > 0xFFFF then num = 0xFFFF
elseif num < 0 then num = 0
end
player_pages[player_name] = math.floor(num / 256) * 256
refresh = true
else
minetest.chat_send_player(player_name, "Error: Invalid hex number. (e.g. 0000, 3000, FFFF)")
end
end
if refresh and fields.quit ~= "true" then
show_unicode_formspec(player_name)
return true
end
end)
-- 4. チャットコマンドで起動
minetest.register_chatcommand("uview", {
params = "",
description = "Open Unicode Viewer",
func = function(name, param)
player_pages[name] = 0
show_unicode_formspec(name)
return true
end,
})
-- 5. アイテム登録
minetest.register_craftitem("unicode_viewer:viewer", {
description = "Unicode Viewer",
inventory_image = "unicode_view.png",
stack_max = 1,
on_use = function(itemstack, user)
if user then show_unicode_formspec(user:get_player_name()) end
return itemstack
end,
})