mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-10-18 23:47:39 +00:00
Compare commits
43 Commits
v1.14.4-1.
...
v1.14.4-1.
Author | SHA1 | Date | |
---|---|---|---|
![]() |
9134f243c1 | ||
![]() |
c0f3ca81fb | ||
![]() |
b9b8121be9 | ||
![]() |
014bf55cd4 | ||
![]() |
085ae2e74a | ||
![]() |
4ff33f165d | ||
![]() |
d929c02d2a | ||
![]() |
d50a08a549 | ||
![]() |
13de2c4dd0 | ||
![]() |
906280225e | ||
![]() |
161a5b4707 | ||
![]() |
c6b6b4479c | ||
![]() |
96e7b60285 | ||
![]() |
086fccd997 | ||
![]() |
e251dd066c | ||
![]() |
c60dcb4f5a | ||
![]() |
4be0b15afa | ||
![]() |
a4ae36b6b3 | ||
![]() |
ac075d9f53 | ||
![]() |
05d7be0362 | ||
![]() |
9a71dc1a26 | ||
![]() |
156023b154 | ||
![]() |
6b3773a862 | ||
![]() |
376d628cf0 | ||
![]() |
44062ebd52 | ||
![]() |
5739285fc2 | ||
![]() |
70b457ed18 | ||
![]() |
6816931659 | ||
![]() |
1547ecbeb3 | ||
![]() |
c28b468844 | ||
![]() |
052cf8ee7d | ||
![]() |
550ada2f9e | ||
![]() |
17b7727262 | ||
![]() |
4553e404b2 | ||
![]() |
a565a571f9 | ||
![]() |
fb64b6017b | ||
![]() |
ed4229ab70 | ||
![]() |
3fb906ef6c | ||
![]() |
e1663f3df0 | ||
![]() |
358289b5f9 | ||
![]() |
5eec24676f | ||
![]() |
447c3ab125 | ||
![]() |
8fac68386e |
3
.github/workflows/main-ci.yml
vendored
3
.github/workflows/main-ci.yml
vendored
@@ -32,6 +32,9 @@ jobs:
|
|||||||
name: CC-Tweaked
|
name: CC-Tweaked
|
||||||
path: build/libs
|
path: build/libs
|
||||||
|
|
||||||
|
- name: Upload Coverage
|
||||||
|
run: bash <(curl -s https://codecov.io/bash)
|
||||||
|
|
||||||
lint-lua:
|
lint-lua:
|
||||||
name: Lint Lua
|
name: Lint Lua
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
10
build.gradle
10
build.gradle
@@ -17,6 +17,7 @@ buildscript {
|
|||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id "checkstyle"
|
id "checkstyle"
|
||||||
|
id "jacoco"
|
||||||
id "com.github.hierynomus.license" version "0.15.0"
|
id "com.github.hierynomus.license" version "0.15.0"
|
||||||
id "com.matthewprenger.cursegradle" version "1.3.0"
|
id "com.matthewprenger.cursegradle" version "1.3.0"
|
||||||
id "com.github.breadmoirai.github-release" version "2.2.4"
|
id "com.github.breadmoirai.github-release" version "2.2.4"
|
||||||
@@ -288,6 +289,15 @@ test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jacocoTestReport {
|
||||||
|
reports {
|
||||||
|
xml.enabled true
|
||||||
|
html.enabled true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
check.dependsOn jacocoTestReport
|
||||||
|
|
||||||
license {
|
license {
|
||||||
mapping("java", "SLASHSTAR_STYLE")
|
mapping("java", "SLASHSTAR_STYLE")
|
||||||
strictCheck true
|
strictCheck true
|
||||||
|
@@ -1,6 +1,77 @@
|
|||||||
|
--- Execute a specific command.
|
||||||
|
--
|
||||||
|
-- @tparam string command The command to execute.
|
||||||
|
-- @treturn boolean Whether the command executed successfully.
|
||||||
|
-- @treturn { string... } The output of this command, as a list of lines.
|
||||||
|
-- @treturn number|nil The number of "affected" objects, or `nil` if the command
|
||||||
|
-- failed. The definition of this varies from command to command.
|
||||||
|
-- @usage Set the block above the command computer to stone.
|
||||||
|
--
|
||||||
|
-- commands.exec("setblock ~ ~1 ~ minecraft:stone")
|
||||||
function exec(command) end
|
function exec(command) end
|
||||||
|
|
||||||
|
--- Asynchronously execute a command.
|
||||||
|
--
|
||||||
|
-- Unlike @{exec}, this will immediately return, instead of waiting for the
|
||||||
|
-- command to execute. This allows you to run multiple commands at the same
|
||||||
|
-- time.
|
||||||
|
--
|
||||||
|
-- When this command has finished executing, it will queue a `task_complete`
|
||||||
|
-- event containing the result of executing this command (what @{exec} would
|
||||||
|
-- return).
|
||||||
|
--
|
||||||
|
-- @tparam string command The command to execute.
|
||||||
|
-- @treturn number The "task id". When this command has been executed, it will
|
||||||
|
-- queue a `task_complete` event with a matching id.
|
||||||
|
-- @usage Asynchronously sets the block above the computer to stone.
|
||||||
|
--
|
||||||
|
-- commands.execAsync("~ ~1 ~ minecraft:stone")
|
||||||
|
-- @see parallel One may also use the parallel API to run multiple commands at
|
||||||
|
-- once.
|
||||||
function execAsync(commad) end
|
function execAsync(commad) end
|
||||||
|
|
||||||
|
--- List all available commands which the computer has permission to execute.
|
||||||
|
--
|
||||||
|
-- @treturn { string... } A list of all available commands
|
||||||
function list() end
|
function list() end
|
||||||
|
|
||||||
|
--- Get the position of the current command computer.
|
||||||
|
--
|
||||||
|
-- @treturn number This computer's x position.
|
||||||
|
-- @treturn number This computer's y position.
|
||||||
|
-- @treturn number This computer's z position.
|
||||||
|
-- @see gps.locate To get the position of a non-command computer.
|
||||||
function getBlockPosition() end
|
function getBlockPosition() end
|
||||||
function getBlockInfos(min_x, min_y, min_z, max_x, max_y, max_z) end
|
|
||||||
|
--- Get some basic information about a block.
|
||||||
|
--
|
||||||
|
-- The returned table contains the current name, metadata and block state (as
|
||||||
|
-- with @{turtle.inspect}). If there is a tile entity for that block, its NBT
|
||||||
|
-- will also be returned.
|
||||||
|
--
|
||||||
|
-- @tparam number x The x position of the block to query.
|
||||||
|
-- @tparam number y The y position of the block to query.
|
||||||
|
-- @tparam number z The z position of the block to query.
|
||||||
|
-- @treturn table The given block's information.
|
||||||
|
-- @throws If the coordinates are not within the world, or are not currently
|
||||||
|
-- loaded.
|
||||||
function getBlockInfo(x, y, z) end
|
function getBlockInfo(x, y, z) end
|
||||||
|
|
||||||
|
--- Get information about a range of blocks.
|
||||||
|
--
|
||||||
|
-- This returns the same information as @{getBlockInfo}, just for multiple
|
||||||
|
-- blocks at once.
|
||||||
|
--
|
||||||
|
-- Blocks are traversed by ascending y level, followed by z and x - the returned
|
||||||
|
-- table may be indexed using `x + z*width + y*depth*depth`.
|
||||||
|
--
|
||||||
|
-- @tparam number min_x The start x coordinate of the range to query.
|
||||||
|
-- @tparam number min_y The start y coordinate of the range to query.
|
||||||
|
-- @tparam number min_z The start z coordinate of the range to query.
|
||||||
|
-- @tparam number max_x The end x coordinate of the range to query.
|
||||||
|
-- @tparam number max_y The end y coordinate of the range to query.
|
||||||
|
-- @tparam number max_z The end z coordinate of the range to query.
|
||||||
|
-- @treturn { table... } A list of information about each block.
|
||||||
|
-- @throws If the coordinates are not within the world.
|
||||||
|
-- @throws If trying to get information about more than 4096 blocks.
|
||||||
|
function getBlockInfos(min_x, min_y, min_z, max_x, max_y, max_z) end
|
||||||
|
@@ -19,6 +19,48 @@ function getFreeSpace(path) end
|
|||||||
function find(pattern) end
|
function find(pattern) end
|
||||||
function getDir(path) end
|
function getDir(path) end
|
||||||
|
|
||||||
|
--- Returns true if a path is mounted to the parent filesystem.
|
||||||
|
--
|
||||||
|
-- The root filesystem "/" is considered a mount, along with disk folders and
|
||||||
|
-- the rom folder. Other programs (such as network shares) can exstend this to
|
||||||
|
-- make other mount types by correctly assigning their return value for getDrive.
|
||||||
|
--
|
||||||
|
-- @tparam string path The path to check.
|
||||||
|
-- @treturn boolean If the path is mounted, rather than a normal file/folder.
|
||||||
|
-- @throws If the path does not exist.
|
||||||
|
-- @see getDrive
|
||||||
|
function isDriveRoot(path) end
|
||||||
|
|
||||||
|
--- Get the capacity of the drive at the given path.
|
||||||
|
--
|
||||||
|
-- This may be used in conjunction with @{getFreeSpace} to determine what
|
||||||
|
-- percentage of this drive has been used.
|
||||||
|
--
|
||||||
|
-- @tparam string path The path of the drive to get.
|
||||||
|
-- @treturn number This drive's capacity. This will be 0 for "read-only" drives,
|
||||||
|
-- such as the ROM or treasure disks.
|
||||||
|
function getCapacity(path) end
|
||||||
|
|
||||||
|
--- Get attributes about a specific file or folder.
|
||||||
|
--
|
||||||
|
-- The returned attributes table contains information about the size of the
|
||||||
|
-- file, whether it is a directory, and when it was created and last modified.
|
||||||
|
--
|
||||||
|
-- The creation and modification times are given as the number of milliseconds
|
||||||
|
-- since the UNIX epoch. This may be given to @{os.date} in order to convert it
|
||||||
|
-- to more usable form.
|
||||||
|
--
|
||||||
|
-- @tparam string path The path to get attributes for.
|
||||||
|
-- @treturn { size = number, isDir = boolean, created = number, modified = number }
|
||||||
|
-- The resulting attributes.
|
||||||
|
-- @throws If the path does not exist.
|
||||||
|
-- @see getSize If you only care about the file's size.
|
||||||
|
-- @see isDir If you only care whether a path is a directory or not.
|
||||||
|
function attributes(path) end
|
||||||
|
|
||||||
|
-- Defined in bios.lua
|
||||||
|
function complete(sPath, sLocation, bIncludeFiles, bIncludeDirs) end
|
||||||
|
|
||||||
--- A file handle which can be read from.
|
--- A file handle which can be read from.
|
||||||
--
|
--
|
||||||
-- @type ReadHandle
|
-- @type ReadHandle
|
||||||
|
@@ -15,3 +15,10 @@ function cancelTimer(id) end
|
|||||||
function cancelAlarm(id) end
|
function cancelAlarm(id) end
|
||||||
function epoch(timezone) end
|
function epoch(timezone) end
|
||||||
function date(format, time) end
|
function date(format, time) end
|
||||||
|
|
||||||
|
-- Defined in bios.lua
|
||||||
|
function loadAPI(path) end
|
||||||
|
function pullEvent(filter) end
|
||||||
|
function pullEventRaw(filter) end
|
||||||
|
function version() end
|
||||||
|
function run(env, path, ...) end
|
||||||
|
28
doc/stub/pocket.lua
Normal file
28
doc/stub/pocket.lua
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
--[[-
|
||||||
|
Control the current pocket computer, adding or removing upgrades.
|
||||||
|
|
||||||
|
This API is only available on pocket computers. As such, you may use its
|
||||||
|
presence to determine what kind of computer you are using:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
if pocket then
|
||||||
|
print("On a pocket computer")
|
||||||
|
else
|
||||||
|
print("On something else")
|
||||||
|
end
|
||||||
|
```
|
||||||
|
]]
|
||||||
|
|
||||||
|
--- Search the player's inventory for another upgrade, replacing the existing
|
||||||
|
-- one with that item if found.
|
||||||
|
--
|
||||||
|
-- This inventory search starts from the player's currently selected slot,
|
||||||
|
-- allowing you to prioritise upgrades.
|
||||||
|
--
|
||||||
|
-- @throws If an upgrade cannot be found.
|
||||||
|
function equipBack() end
|
||||||
|
|
||||||
|
--- Remove the pocket computer's current upgrade.
|
||||||
|
--
|
||||||
|
-- @throws If this pocket computer does not currently have an upgrade.
|
||||||
|
function unequipBack() end
|
@@ -1,14 +1,120 @@
|
|||||||
|
--[[- Interact with redstone attached to this computer.
|
||||||
|
|
||||||
|
The @{redstone} library exposes three "types" of redstone control:
|
||||||
|
- Binary input/output (@{setOutput}/@{getInput}): These simply check if a
|
||||||
|
redstone wire has any input or output. A signal strength of 1 and 15 are
|
||||||
|
treated the same.
|
||||||
|
- Analogue input/output (@{setAnalogueOutput}/@{getAnalogueInput}): These
|
||||||
|
work with the actual signal strength of the redstone wired, from 0 to 15.
|
||||||
|
- Bundled cables (@{setBundledOutput}/@{getBundledInput}): These interact with
|
||||||
|
"bundled" cables, such as those from Project:Red. These allow you to send
|
||||||
|
16 separate on/off signals. Each channel corresponds to a colour, with the
|
||||||
|
first being @{colors.white} and the last @{colors.black}.
|
||||||
|
|
||||||
|
Whenever a redstone input changes, a `redstone` event will be fired. This may
|
||||||
|
be used in or
|
||||||
|
|
||||||
|
This module may also be referred to as `rs`. For example, one may call
|
||||||
|
`rs.getSides()` instead of @{redstone.getSides}.
|
||||||
|
|
||||||
|
@module redstone
|
||||||
|
@usage Toggle the redstone signal above the computer every 0.5 seconds.
|
||||||
|
|
||||||
|
while true do
|
||||||
|
redstone.setOutput("top", not redstone.getOutput("top"))
|
||||||
|
sleep(0.5)
|
||||||
|
end
|
||||||
|
@usage Mimic a redstone comparator in [subtraction mode][comparator].
|
||||||
|
|
||||||
|
while true do
|
||||||
|
local rear = rs.getAnalogueInput("back")
|
||||||
|
local sides = math.max(rs.getAnalogueInput("left"), rs.getAnalogueInput("right"))
|
||||||
|
rs.setAnalogueOutput("front", math.max(rear - sides, 0))
|
||||||
|
|
||||||
|
os.pullEvent("redstone") -- Wait for a change to inputs.
|
||||||
|
end
|
||||||
|
|
||||||
|
[comparator]: https://minecraft.gamepedia.com/Redstone_Comparator#Subtract_signal_strength "Redstone Comparator on the Minecraft wiki."
|
||||||
|
]]
|
||||||
|
|
||||||
|
--- Returns a table containing the six sides of the computer. Namely, "top",
|
||||||
|
-- "bottom", "left", "right", "front" and "back".
|
||||||
|
--
|
||||||
|
-- @treturn { string... } A table of valid sides.
|
||||||
function getSides() end
|
function getSides() end
|
||||||
|
|
||||||
|
--- Turn the redstone signal of a specific side on or off.
|
||||||
|
--
|
||||||
|
-- @tparam string side The side to set.
|
||||||
|
-- @tparam boolean on Whether the redstone signal should be on or off. When on,
|
||||||
|
-- a signal strength of 15 is emitted.
|
||||||
function setOutput(side, on) end
|
function setOutput(side, on) end
|
||||||
|
|
||||||
|
--- Get the current redstone output of a specific side.
|
||||||
|
--
|
||||||
|
-- @tparam string side The side to get.
|
||||||
|
-- @treturn boolean Whether the redstone output is on or off.
|
||||||
|
-- @see setOutput
|
||||||
function getOutput(side) end
|
function getOutput(side) end
|
||||||
|
|
||||||
|
--- Get the current redstone input of a specific side.
|
||||||
|
--
|
||||||
|
-- @tparam string side The side to get.
|
||||||
|
-- @treturn boolean Whether the redstone input is on or off.
|
||||||
function getInput(side) end
|
function getInput(side) end
|
||||||
function setBundledOutput(side, output) end
|
|
||||||
function getBundledOutput(side) end
|
--- Set the redstone signal strength for a specific side.
|
||||||
function getBundledInput(side) end
|
--
|
||||||
function testBundledInput(side, mask) end
|
-- @tparam string side The side to set.
|
||||||
|
-- @tparam number value The signal strength, between 0 and 15.
|
||||||
|
-- @throws If `value` is not between 0 and 15.
|
||||||
function setAnalogOutput(side, value) end
|
function setAnalogOutput(side, value) end
|
||||||
setAnalogueOutput = setAnalogOutput
|
setAnalogueOutput = setAnalogOutput
|
||||||
|
|
||||||
|
--- Get the redstone output signal strength for a specific side.
|
||||||
|
--
|
||||||
|
-- @tparam string side The side to get.
|
||||||
|
-- @treturn number The output signal strength, between 0 and 15.
|
||||||
|
-- @see setAnalogueOutput
|
||||||
function getAnalogOutput(sid) end
|
function getAnalogOutput(sid) end
|
||||||
getAnalogueOutput = getAnalogOutput
|
getAnalogueOutput = getAnalogOutput
|
||||||
|
|
||||||
|
--- Get the redstone input signal strength for a specific side.
|
||||||
|
--
|
||||||
|
-- @tparam string side The side to get.
|
||||||
|
-- @treturn number The input signal strength, between 0 and 15.
|
||||||
function getAnalogInput(side) end
|
function getAnalogInput(side) end
|
||||||
getAnalogueInput = getAnaloguInput
|
getAnalogueInput = getAnalogInput
|
||||||
|
|
||||||
|
--- Set the bundled cable output for a specific side.
|
||||||
|
--
|
||||||
|
-- @tparam string side The side to set.
|
||||||
|
-- @tparam number The colour bitmask to set.
|
||||||
|
-- @see colors.subtract For removing a colour from the bitmask.
|
||||||
|
-- @see colors.combine For adding a colour to the bitmask.
|
||||||
|
function setBundledOutput(side, output) end
|
||||||
|
|
||||||
|
--- Get the bundled cable output for a specific side.
|
||||||
|
--
|
||||||
|
-- @tparam string side The side to get.
|
||||||
|
-- @treturn number The bundled cable's output.
|
||||||
|
function getBundledOutput(side) end
|
||||||
|
|
||||||
|
--- Get the bundled cable input for a specific side.
|
||||||
|
--
|
||||||
|
-- @tparam string side The side to get.
|
||||||
|
-- @treturn number The bundled cable's input.
|
||||||
|
-- @see testBundledInput To determine if a specific colour is set.
|
||||||
|
function getBundledInput(side) end
|
||||||
|
|
||||||
|
--- Determine if a specific combination of colours are on for the given side.
|
||||||
|
--
|
||||||
|
-- @tparam string side The side to test.
|
||||||
|
-- @tparam number mask The mask to test.
|
||||||
|
-- @see getBundledInput
|
||||||
|
-- @see colors.combine For adding a colour to the bitmask.
|
||||||
|
-- @usage Check if @{colors.white} and @{colors.black} are on for above the
|
||||||
|
-- computer.
|
||||||
|
--
|
||||||
|
-- print(redstone.testBundledInput("top", colors.combine(colors.white, colors.black)))
|
||||||
|
function testBundledInput(side, mask) end
|
||||||
|
@@ -15,14 +15,14 @@ isColor = isColour
|
|||||||
function getTextColour() end
|
function getTextColour() end
|
||||||
getTextColor = getTextColor
|
getTextColor = getTextColor
|
||||||
function getBackgroundColour() end
|
function getBackgroundColour() end
|
||||||
getBackgroundColour = getBackgroundColour
|
getBackgroundColor = getBackgroundColour
|
||||||
function blit(text, text_colours, background_colours) end
|
function blit(text, text_colours, background_colours) end
|
||||||
function setPaletteColour(colour, ...) end
|
function setPaletteColour(colour, ...) end
|
||||||
setPaletteColour = setPaletteColour
|
setPaletteColor = setPaletteColour
|
||||||
function getPaletteColour(colour, ...) end
|
function getPaletteColour(colour, ...) end
|
||||||
getPaletteColour = getPaletteColour
|
getPaletteColor = getPaletteColour
|
||||||
function nativePaletteColour(colour) end
|
function nativePaletteColour(colour) end
|
||||||
nativePaletteColour = nativePaletteColour
|
nativePaletteColor = nativePaletteColour
|
||||||
|
|
||||||
--- @type Redirect
|
--- @type Redirect
|
||||||
local Redirect = {}
|
local Redirect = {}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
# Mod properties
|
# Mod properties
|
||||||
mod_version=1.87.1
|
mod_version=1.89.0
|
||||||
|
|
||||||
# Minecraft properties (update mods.toml when changing)
|
# Minecraft properties (update mods.toml when changing)
|
||||||
mc_version=1.14.4
|
mc_version=1.14.4
|
||||||
|
@@ -33,17 +33,27 @@
|
|||||||
|
|
||||||
;; It's useful to name arguments for documentation, so we allow this. It'd
|
;; It's useful to name arguments for documentation, so we allow this. It'd
|
||||||
;; be good to find a compromise in the future, but this works for now.
|
;; be good to find a compromise in the future, but this works for now.
|
||||||
-var:unused-arg
|
-var:unused-arg)
|
||||||
|
|
||||||
;; Some APIS (keys, colour and os mainly) are incomplete right now.
|
|
||||||
-var:unresolved-member)
|
|
||||||
(lint
|
(lint
|
||||||
(bracket-spaces
|
(bracket-spaces
|
||||||
(call no-space)
|
(call no-space)
|
||||||
(function-args no-space)
|
(function-args no-space)
|
||||||
(parens no-space)
|
(parens no-space)
|
||||||
(table space)
|
(table space)
|
||||||
(index no-space))))
|
(index no-space))
|
||||||
|
|
||||||
|
;; colours imports from colors, and we don't handle that right now.
|
||||||
|
;; keys is entirely dynamic, so we skip it.
|
||||||
|
(dynamic-modules colours keys)
|
||||||
|
|
||||||
|
(globals
|
||||||
|
:max
|
||||||
|
_CC_DEFAULT_SETTINGS
|
||||||
|
_CC_DISABLE_LUA51_FEATURES
|
||||||
|
;; Ideally we'd pick these up from bios.lua, but illuaminate currently
|
||||||
|
;; isn't smart enough.
|
||||||
|
sleep write printError read rs)))
|
||||||
|
|
||||||
;; We disable the unused global linter in bios.lua and the APIs. In the future
|
;; We disable the unused global linter in bios.lua and the APIs. In the future
|
||||||
;; hopefully we'll get illuaminate to handle this.
|
;; hopefully we'll get illuaminate to handle this.
|
||||||
@@ -60,17 +70,13 @@
|
|||||||
|
|
||||||
;; Suppress warnings for currently undocumented modules.
|
;; Suppress warnings for currently undocumented modules.
|
||||||
(at
|
(at
|
||||||
(/doc/stub/commands.lua
|
(/doc/stub/fs.lua
|
||||||
/doc/stub/fs.lua
|
|
||||||
/doc/stub/http.lua
|
/doc/stub/http.lua
|
||||||
/doc/stub/os.lua
|
/doc/stub/os.lua
|
||||||
/doc/stub/redstone.lua
|
|
||||||
/doc/stub/term.lua
|
/doc/stub/term.lua
|
||||||
/doc/stub/turtle.lua
|
/doc/stub/turtle.lua
|
||||||
/src/main/resources/*/computercraft/lua/rom/apis/command/commands.lua
|
|
||||||
/src/main/resources/*/computercraft/lua/rom/apis/io.lua
|
/src/main/resources/*/computercraft/lua/rom/apis/io.lua
|
||||||
/src/main/resources/*/computercraft/lua/rom/apis/window.lua
|
/src/main/resources/*/computercraft/lua/rom/apis/window.lua)
|
||||||
/src/main/resources/*/computercraft/lua/rom/modules/main/cc/shell/completion.lua)
|
|
||||||
|
|
||||||
(linters -doc:undocumented -doc:undocumented-arg))
|
(linters -doc:undocumented -doc:undocumented-arg))
|
||||||
|
|
||||||
@@ -79,6 +85,11 @@
|
|||||||
(/src/main/resources/*/computercraft/lua/rom/apis/textutils.lua
|
(/src/main/resources/*/computercraft/lua/rom/apis/textutils.lua
|
||||||
/src/main/resources/*/computercraft/lua/rom/modules/main/cc/completion.lua
|
/src/main/resources/*/computercraft/lua/rom/modules/main/cc/completion.lua
|
||||||
/src/main/resources/*/computercraft/lua/rom/modules/main/cc/shell/completion.lua
|
/src/main/resources/*/computercraft/lua/rom/modules/main/cc/shell/completion.lua
|
||||||
/src/main/resources/*/computercraft/lua/rom/programs/advanced/multishell.lua
|
|
||||||
/src/main/resources/*/computercraft/lua/rom/programs/shell.lua)
|
/src/main/resources/*/computercraft/lua/rom/programs/shell.lua)
|
||||||
(linters -doc:unresolved-reference))
|
(linters -doc:unresolved-reference))
|
||||||
|
|
||||||
|
(at /src/test/resources/test-rom
|
||||||
|
(lint
|
||||||
|
(globals
|
||||||
|
:max sleep write
|
||||||
|
cct_test describe expect howlci fail it pending stub)))
|
||||||
|
@@ -17,6 +17,9 @@
|
|||||||
{
|
{
|
||||||
"condition": "computercraft:block_named"
|
"condition": "computercraft:block_named"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"condition": "computercraft:has_id"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"condition": "minecraft:inverted",
|
"condition": "minecraft:inverted",
|
||||||
"term": {
|
"term": {
|
||||||
|
@@ -17,6 +17,9 @@
|
|||||||
{
|
{
|
||||||
"condition": "computercraft:block_named"
|
"condition": "computercraft:block_named"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"condition": "computercraft:has_id"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"condition": "minecraft:inverted",
|
"condition": "minecraft:inverted",
|
||||||
"term": {
|
"term": {
|
||||||
|
@@ -17,6 +17,9 @@
|
|||||||
{
|
{
|
||||||
"condition": "computercraft:block_named"
|
"condition": "computercraft:block_named"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"condition": "computercraft:has_id"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"condition": "minecraft:inverted",
|
"condition": "minecraft:inverted",
|
||||||
"term": {
|
"term": {
|
||||||
|
@@ -17,6 +17,9 @@
|
|||||||
{
|
{
|
||||||
"condition": "computercraft:block_named"
|
"condition": "computercraft:block_named"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"condition": "computercraft:has_id"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"condition": "minecraft:inverted",
|
"condition": "minecraft:inverted",
|
||||||
"term": {
|
"term": {
|
||||||
|
@@ -65,7 +65,8 @@ public final class ComputerCraft
|
|||||||
public static boolean disable_lua51_features = false;
|
public static boolean disable_lua51_features = false;
|
||||||
public static String default_computer_settings = "";
|
public static String default_computer_settings = "";
|
||||||
public static boolean debug_enable = true;
|
public static boolean debug_enable = true;
|
||||||
public static boolean logPeripheralErrors = false;
|
public static boolean logPeripheralErrors = true;
|
||||||
|
public static boolean commandRequireCreative = true;
|
||||||
|
|
||||||
public static int computer_threads = 1;
|
public static int computer_threads = 1;
|
||||||
public static long maxMainGlobalTime = TimeUnit.MILLISECONDS.toNanos( 10 );
|
public static long maxMainGlobalTime = TimeUnit.MILLISECONDS.toNanos( 10 );
|
||||||
@@ -90,6 +91,7 @@ public final class ComputerCraft
|
|||||||
public static int modem_highAltitudeRangeDuringStorm = 384;
|
public static int modem_highAltitudeRangeDuringStorm = 384;
|
||||||
public static int maxNotesPerTick = 8;
|
public static int maxNotesPerTick = 8;
|
||||||
public static MonitorRenderer monitorRenderer = MonitorRenderer.BEST;
|
public static MonitorRenderer monitorRenderer = MonitorRenderer.BEST;
|
||||||
|
public static long monitorBandwidth = 1_000_000;
|
||||||
|
|
||||||
public static boolean turtlesNeedFuel = true;
|
public static boolean turtlesNeedFuel = true;
|
||||||
public static int turtleFuelLimit = 20000;
|
public static int turtleFuelLimit = 20000;
|
||||||
|
@@ -50,15 +50,14 @@ public final class FixedWidthFontRenderer
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
private static float toGreyscale( double[] rgb )
|
public static float toGreyscale( double[] rgb )
|
||||||
{
|
{
|
||||||
return (float) ((rgb[0] + rgb[1] + rgb[2]) / 3);
|
return (float) ((rgb[0] + rgb[1] + rgb[2]) / 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getColour( char c )
|
public static int getColour( char c, Colour def )
|
||||||
{
|
{
|
||||||
int i = "0123456789abcdef".indexOf( c );
|
return 15 - Terminal.getColour( c, def );
|
||||||
return i < 0 ? 0 : 15 - i;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void drawChar( BufferBuilder buffer, float x, float y, int index, float r, float g, float b )
|
private static void drawChar( BufferBuilder buffer, float x, float y, int index, float r, float g, float b )
|
||||||
@@ -92,7 +91,7 @@ public final class FixedWidthFontRenderer
|
|||||||
|
|
||||||
private static void drawQuad( BufferBuilder buffer, float x, float y, float width, float height, Palette palette, boolean greyscale, char colourIndex )
|
private static void drawQuad( BufferBuilder buffer, float x, float y, float width, float height, Palette palette, boolean greyscale, char colourIndex )
|
||||||
{
|
{
|
||||||
double[] colour = palette.getColour( getColour( colourIndex ) );
|
double[] colour = palette.getColour( getColour( colourIndex, Colour.Black ) );
|
||||||
float r, g, b;
|
float r, g, b;
|
||||||
if( greyscale )
|
if( greyscale )
|
||||||
{
|
{
|
||||||
@@ -160,7 +159,7 @@ public final class FixedWidthFontRenderer
|
|||||||
|
|
||||||
for( int i = 0; i < text.length(); i++ )
|
for( int i = 0; i < text.length(); i++ )
|
||||||
{
|
{
|
||||||
double[] colour = palette.getColour( getColour( textColour.charAt( i ) ) );
|
double[] colour = palette.getColour( getColour( textColour.charAt( i ), Colour.White ) );
|
||||||
float r, g, b;
|
float r, g, b;
|
||||||
if( greyscale )
|
if( greyscale )
|
||||||
{
|
{
|
||||||
|
@@ -0,0 +1,156 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||||
|
* Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission.
|
||||||
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
package dan200.computercraft.client.render;
|
||||||
|
|
||||||
|
import com.google.common.base.Strings;
|
||||||
|
import com.mojang.blaze3d.platform.GLX;
|
||||||
|
import com.mojang.blaze3d.platform.TextureUtil;
|
||||||
|
import dan200.computercraft.ComputerCraft;
|
||||||
|
import dan200.computercraft.client.gui.FixedWidthFontRenderer;
|
||||||
|
import dan200.computercraft.shared.util.Palette;
|
||||||
|
import org.lwjgl.BufferUtils;
|
||||||
|
import org.lwjgl.opengl.GL13;
|
||||||
|
import org.lwjgl.opengl.GL20;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.FloatBuffer;
|
||||||
|
|
||||||
|
class MonitorTextureBufferShader
|
||||||
|
{
|
||||||
|
static final int TEXTURE_INDEX = GL13.GL_TEXTURE3;
|
||||||
|
|
||||||
|
private static final FloatBuffer PALETTE_BUFFER = BufferUtils.createFloatBuffer( 16 * 3 );
|
||||||
|
|
||||||
|
private static int uniformFont;
|
||||||
|
private static int uniformWidth;
|
||||||
|
private static int uniformHeight;
|
||||||
|
private static int uniformTbo;
|
||||||
|
private static int uniformPalette;
|
||||||
|
|
||||||
|
private static boolean initialised;
|
||||||
|
private static boolean ok;
|
||||||
|
private static int program;
|
||||||
|
|
||||||
|
static void setupUniform( int width, int height, Palette palette, boolean greyscale )
|
||||||
|
{
|
||||||
|
GLX.glUniform1i( uniformWidth, width );
|
||||||
|
GLX.glUniform1i( uniformHeight, height );
|
||||||
|
|
||||||
|
PALETTE_BUFFER.rewind();
|
||||||
|
for( int i = 0; i < 16; i++ )
|
||||||
|
{
|
||||||
|
double[] colour = palette.getColour( i );
|
||||||
|
if( greyscale )
|
||||||
|
{
|
||||||
|
float f = FixedWidthFontRenderer.toGreyscale( colour );
|
||||||
|
PALETTE_BUFFER.put( f ).put( f ).put( f );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PALETTE_BUFFER.put( (float) colour[0] ).put( (float) colour[1] ).put( (float) colour[2] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PALETTE_BUFFER.flip();
|
||||||
|
GLX.glUniform3( uniformPalette, PALETTE_BUFFER );
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean use()
|
||||||
|
{
|
||||||
|
if( initialised )
|
||||||
|
{
|
||||||
|
if( ok ) GLX.glUseProgram( program );
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ok = load() )
|
||||||
|
{
|
||||||
|
GL20.glUseProgram( program );
|
||||||
|
GLX.glUniform1i( uniformFont, 0 );
|
||||||
|
GLX.glUniform1i( uniformTbo, TEXTURE_INDEX - GL13.GL_TEXTURE0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean load()
|
||||||
|
{
|
||||||
|
initialised = true;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
int vertexShader = loadShader( GL20.GL_VERTEX_SHADER, "assets/computercraft/shaders/monitor.vert" );
|
||||||
|
int fragmentShader = loadShader( GL20.GL_FRAGMENT_SHADER, "assets/computercraft/shaders/monitor.frag" );
|
||||||
|
|
||||||
|
program = GLX.glCreateProgram();
|
||||||
|
GLX.glAttachShader( program, vertexShader );
|
||||||
|
GLX.glAttachShader( program, fragmentShader );
|
||||||
|
GL20.glBindAttribLocation( program, 0, "v_pos" );
|
||||||
|
|
||||||
|
GLX.glLinkProgram( program );
|
||||||
|
boolean ok = GLX.glGetProgrami( program, GL20.GL_LINK_STATUS ) != 0;
|
||||||
|
String log = GLX.glGetProgramInfoLog( program, Short.MAX_VALUE ).trim();
|
||||||
|
if( !Strings.isNullOrEmpty( log ) )
|
||||||
|
{
|
||||||
|
ComputerCraft.log.warn( "Problems when linking monitor shader: {}", log );
|
||||||
|
}
|
||||||
|
|
||||||
|
GL20.glDetachShader( program, vertexShader );
|
||||||
|
GL20.glDetachShader( program, fragmentShader );
|
||||||
|
GLX.glDeleteShader( vertexShader );
|
||||||
|
GLX.glDeleteShader( fragmentShader );
|
||||||
|
|
||||||
|
if( !ok ) return false;
|
||||||
|
|
||||||
|
uniformFont = getUniformLocation( program, "u_font" );
|
||||||
|
uniformWidth = getUniformLocation( program, "u_width" );
|
||||||
|
uniformHeight = getUniformLocation( program, "u_height" );
|
||||||
|
uniformTbo = getUniformLocation( program, "u_tbo" );
|
||||||
|
uniformPalette = getUniformLocation( program, "u_palette" );
|
||||||
|
|
||||||
|
ComputerCraft.log.info( "Loaded monitor shader." );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch( Exception e )
|
||||||
|
{
|
||||||
|
ComputerCraft.log.error( "Cannot load monitor shaders", e );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int loadShader( int kind, String path ) throws IOException
|
||||||
|
{
|
||||||
|
String contents;
|
||||||
|
try( InputStream stream = TileEntityMonitorRenderer.class.getClassLoader().getResourceAsStream( path ) )
|
||||||
|
{
|
||||||
|
if( stream == null ) throw new IllegalArgumentException( "Cannot find " + path );
|
||||||
|
contents = TextureUtil.readResourceAsString( stream );
|
||||||
|
}
|
||||||
|
|
||||||
|
int shader = GLX.glCreateShader( kind );
|
||||||
|
|
||||||
|
GLX.glShaderSource( shader, contents );
|
||||||
|
GLX.glCompileShader( shader );
|
||||||
|
|
||||||
|
boolean ok = GLX.glGetShaderi( shader, GL20.GL_COMPILE_STATUS ) != 0;
|
||||||
|
String log = GLX.glGetShaderInfoLog( shader, Short.MAX_VALUE ).trim();
|
||||||
|
if( !Strings.isNullOrEmpty( log ) )
|
||||||
|
{
|
||||||
|
ComputerCraft.log.warn( "Problems when loading monitor shader {}: {}", path, log );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !ok ) throw new IllegalStateException( "Cannot compile shader " + path );
|
||||||
|
return shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int getUniformLocation( int program, String name )
|
||||||
|
{
|
||||||
|
int uniform = GLX.glGetUniformLocation( program, name );
|
||||||
|
if( uniform == -1 ) throw new IllegalStateException( "Cannot find uniform " + name );
|
||||||
|
return uniform;
|
||||||
|
}
|
||||||
|
}
|
@@ -10,26 +10,36 @@ import com.mojang.blaze3d.platform.GlStateManager;
|
|||||||
import dan200.computercraft.client.FrameInfo;
|
import dan200.computercraft.client.FrameInfo;
|
||||||
import dan200.computercraft.client.gui.FixedWidthFontRenderer;
|
import dan200.computercraft.client.gui.FixedWidthFontRenderer;
|
||||||
import dan200.computercraft.core.terminal.Terminal;
|
import dan200.computercraft.core.terminal.Terminal;
|
||||||
|
import dan200.computercraft.core.terminal.TextBuffer;
|
||||||
import dan200.computercraft.shared.peripheral.monitor.ClientMonitor;
|
import dan200.computercraft.shared.peripheral.monitor.ClientMonitor;
|
||||||
import dan200.computercraft.shared.peripheral.monitor.MonitorRenderer;
|
import dan200.computercraft.shared.peripheral.monitor.MonitorRenderer;
|
||||||
import dan200.computercraft.shared.peripheral.monitor.TileMonitor;
|
import dan200.computercraft.shared.peripheral.monitor.TileMonitor;
|
||||||
|
import dan200.computercraft.shared.util.Colour;
|
||||||
import dan200.computercraft.shared.util.DirectionUtil;
|
import dan200.computercraft.shared.util.DirectionUtil;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.renderer.BufferBuilder;
|
import net.minecraft.client.renderer.BufferBuilder;
|
||||||
|
import net.minecraft.client.renderer.GLAllocation;
|
||||||
import net.minecraft.client.renderer.Tessellator;
|
import net.minecraft.client.renderer.Tessellator;
|
||||||
import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
|
import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
|
||||||
|
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||||
import net.minecraft.client.renderer.vertex.VertexBuffer;
|
import net.minecraft.client.renderer.vertex.VertexBuffer;
|
||||||
import net.minecraft.util.Direction;
|
import net.minecraft.util.Direction;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import org.lwjgl.opengl.GL11;
|
import org.lwjgl.opengl.GL11;
|
||||||
|
import org.lwjgl.opengl.GL13;
|
||||||
|
import org.lwjgl.opengl.GL15;
|
||||||
|
import org.lwjgl.opengl.GL31;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.*;
|
||||||
import static dan200.computercraft.shared.peripheral.monitor.TileMonitor.RENDER_MARGIN;
|
import static dan200.computercraft.shared.peripheral.monitor.TileMonitor.RENDER_MARGIN;
|
||||||
|
|
||||||
public class TileEntityMonitorRenderer extends TileEntityRenderer<TileMonitor>
|
public class TileEntityMonitorRenderer extends TileEntityRenderer<TileMonitor>
|
||||||
{
|
{
|
||||||
private static final float MARGIN = (float) (TileMonitor.RENDER_MARGIN * 1.1);
|
private static final float MARGIN = (float) (TileMonitor.RENDER_MARGIN * 1.1);
|
||||||
|
private static ByteBuffer tboContents;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render( @Nonnull TileMonitor monitor, double posX, double posY, double posZ, float f, int i )
|
public void render( @Nonnull TileMonitor monitor, double posX, double posY, double posZ, float f, int i )
|
||||||
@@ -92,8 +102,8 @@ public class TileEntityMonitorRenderer extends TileEntityRenderer<TileMonitor>
|
|||||||
if( terminal != null )
|
if( terminal != null )
|
||||||
{
|
{
|
||||||
// Draw a terminal
|
// Draw a terminal
|
||||||
double xScale = xSize / (terminal.getWidth() * FixedWidthFontRenderer.FONT_WIDTH);
|
double xScale = xSize / (terminal.getWidth() * FONT_WIDTH);
|
||||||
double yScale = ySize / (terminal.getHeight() * FixedWidthFontRenderer.FONT_HEIGHT);
|
double yScale = ySize / (terminal.getHeight() * FONT_HEIGHT);
|
||||||
|
|
||||||
GlStateManager.pushMatrix();
|
GlStateManager.pushMatrix();
|
||||||
GlStateManager.scaled( (float) xScale, (float) -yScale, 1.0f );
|
GlStateManager.scaled( (float) xScale, (float) -yScale, 1.0f );
|
||||||
@@ -142,6 +152,59 @@ public class TileEntityMonitorRenderer extends TileEntityRenderer<TileMonitor>
|
|||||||
|
|
||||||
switch( renderer )
|
switch( renderer )
|
||||||
{
|
{
|
||||||
|
case TBO:
|
||||||
|
{
|
||||||
|
if( !MonitorTextureBufferShader.use() ) return;
|
||||||
|
|
||||||
|
Terminal terminal = monitor.getTerminal();
|
||||||
|
int width = terminal.getWidth(), height = terminal.getHeight();
|
||||||
|
int pixelWidth = width * FONT_WIDTH, pixelHeight = height * FONT_HEIGHT;
|
||||||
|
|
||||||
|
if( redraw )
|
||||||
|
{
|
||||||
|
int size = width * height * 3;
|
||||||
|
if( tboContents == null || tboContents.capacity() < size )
|
||||||
|
{
|
||||||
|
tboContents = GLAllocation.createDirectByteBuffer( size );
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteBuffer monitorBuffer = tboContents;
|
||||||
|
monitorBuffer.position( 0 );
|
||||||
|
for( int y = 0; y < height; y++ )
|
||||||
|
{
|
||||||
|
TextBuffer text = terminal.getLine( y ), textColour = terminal.getTextColourLine( y ), background = terminal.getBackgroundColourLine( y );
|
||||||
|
for( int x = 0; x < width; x++ )
|
||||||
|
{
|
||||||
|
monitorBuffer.put( (byte) (text.charAt( x ) & 0xFF) );
|
||||||
|
monitorBuffer.put( (byte) getColour( textColour.charAt( x ), Colour.White ) );
|
||||||
|
monitorBuffer.put( (byte) getColour( background.charAt( x ), Colour.Black ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
monitorBuffer.flip();
|
||||||
|
|
||||||
|
GLX.glBindBuffer( GL31.GL_TEXTURE_BUFFER, monitor.tboBuffer );
|
||||||
|
GLX.glBufferData( GL31.GL_TEXTURE_BUFFER, monitorBuffer, GL15.GL_STATIC_DRAW );
|
||||||
|
GLX.glBindBuffer( GL31.GL_TEXTURE_BUFFER, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bind TBO texture and set up the uniforms. We've already set up the main font above.
|
||||||
|
GlStateManager.activeTexture( MonitorTextureBufferShader.TEXTURE_INDEX );
|
||||||
|
GL11.glBindTexture( GL31.GL_TEXTURE_BUFFER, monitor.tboTexture );
|
||||||
|
GlStateManager.activeTexture( GL13.GL_TEXTURE0 );
|
||||||
|
|
||||||
|
MonitorTextureBufferShader.setupUniform( width, height, terminal.getPalette(), !monitor.isColour() );
|
||||||
|
|
||||||
|
buffer.begin( GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION );
|
||||||
|
buffer.pos( -xMargin, -yMargin, 0 ).endVertex();
|
||||||
|
buffer.pos( -xMargin, pixelHeight + yMargin, 0 ).endVertex();
|
||||||
|
buffer.pos( pixelWidth + xMargin, -yMargin, 0 ).endVertex();
|
||||||
|
buffer.pos( pixelWidth + xMargin, pixelHeight + yMargin, 0 ).endVertex();
|
||||||
|
tessellator.draw();
|
||||||
|
|
||||||
|
GLX.glUseProgram( 0 );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case VBO:
|
case VBO:
|
||||||
{
|
{
|
||||||
VertexBuffer vbo = monitor.buffer;
|
VertexBuffer vbo = monitor.buffer;
|
||||||
|
@@ -103,7 +103,7 @@ public class OSAPI implements ILuaAPI
|
|||||||
double t = alarm.m_day * 24.0 + alarm.m_time;
|
double t = alarm.m_day * 24.0 + alarm.m_time;
|
||||||
if( now >= t )
|
if( now >= t )
|
||||||
{
|
{
|
||||||
queueLuaEvent( "alarm", new Object[] { entry.getKey() } );
|
queueLuaEvent( "alarm", new Object[] { entry.getIntKey() } );
|
||||||
it.remove();
|
it.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -16,11 +16,11 @@ import static dan200.computercraft.api.lua.ArgumentHelper.*;
|
|||||||
|
|
||||||
public class RedstoneAPI implements ILuaAPI
|
public class RedstoneAPI implements ILuaAPI
|
||||||
{
|
{
|
||||||
private IAPIEnvironment m_environment;
|
private final IAPIEnvironment environment;
|
||||||
|
|
||||||
public RedstoneAPI( IAPIEnvironment environment )
|
public RedstoneAPI( IAPIEnvironment environment )
|
||||||
{
|
{
|
||||||
m_environment = environment;
|
this.environment = environment;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -63,31 +63,31 @@ public class RedstoneAPI implements ILuaAPI
|
|||||||
// setOutput
|
// setOutput
|
||||||
ComputerSide side = parseSide( args );
|
ComputerSide side = parseSide( args );
|
||||||
boolean output = getBoolean( args, 1 );
|
boolean output = getBoolean( args, 1 );
|
||||||
m_environment.setOutput( side, output ? 15 : 0 );
|
environment.setOutput( side, output ? 15 : 0 );
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
case 2: // getOutput
|
case 2: // getOutput
|
||||||
return new Object[] { m_environment.getOutput( parseSide( args ) ) > 0 };
|
return new Object[] { environment.getOutput( parseSide( args ) ) > 0 };
|
||||||
case 3: // getInput
|
case 3: // getInput
|
||||||
return new Object[] { m_environment.getInput( parseSide( args ) ) > 0 };
|
return new Object[] { environment.getInput( parseSide( args ) ) > 0 };
|
||||||
case 4:
|
case 4:
|
||||||
{
|
{
|
||||||
// setBundledOutput
|
// setBundledOutput
|
||||||
ComputerSide side = parseSide( args );
|
ComputerSide side = parseSide( args );
|
||||||
int output = getInt( args, 1 );
|
int output = getInt( args, 1 );
|
||||||
m_environment.setBundledOutput( side, output );
|
environment.setBundledOutput( side, output );
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
case 5: // getBundledOutput
|
case 5: // getBundledOutput
|
||||||
return new Object[] { m_environment.getBundledOutput( parseSide( args ) ) };
|
return new Object[] { environment.getBundledOutput( parseSide( args ) ) };
|
||||||
case 6: // getBundledInput
|
case 6: // getBundledInput
|
||||||
return new Object[] { m_environment.getBundledInput( parseSide( args ) ) };
|
return new Object[] { environment.getBundledInput( parseSide( args ) ) };
|
||||||
case 7:
|
case 7:
|
||||||
{
|
{
|
||||||
// testBundledInput
|
// testBundledInput
|
||||||
ComputerSide side = parseSide( args );
|
ComputerSide side = parseSide( args );
|
||||||
int mask = getInt( args, 1 );
|
int mask = getInt( args, 1 );
|
||||||
int input = m_environment.getBundledInput( side );
|
int input = environment.getBundledInput( side );
|
||||||
return new Object[] { (input & mask) == mask };
|
return new Object[] { (input & mask) == mask };
|
||||||
}
|
}
|
||||||
case 8:
|
case 8:
|
||||||
@@ -100,15 +100,15 @@ public class RedstoneAPI implements ILuaAPI
|
|||||||
{
|
{
|
||||||
throw new LuaException( "Expected number in range 0-15" );
|
throw new LuaException( "Expected number in range 0-15" );
|
||||||
}
|
}
|
||||||
m_environment.setOutput( side, output );
|
environment.setOutput( side, output );
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
case 10:
|
case 10:
|
||||||
case 11: // getAnalogOutput/getAnalogueOutput
|
case 11: // getAnalogOutput/getAnalogueOutput
|
||||||
return new Object[] { m_environment.getOutput( parseSide( args ) ) };
|
return new Object[] { environment.getOutput( parseSide( args ) ) };
|
||||||
case 12:
|
case 12:
|
||||||
case 13: // getAnalogInput/getAnalogueInput
|
case 13: // getAnalogInput/getAnalogueInput
|
||||||
return new Object[] { m_environment.getInput( parseSide( args ) ) };
|
return new Object[] { environment.getInput( parseSide( args ) ) };
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@@ -37,12 +37,8 @@ public abstract class HandleGeneric implements ILuaObject
|
|||||||
{
|
{
|
||||||
m_open = false;
|
m_open = false;
|
||||||
|
|
||||||
Closeable closeable = m_closable;
|
IoUtil.closeQuietly( m_closable );
|
||||||
if( closeable != null )
|
m_closable = null;
|
||||||
{
|
|
||||||
IoUtil.closeQuietly( closeable );
|
|
||||||
m_closable = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -106,7 +106,7 @@ public abstract class Resource<T extends Resource<T>> implements Closeable
|
|||||||
|
|
||||||
protected static <T extends Closeable> T closeCloseable( T closeable )
|
protected static <T extends Closeable> T closeCloseable( T closeable )
|
||||||
{
|
{
|
||||||
if( closeable != null ) IoUtil.closeQuietly( closeable );
|
IoUtil.closeQuietly( closeable );
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -221,7 +221,7 @@ public class Websocket extends Resource<Websocket>
|
|||||||
|
|
||||||
WeakReference<WebsocketHandle> websocketHandleRef = websocketHandle;
|
WeakReference<WebsocketHandle> websocketHandleRef = websocketHandle;
|
||||||
WebsocketHandle websocketHandle = websocketHandleRef == null ? null : websocketHandleRef.get();
|
WebsocketHandle websocketHandle = websocketHandleRef == null ? null : websocketHandleRef.get();
|
||||||
if( websocketHandle != null ) IoUtil.closeQuietly( websocketHandle );
|
IoUtil.closeQuietly( websocketHandle );
|
||||||
this.websocketHandle = null;
|
this.websocketHandle = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -366,8 +366,7 @@ public class FileSystem
|
|||||||
Reference<?> ref;
|
Reference<?> ref;
|
||||||
while( (ref = m_openFileQueue.poll()) != null )
|
while( (ref = m_openFileQueue.poll()) != null )
|
||||||
{
|
{
|
||||||
Closeable file = m_openFiles.remove( ref );
|
IoUtil.closeQuietly( m_openFiles.remove( ref ) );
|
||||||
if( file != null ) IoUtil.closeQuietly( file );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -5,18 +5,20 @@
|
|||||||
*/
|
*/
|
||||||
package dan200.computercraft.core.terminal;
|
package dan200.computercraft.core.terminal;
|
||||||
|
|
||||||
|
import dan200.computercraft.shared.util.Colour;
|
||||||
import dan200.computercraft.shared.util.Palette;
|
import dan200.computercraft.shared.util.Palette;
|
||||||
import net.minecraft.nbt.CompoundNBT;
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
|
import net.minecraft.network.PacketBuffer;
|
||||||
|
|
||||||
public class Terminal
|
public class Terminal
|
||||||
{
|
{
|
||||||
private static final String base16 = "0123456789abcdef";
|
private static final String base16 = "0123456789abcdef";
|
||||||
|
|
||||||
private int m_cursorX;
|
private int m_cursorX = 0;
|
||||||
private int m_cursorY;
|
private int m_cursorY = 0;
|
||||||
private boolean m_cursorBlink;
|
private boolean m_cursorBlink = false;
|
||||||
private int m_cursorColour;
|
private int m_cursorColour = 0;
|
||||||
private int m_cursorBackgroundColour;
|
private int m_cursorBackgroundColour = 15;
|
||||||
|
|
||||||
private int m_width;
|
private int m_width;
|
||||||
private int m_height;
|
private int m_height;
|
||||||
@@ -25,9 +27,9 @@ public class Terminal
|
|||||||
private TextBuffer[] m_textColour;
|
private TextBuffer[] m_textColour;
|
||||||
private TextBuffer[] m_backgroundColour;
|
private TextBuffer[] m_backgroundColour;
|
||||||
|
|
||||||
private final Palette m_palette;
|
private final Palette m_palette = new Palette();
|
||||||
|
|
||||||
private boolean m_changed;
|
private boolean m_changed = false;
|
||||||
private final Runnable onChanged;
|
private final Runnable onChanged;
|
||||||
|
|
||||||
public Terminal( int width, int height )
|
public Terminal( int width, int height )
|
||||||
@@ -41,9 +43,6 @@ public class Terminal
|
|||||||
m_height = height;
|
m_height = height;
|
||||||
onChanged = changedCallback;
|
onChanged = changedCallback;
|
||||||
|
|
||||||
m_cursorColour = 0;
|
|
||||||
m_cursorBackgroundColour = 15;
|
|
||||||
|
|
||||||
m_text = new TextBuffer[m_height];
|
m_text = new TextBuffer[m_height];
|
||||||
m_textColour = new TextBuffer[m_height];
|
m_textColour = new TextBuffer[m_height];
|
||||||
m_backgroundColour = new TextBuffer[m_height];
|
m_backgroundColour = new TextBuffer[m_height];
|
||||||
@@ -53,14 +52,6 @@ public class Terminal
|
|||||||
m_textColour[i] = new TextBuffer( base16.charAt( m_cursorColour ), m_width );
|
m_textColour[i] = new TextBuffer( base16.charAt( m_cursorColour ), m_width );
|
||||||
m_backgroundColour[i] = new TextBuffer( base16.charAt( m_cursorBackgroundColour ), m_width );
|
m_backgroundColour[i] = new TextBuffer( base16.charAt( m_cursorBackgroundColour ), m_width );
|
||||||
}
|
}
|
||||||
|
|
||||||
m_cursorX = 0;
|
|
||||||
m_cursorY = 0;
|
|
||||||
m_cursorBlink = false;
|
|
||||||
|
|
||||||
m_changed = false;
|
|
||||||
|
|
||||||
m_palette = new Palette();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void reset()
|
public synchronized void reset()
|
||||||
@@ -336,6 +327,62 @@ public class Terminal
|
|||||||
m_changed = false;
|
m_changed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public synchronized void write( PacketBuffer buffer )
|
||||||
|
{
|
||||||
|
buffer.writeInt( m_cursorX );
|
||||||
|
buffer.writeInt( m_cursorY );
|
||||||
|
buffer.writeBoolean( m_cursorBlink );
|
||||||
|
buffer.writeByte( m_cursorBackgroundColour << 4 | m_cursorColour );
|
||||||
|
|
||||||
|
for( int y = 0; y < m_height; y++ )
|
||||||
|
{
|
||||||
|
TextBuffer text = m_text[y];
|
||||||
|
TextBuffer textColour = m_textColour[y];
|
||||||
|
TextBuffer backColour = m_backgroundColour[y];
|
||||||
|
|
||||||
|
for( int x = 0; x < m_width; x++ )
|
||||||
|
{
|
||||||
|
buffer.writeByte( text.charAt( x ) & 0xFF );
|
||||||
|
buffer.writeByte( getColour(
|
||||||
|
backColour.charAt( x ), Colour.Black ) << 4 |
|
||||||
|
getColour( textColour.charAt( x ), Colour.White )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_palette.write( buffer );
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void read( PacketBuffer buffer )
|
||||||
|
{
|
||||||
|
m_cursorX = buffer.readInt();
|
||||||
|
m_cursorY = buffer.readInt();
|
||||||
|
m_cursorBlink = buffer.readBoolean();
|
||||||
|
|
||||||
|
byte cursorColour = buffer.readByte();
|
||||||
|
m_cursorBackgroundColour = (cursorColour >> 4) & 0xF;
|
||||||
|
m_cursorColour = cursorColour & 0xF;
|
||||||
|
|
||||||
|
for( int y = 0; y < m_height; y++ )
|
||||||
|
{
|
||||||
|
TextBuffer text = m_text[y];
|
||||||
|
TextBuffer textColour = m_textColour[y];
|
||||||
|
TextBuffer backColour = m_backgroundColour[y];
|
||||||
|
|
||||||
|
for( int x = 0; x < m_width; x++ )
|
||||||
|
{
|
||||||
|
text.setChar( x, (char) (buffer.readByte() & 0xFF) );
|
||||||
|
|
||||||
|
byte colour = buffer.readByte();
|
||||||
|
backColour.setChar( x, base16.charAt( (colour >> 4) & 0xF ) );
|
||||||
|
textColour.setChar( x, base16.charAt( colour & 0xF ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_palette.read( buffer );
|
||||||
|
setChanged();
|
||||||
|
}
|
||||||
|
|
||||||
public synchronized CompoundNBT writeToNBT( CompoundNBT nbt )
|
public synchronized CompoundNBT writeToNBT( CompoundNBT nbt )
|
||||||
{
|
{
|
||||||
nbt.putInt( "term_cursorX", m_cursorX );
|
nbt.putInt( "term_cursorX", m_cursorX );
|
||||||
@@ -349,10 +396,8 @@ public class Terminal
|
|||||||
nbt.putString( "term_textColour_" + n, m_textColour[n].toString() );
|
nbt.putString( "term_textColour_" + n, m_textColour[n].toString() );
|
||||||
nbt.putString( "term_textBgColour_" + n, m_backgroundColour[n].toString() );
|
nbt.putString( "term_textBgColour_" + n, m_backgroundColour[n].toString() );
|
||||||
}
|
}
|
||||||
if( m_palette != null )
|
|
||||||
{
|
m_palette.writeToNBT( nbt );
|
||||||
m_palette.writeToNBT( nbt );
|
|
||||||
}
|
|
||||||
return nbt;
|
return nbt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -382,10 +427,15 @@ public class Terminal
|
|||||||
m_backgroundColour[n].write( nbt.getString( "term_textBgColour_" + n ) );
|
m_backgroundColour[n].write( nbt.getString( "term_textBgColour_" + n ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( m_palette != null )
|
|
||||||
{
|
m_palette.readFromNBT( nbt );
|
||||||
m_palette.readFromNBT( nbt );
|
|
||||||
}
|
|
||||||
setChanged();
|
setChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int getColour( char c, Colour def )
|
||||||
|
{
|
||||||
|
if( c >= '0' && c <= '9' ) return c - '0';
|
||||||
|
if( c >= 'a' && c <= 'f' ) return c - 'a' + 10;
|
||||||
|
return 15 - def.ordinal();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -8,6 +8,7 @@ package dan200.computercraft.data;
|
|||||||
|
|
||||||
import dan200.computercraft.ComputerCraft;
|
import dan200.computercraft.ComputerCraft;
|
||||||
import dan200.computercraft.shared.data.BlockNamedEntityLootCondition;
|
import dan200.computercraft.shared.data.BlockNamedEntityLootCondition;
|
||||||
|
import dan200.computercraft.shared.data.HasComputerIdLootCondition;
|
||||||
import dan200.computercraft.shared.data.PlayerCreativeLootCondition;
|
import dan200.computercraft.shared.data.PlayerCreativeLootCondition;
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.data.DataGenerator;
|
import net.minecraft.data.DataGenerator;
|
||||||
@@ -67,6 +68,7 @@ public class LootTables extends LootTableProvider
|
|||||||
.addEntry( DynamicLootEntry.func_216162_a( new ResourceLocation( ComputerCraft.MOD_ID, "computer" ) ) )
|
.addEntry( DynamicLootEntry.func_216162_a( new ResourceLocation( ComputerCraft.MOD_ID, "computer" ) ) )
|
||||||
.acceptCondition( Alternative.builder(
|
.acceptCondition( Alternative.builder(
|
||||||
BlockNamedEntityLootCondition.builder(),
|
BlockNamedEntityLootCondition.builder(),
|
||||||
|
HasComputerIdLootCondition.builder(),
|
||||||
PlayerCreativeLootCondition.builder().inverted()
|
PlayerCreativeLootCondition.builder().inverted()
|
||||||
) )
|
) )
|
||||||
).build() );
|
).build() );
|
||||||
|
@@ -13,6 +13,7 @@ import dan200.computercraft.ComputerCraft;
|
|||||||
import dan200.computercraft.api.turtle.event.TurtleAction;
|
import dan200.computercraft.api.turtle.event.TurtleAction;
|
||||||
import dan200.computercraft.core.apis.AddressPredicate;
|
import dan200.computercraft.core.apis.AddressPredicate;
|
||||||
import dan200.computercraft.core.apis.http.websocket.Websocket;
|
import dan200.computercraft.core.apis.http.websocket.Websocket;
|
||||||
|
import dan200.computercraft.shared.peripheral.monitor.MonitorRenderer;
|
||||||
import net.minecraftforge.common.ForgeConfigSpec;
|
import net.minecraftforge.common.ForgeConfigSpec;
|
||||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||||
import net.minecraftforge.fml.ModLoadingContext;
|
import net.minecraftforge.fml.ModLoadingContext;
|
||||||
@@ -66,6 +67,7 @@ public final class Config
|
|||||||
private static final ConfigValue<Integer> modemRangeDuringStorm;
|
private static final ConfigValue<Integer> modemRangeDuringStorm;
|
||||||
private static final ConfigValue<Integer> modemHighAltitudeRangeDuringStorm;
|
private static final ConfigValue<Integer> modemHighAltitudeRangeDuringStorm;
|
||||||
private static final ConfigValue<Integer> maxNotesPerTick;
|
private static final ConfigValue<Integer> maxNotesPerTick;
|
||||||
|
private static final ConfigValue<Integer> monitorBandwidth;
|
||||||
|
|
||||||
private static final ConfigValue<Boolean> turtlesNeedFuel;
|
private static final ConfigValue<Boolean> turtlesNeedFuel;
|
||||||
private static final ConfigValue<Integer> turtleFuelLimit;
|
private static final ConfigValue<Integer> turtleFuelLimit;
|
||||||
@@ -74,7 +76,10 @@ public final class Config
|
|||||||
private static final ConfigValue<Boolean> turtlesCanPush;
|
private static final ConfigValue<Boolean> turtlesCanPush;
|
||||||
private static final ConfigValue<List<? extends String>> turtleDisabledActions;
|
private static final ConfigValue<List<? extends String>> turtleDisabledActions;
|
||||||
|
|
||||||
private static final ForgeConfigSpec spec;
|
private static final ConfigValue<MonitorRenderer> monitorRenderer;
|
||||||
|
|
||||||
|
private static final ForgeConfigSpec commonSpec;
|
||||||
|
private static final ForgeConfigSpec clientSpec;
|
||||||
|
|
||||||
private Config() {}
|
private Config() {}
|
||||||
|
|
||||||
@@ -226,6 +231,16 @@ public final class Config
|
|||||||
.comment( "Maximum amount of notes a speaker can play at once" )
|
.comment( "Maximum amount of notes a speaker can play at once" )
|
||||||
.defineInRange( "max_notes_per_tick", ComputerCraft.maxNotesPerTick, 1, Integer.MAX_VALUE );
|
.defineInRange( "max_notes_per_tick", ComputerCraft.maxNotesPerTick, 1, Integer.MAX_VALUE );
|
||||||
|
|
||||||
|
monitorBandwidth = builder
|
||||||
|
.comment( "The limit to how much monitor data can be sent *per tick*. Note:\n" +
|
||||||
|
" - Bandwidth is measured before compression, so the data sent to the client is smaller.\n" +
|
||||||
|
" - This ignores the number of players a packet is sent to. Updating a monitor for one player consumes " +
|
||||||
|
"the same bandwidth limit as sending to 20.\n" +
|
||||||
|
" - A full sized monitor sends ~25kb of data. So the default (1MB) allows for ~40 monitors to be updated " +
|
||||||
|
"in a single tick. \n" +
|
||||||
|
"Set to 0 to disable." )
|
||||||
|
.defineInRange( "monitor_bandwidth", (int) ComputerCraft.monitorBandwidth, 0, Integer.MAX_VALUE );
|
||||||
|
|
||||||
builder.pop();
|
builder.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,12 +275,20 @@ public final class Config
|
|||||||
builder.pop();
|
builder.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
spec = builder.build();
|
commonSpec = builder.build();
|
||||||
|
|
||||||
|
Builder clientBuilder = new Builder();
|
||||||
|
monitorRenderer = clientBuilder
|
||||||
|
.comment( "The renderer to use for monitors. Generally this should be kept at \"best\" - if " +
|
||||||
|
"monitors have performance issues, you may wish to experiment with alternative renderers." )
|
||||||
|
.defineEnum( "monitor_renderer", MonitorRenderer.BEST );
|
||||||
|
clientSpec = clientBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void load()
|
public static void load()
|
||||||
{
|
{
|
||||||
ModLoadingContext.get().registerConfig( ModConfig.Type.COMMON, spec );
|
ModLoadingContext.get().registerConfig( ModConfig.Type.COMMON, commonSpec );
|
||||||
|
ModLoadingContext.get().registerConfig( ModConfig.Type.CLIENT, clientSpec );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void sync()
|
public static void sync()
|
||||||
@@ -305,6 +328,7 @@ public final class Config
|
|||||||
ComputerCraft.modem_highAltitudeRange = modemHighAltitudeRange.get();
|
ComputerCraft.modem_highAltitudeRange = modemHighAltitudeRange.get();
|
||||||
ComputerCraft.modem_rangeDuringStorm = modemRangeDuringStorm.get();
|
ComputerCraft.modem_rangeDuringStorm = modemRangeDuringStorm.get();
|
||||||
ComputerCraft.modem_highAltitudeRangeDuringStorm = modemHighAltitudeRangeDuringStorm.get();
|
ComputerCraft.modem_highAltitudeRangeDuringStorm = modemHighAltitudeRangeDuringStorm.get();
|
||||||
|
ComputerCraft.monitorBandwidth = monitorBandwidth.get();
|
||||||
|
|
||||||
// Turtles
|
// Turtles
|
||||||
ComputerCraft.turtlesNeedFuel = turtlesNeedFuel.get();
|
ComputerCraft.turtlesNeedFuel = turtlesNeedFuel.get();
|
||||||
@@ -315,6 +339,9 @@ public final class Config
|
|||||||
|
|
||||||
ComputerCraft.turtleDisabledActions.clear();
|
ComputerCraft.turtleDisabledActions.clear();
|
||||||
for( String value : turtleDisabledActions.get() ) ComputerCraft.turtleDisabledActions.add( getAction( value ) );
|
for( String value : turtleDisabledActions.get() ) ComputerCraft.turtleDisabledActions.add( getAction( value ) );
|
||||||
|
|
||||||
|
// Client
|
||||||
|
ComputerCraft.monitorRenderer = monitorRenderer.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
package dan200.computercraft.shared.common;
|
package dan200.computercraft.shared.common;
|
||||||
|
|
||||||
import dan200.computercraft.core.terminal.Terminal;
|
import dan200.computercraft.core.terminal.Terminal;
|
||||||
import net.minecraft.nbt.CompoundNBT;
|
import dan200.computercraft.shared.network.client.TerminalState;
|
||||||
|
|
||||||
public class ClientTerminal implements ITerminal
|
public class ClientTerminal implements ITerminal
|
||||||
{
|
{
|
||||||
@@ -46,14 +46,13 @@ public class ClientTerminal implements ITerminal
|
|||||||
return m_colour;
|
return m_colour;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void readDescription( CompoundNBT nbt )
|
public void read( TerminalState state )
|
||||||
{
|
{
|
||||||
m_colour = nbt.getBoolean( "colour" );
|
m_colour = state.colour;
|
||||||
if( nbt.contains( "terminal" ) )
|
if( state.hasTerminal() )
|
||||||
{
|
{
|
||||||
CompoundNBT terminal = nbt.getCompound( "terminal" );
|
resizeTerminal( state.width, state.height );
|
||||||
resizeTerminal( terminal.getInt( "term_width" ), terminal.getInt( "term_height" ) );
|
state.apply( m_terminal );
|
||||||
m_terminal.readFromNBT( terminal );
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
package dan200.computercraft.shared.common;
|
package dan200.computercraft.shared.common;
|
||||||
|
|
||||||
import dan200.computercraft.core.terminal.Terminal;
|
import dan200.computercraft.core.terminal.Terminal;
|
||||||
import net.minecraft.nbt.CompoundNBT;
|
import dan200.computercraft.shared.network.client.TerminalState;
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
@@ -69,8 +69,6 @@ public class ServerTerminal implements ITerminal
|
|||||||
return m_terminalChangedLastFrame;
|
return m_terminalChangedLastFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ITerminal implementation
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Terminal getTerminal()
|
public Terminal getTerminal()
|
||||||
{
|
{
|
||||||
@@ -83,18 +81,8 @@ public class ServerTerminal implements ITerminal
|
|||||||
return m_colour;
|
return m_colour;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Networking stuff
|
public TerminalState write()
|
||||||
|
|
||||||
public void writeDescription( CompoundNBT nbt )
|
|
||||||
{
|
{
|
||||||
nbt.putBoolean( "colour", m_colour );
|
return new TerminalState( m_colour, m_terminal );
|
||||||
if( m_terminal != null )
|
|
||||||
{
|
|
||||||
CompoundNBT terminal = new CompoundNBT();
|
|
||||||
terminal.putInt( "term_width", m_terminal.getWidth() );
|
|
||||||
terminal.putInt( "term_height", m_terminal.getHeight() );
|
|
||||||
m_terminal.writeToNBT( terminal );
|
|
||||||
nbt.put( "terminal", terminal );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -120,6 +120,11 @@ public class TileCommandComputer extends TileComputer
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isUsable( PlayerEntity player, boolean ignoreRange )
|
public boolean isUsable( PlayerEntity player, boolean ignoreRange )
|
||||||
|
{
|
||||||
|
return isUsable( player ) && super.isUsable( player, ignoreRange );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isUsable( PlayerEntity player )
|
||||||
{
|
{
|
||||||
MinecraftServer server = player.getServer();
|
MinecraftServer server = player.getServer();
|
||||||
if( server == null || !server.isCommandBlockEnabled() )
|
if( server == null || !server.isCommandBlockEnabled() )
|
||||||
@@ -127,14 +132,12 @@ public class TileCommandComputer extends TileComputer
|
|||||||
player.sendStatusMessage( new TranslationTextComponent( "advMode.notEnabled" ), true );
|
player.sendStatusMessage( new TranslationTextComponent( "advMode.notEnabled" ), true );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if( !player.canUseCommandBlock() )
|
else if( ComputerCraft.commandRequireCreative ? !player.canUseCommandBlock() : !server.getPlayerList().canSendCommands( player.getGameProfile() ) )
|
||||||
{
|
{
|
||||||
player.sendStatusMessage( new TranslationTextComponent( "advMode.notAllowed" ), true );
|
player.sendStatusMessage( new TranslationTextComponent( "advMode.notAllowed" ), true );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
return true;
|
||||||
return super.isUsable( player, ignoreRange );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -277,7 +277,7 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
|
|||||||
if( offset.equals( neighbour ) )
|
if( offset.equals( neighbour ) )
|
||||||
{
|
{
|
||||||
updateSideInput( computer, dir, offset );
|
updateSideInput( computer, dir, offset );
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -35,4 +35,3 @@ public enum ComputerState implements IStringSerializable
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -154,9 +154,7 @@ public class ServerComputer extends ServerTerminal implements IComputer, IComput
|
|||||||
|
|
||||||
protected NetworkMessage createTerminalPacket()
|
protected NetworkMessage createTerminalPacket()
|
||||||
{
|
{
|
||||||
CompoundNBT tagCompound = new CompoundNBT();
|
return new ComputerTerminalClientMessage( getInstanceID(), write() );
|
||||||
writeDescription( tagCompound );
|
|
||||||
return new ComputerTerminalClientMessage( getInstanceID(), tagCompound );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void broadcastState( boolean force )
|
public void broadcastState( boolean force )
|
||||||
|
@@ -6,6 +6,7 @@
|
|||||||
package dan200.computercraft.shared.computer.inventory;
|
package dan200.computercraft.shared.computer.inventory;
|
||||||
|
|
||||||
import dan200.computercraft.ComputerCraft;
|
import dan200.computercraft.ComputerCraft;
|
||||||
|
import dan200.computercraft.shared.computer.blocks.TileCommandComputer;
|
||||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||||
import dan200.computercraft.shared.computer.core.IContainerComputer;
|
import dan200.computercraft.shared.computer.core.IContainerComputer;
|
||||||
import dan200.computercraft.shared.computer.core.ServerComputer;
|
import dan200.computercraft.shared.computer.core.ServerComputer;
|
||||||
@@ -14,8 +15,6 @@ import dan200.computercraft.shared.network.container.ViewComputerContainerData;
|
|||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.entity.player.PlayerInventory;
|
import net.minecraft.entity.player.PlayerInventory;
|
||||||
import net.minecraft.inventory.container.ContainerType;
|
import net.minecraft.inventory.container.ContainerType;
|
||||||
import net.minecraft.server.MinecraftServer;
|
|
||||||
import net.minecraft.util.text.TranslationTextComponent;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
@@ -48,18 +47,9 @@ public class ContainerViewComputer extends ContainerComputerBase implements ICon
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If we're a command computer then ensure we're in creative
|
// If we're a command computer then ensure we're in creative
|
||||||
if( computer.getFamily() == ComputerFamily.Command )
|
if( computer.getFamily() == ComputerFamily.Command && !TileCommandComputer.isUsable( player ) )
|
||||||
{
|
{
|
||||||
MinecraftServer server = player.getServer();
|
return false;
|
||||||
if( server == null || !server.isCommandBlockEnabled() )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if( !player.canUseCommandBlock() )
|
|
||||||
{
|
|
||||||
player.sendStatusMessage( new TranslationTextComponent( "advMode.notAllowed" ), false );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@@ -19,9 +19,7 @@ public final class ComputerItemFactory
|
|||||||
@Nonnull
|
@Nonnull
|
||||||
public static ItemStack create( TileComputer tile )
|
public static ItemStack create( TileComputer tile )
|
||||||
{
|
{
|
||||||
String label = tile.getLabel();
|
return create( tile.getComputerID(), tile.getLabel(), tile.getFamily() );
|
||||||
int id = label != null ? tile.getComputerID() : -1;
|
|
||||||
return create( id, label, tile.getFamily() );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
|
@@ -37,7 +37,7 @@ public abstract class ItemComputerBase extends BlockItem implements IComputerIte
|
|||||||
@Override
|
@Override
|
||||||
public void addInformation( @Nonnull ItemStack stack, @Nullable World world, @Nonnull List<ITextComponent> list, @Nonnull ITooltipFlag options )
|
public void addInformation( @Nonnull ItemStack stack, @Nullable World world, @Nonnull List<ITextComponent> list, @Nonnull ITooltipFlag options )
|
||||||
{
|
{
|
||||||
if( options.isAdvanced() )
|
if( options.isAdvanced() || getLabel( stack ) == null )
|
||||||
{
|
{
|
||||||
int id = getComputerID( stack );
|
int id = getComputerID( stack );
|
||||||
if( id >= 0 )
|
if( id >= 0 )
|
||||||
|
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||||
|
* Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission.
|
||||||
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
|
*/
|
||||||
|
package dan200.computercraft.shared.data;
|
||||||
|
|
||||||
|
import dan200.computercraft.shared.computer.blocks.IComputerTile;
|
||||||
|
import net.minecraft.tileentity.TileEntity;
|
||||||
|
import net.minecraft.world.storage.loot.LootContext;
|
||||||
|
import net.minecraft.world.storage.loot.LootParameter;
|
||||||
|
import net.minecraft.world.storage.loot.LootParameters;
|
||||||
|
import net.minecraft.world.storage.loot.conditions.ILootCondition;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A loot condition which checks if the tile entity has has a non-0 ID.
|
||||||
|
*/
|
||||||
|
public final class HasComputerIdLootCondition implements ILootCondition
|
||||||
|
{
|
||||||
|
public static final HasComputerIdLootCondition INSTANCE = new HasComputerIdLootCondition();
|
||||||
|
|
||||||
|
private HasComputerIdLootCondition()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test( LootContext lootContext )
|
||||||
|
{
|
||||||
|
TileEntity tile = lootContext.get( LootParameters.BLOCK_ENTITY );
|
||||||
|
return tile instanceof IComputerTile && ((IComputerTile) tile).getComputerID() >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public Set<LootParameter<?>> getRequiredParameters()
|
||||||
|
{
|
||||||
|
return Collections.singleton( LootParameters.BLOCK_ENTITY );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IBuilder builder()
|
||||||
|
{
|
||||||
|
return () -> INSTANCE;
|
||||||
|
}
|
||||||
|
}
|
@@ -14,9 +14,11 @@ import net.minecraft.network.PacketBuffer;
|
|||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraft.world.chunk.Chunk;
|
||||||
import net.minecraftforge.fml.network.NetworkDirection;
|
import net.minecraftforge.fml.network.NetworkDirection;
|
||||||
import net.minecraftforge.fml.network.NetworkEvent;
|
import net.minecraftforge.fml.network.NetworkEvent;
|
||||||
import net.minecraftforge.fml.network.NetworkRegistry;
|
import net.minecraftforge.fml.network.NetworkRegistry;
|
||||||
|
import net.minecraftforge.fml.network.PacketDistributor;
|
||||||
import net.minecraftforge.fml.network.simple.SimpleChannel;
|
import net.minecraftforge.fml.network.simple.SimpleChannel;
|
||||||
import net.minecraftforge.fml.server.ServerLifecycleHooks;
|
import net.minecraftforge.fml.server.ServerLifecycleHooks;
|
||||||
|
|
||||||
@@ -52,6 +54,7 @@ public final class NetworkHandler
|
|||||||
registerMainThread( 12, ComputerDeletedClientMessage::new );
|
registerMainThread( 12, ComputerDeletedClientMessage::new );
|
||||||
registerMainThread( 13, ComputerTerminalClientMessage::new );
|
registerMainThread( 13, ComputerTerminalClientMessage::new );
|
||||||
registerMainThread( 14, PlayRecordClientMessage.class, PlayRecordClientMessage::new );
|
registerMainThread( 14, PlayRecordClientMessage.class, PlayRecordClientMessage::new );
|
||||||
|
registerMainThread( 15, MonitorClientMessage.class, MonitorClientMessage::new );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void sendToPlayer( PlayerEntity player, NetworkMessage packet )
|
public static void sendToPlayer( PlayerEntity player, NetworkMessage packet )
|
||||||
@@ -74,15 +77,13 @@ public final class NetworkHandler
|
|||||||
|
|
||||||
public static void sendToAllAround( NetworkMessage packet, World world, Vec3d pos, double range )
|
public static void sendToAllAround( NetworkMessage packet, World world, Vec3d pos, double range )
|
||||||
{
|
{
|
||||||
for( ServerPlayerEntity player : ServerLifecycleHooks.getCurrentServer().getPlayerList().getPlayers() )
|
PacketDistributor.TargetPoint target = new PacketDistributor.TargetPoint( pos.x, pos.y, pos.z, range, world.getDimension().getType() );
|
||||||
{
|
network.send( PacketDistributor.NEAR.with( () -> target ), packet );
|
||||||
if( player.getEntityWorld() != world ) continue;
|
}
|
||||||
|
|
||||||
double x = pos.x - player.posX;
|
public static void sendToAllTracking( NetworkMessage packet, Chunk chunk )
|
||||||
double y = pos.y - player.posY;
|
{
|
||||||
double z = pos.z - player.posZ;
|
network.send( PacketDistributor.TRACKING_CHUNK.with( () -> chunk ), packet );
|
||||||
if( x * x + y * y + z * z < range * range ) sendToPlayer( player, packet );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -5,7 +5,6 @@
|
|||||||
*/
|
*/
|
||||||
package dan200.computercraft.shared.network.client;
|
package dan200.computercraft.shared.network.client;
|
||||||
|
|
||||||
import net.minecraft.nbt.CompoundNBT;
|
|
||||||
import net.minecraft.network.PacketBuffer;
|
import net.minecraft.network.PacketBuffer;
|
||||||
import net.minecraftforge.fml.network.NetworkEvent;
|
import net.minecraftforge.fml.network.NetworkEvent;
|
||||||
|
|
||||||
@@ -13,12 +12,12 @@ import javax.annotation.Nonnull;
|
|||||||
|
|
||||||
public class ComputerTerminalClientMessage extends ComputerClientMessage
|
public class ComputerTerminalClientMessage extends ComputerClientMessage
|
||||||
{
|
{
|
||||||
private CompoundNBT tag;
|
private TerminalState state;
|
||||||
|
|
||||||
public ComputerTerminalClientMessage( int instanceId, CompoundNBT tag )
|
public ComputerTerminalClientMessage( int instanceId, TerminalState state )
|
||||||
{
|
{
|
||||||
super( instanceId );
|
super( instanceId );
|
||||||
this.tag = tag;
|
this.state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ComputerTerminalClientMessage()
|
public ComputerTerminalClientMessage()
|
||||||
@@ -29,19 +28,19 @@ public class ComputerTerminalClientMessage extends ComputerClientMessage
|
|||||||
public void toBytes( @Nonnull PacketBuffer buf )
|
public void toBytes( @Nonnull PacketBuffer buf )
|
||||||
{
|
{
|
||||||
super.toBytes( buf );
|
super.toBytes( buf );
|
||||||
buf.writeCompoundTag( tag ); // TODO: Do we need to compress this?
|
state.write( buf );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void fromBytes( @Nonnull PacketBuffer buf )
|
public void fromBytes( @Nonnull PacketBuffer buf )
|
||||||
{
|
{
|
||||||
super.fromBytes( buf );
|
super.fromBytes( buf );
|
||||||
tag = buf.readCompoundTag();
|
state = new TerminalState( buf );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handle( NetworkEvent.Context context )
|
public void handle( NetworkEvent.Context context )
|
||||||
{
|
{
|
||||||
getComputer().readDescription( tag );
|
getComputer().read( state );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||||
|
* Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission.
|
||||||
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
package dan200.computercraft.shared.network.client;
|
||||||
|
|
||||||
|
import dan200.computercraft.shared.network.NetworkMessage;
|
||||||
|
import dan200.computercraft.shared.peripheral.monitor.TileMonitor;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.entity.player.ClientPlayerEntity;
|
||||||
|
import net.minecraft.network.PacketBuffer;
|
||||||
|
import net.minecraft.tileentity.TileEntity;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraftforge.fml.network.NetworkEvent;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
|
public class MonitorClientMessage implements NetworkMessage
|
||||||
|
{
|
||||||
|
private final BlockPos pos;
|
||||||
|
private final TerminalState state;
|
||||||
|
|
||||||
|
public MonitorClientMessage( BlockPos pos, TerminalState state )
|
||||||
|
{
|
||||||
|
this.pos = pos;
|
||||||
|
this.state = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MonitorClientMessage( @Nonnull PacketBuffer buf )
|
||||||
|
{
|
||||||
|
pos = buf.readBlockPos();
|
||||||
|
state = new TerminalState( buf );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void toBytes( @Nonnull PacketBuffer buf )
|
||||||
|
{
|
||||||
|
buf.writeBlockPos( pos );
|
||||||
|
state.write( buf );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle( NetworkEvent.Context context )
|
||||||
|
{
|
||||||
|
ClientPlayerEntity player = Minecraft.getInstance().player;
|
||||||
|
if( player == null || player.world == null ) return;
|
||||||
|
|
||||||
|
TileEntity te = player.world.getTileEntity( pos );
|
||||||
|
if( !(te instanceof TileMonitor) ) return;
|
||||||
|
|
||||||
|
((TileMonitor) te).read( state );
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,183 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||||
|
* Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission.
|
||||||
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
package dan200.computercraft.shared.network.client;
|
||||||
|
|
||||||
|
import dan200.computercraft.core.terminal.Terminal;
|
||||||
|
import dan200.computercraft.shared.util.IoUtil;
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.buffer.ByteBufInputStream;
|
||||||
|
import io.netty.buffer.ByteBufOutputStream;
|
||||||
|
import io.netty.buffer.Unpooled;
|
||||||
|
import net.minecraft.network.PacketBuffer;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.UncheckedIOException;
|
||||||
|
import java.util.zip.GZIPInputStream;
|
||||||
|
import java.util.zip.GZIPOutputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A snapshot of a terminal's state.
|
||||||
|
*
|
||||||
|
* This is somewhat memory inefficient (we build a buffer, only to write it elsewhere), however it means we get a
|
||||||
|
* complete and accurate description of a terminal, which avoids a lot of complexities with resizing terminals, dirty
|
||||||
|
* states, etc...
|
||||||
|
*/
|
||||||
|
public class TerminalState
|
||||||
|
{
|
||||||
|
public final boolean colour;
|
||||||
|
|
||||||
|
public final int width;
|
||||||
|
public final int height;
|
||||||
|
|
||||||
|
private final boolean compress;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private final ByteBuf buffer;
|
||||||
|
|
||||||
|
private ByteBuf compressed;
|
||||||
|
|
||||||
|
public TerminalState( boolean colour, @Nullable Terminal terminal )
|
||||||
|
{
|
||||||
|
this( colour, terminal, true );
|
||||||
|
}
|
||||||
|
|
||||||
|
public TerminalState( boolean colour, @Nullable Terminal terminal, boolean compress )
|
||||||
|
{
|
||||||
|
this.colour = colour;
|
||||||
|
this.compress = compress;
|
||||||
|
|
||||||
|
if( terminal == null )
|
||||||
|
{
|
||||||
|
this.width = this.height = 0;
|
||||||
|
this.buffer = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.width = terminal.getWidth();
|
||||||
|
this.height = terminal.getHeight();
|
||||||
|
|
||||||
|
ByteBuf buf = this.buffer = Unpooled.buffer();
|
||||||
|
terminal.write( new PacketBuffer( buf ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public TerminalState( PacketBuffer buf )
|
||||||
|
{
|
||||||
|
this.colour = buf.readBoolean();
|
||||||
|
this.compress = buf.readBoolean();
|
||||||
|
|
||||||
|
if( buf.readBoolean() )
|
||||||
|
{
|
||||||
|
this.width = buf.readVarInt();
|
||||||
|
this.height = buf.readVarInt();
|
||||||
|
|
||||||
|
int length = buf.readVarInt();
|
||||||
|
this.buffer = readCompressed( buf, length, compress );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.width = this.height = 0;
|
||||||
|
this.buffer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write( PacketBuffer buf )
|
||||||
|
{
|
||||||
|
buf.writeBoolean( colour );
|
||||||
|
buf.writeBoolean( compress );
|
||||||
|
|
||||||
|
buf.writeBoolean( buffer != null );
|
||||||
|
if( buffer != null )
|
||||||
|
{
|
||||||
|
buf.writeVarInt( width );
|
||||||
|
buf.writeVarInt( height );
|
||||||
|
|
||||||
|
ByteBuf sendBuffer = getCompressed();
|
||||||
|
buf.writeVarInt( sendBuffer.readableBytes() );
|
||||||
|
buf.writeBytes( sendBuffer, sendBuffer.readerIndex(), sendBuffer.readableBytes() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasTerminal()
|
||||||
|
{
|
||||||
|
return buffer != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size()
|
||||||
|
{
|
||||||
|
return buffer == null ? 0 : buffer.readableBytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void apply( Terminal terminal )
|
||||||
|
{
|
||||||
|
if( buffer == null ) throw new NullPointerException( "buffer" );
|
||||||
|
terminal.read( new PacketBuffer( buffer ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
private ByteBuf getCompressed()
|
||||||
|
{
|
||||||
|
if( buffer == null ) throw new NullPointerException( "buffer" );
|
||||||
|
if( !compress ) return buffer;
|
||||||
|
if( compressed != null ) return compressed;
|
||||||
|
|
||||||
|
ByteBuf compressed = Unpooled.directBuffer();
|
||||||
|
OutputStream stream = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
stream = new GZIPOutputStream( new ByteBufOutputStream( compressed ) );
|
||||||
|
stream.write( buffer.array(), buffer.arrayOffset(), buffer.readableBytes() );
|
||||||
|
}
|
||||||
|
catch( IOException e )
|
||||||
|
{
|
||||||
|
throw new UncheckedIOException( e );
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
IoUtil.closeQuietly( stream );
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.compressed = compressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ByteBuf readCompressed( ByteBuf buf, int length, boolean compress )
|
||||||
|
{
|
||||||
|
if( compress )
|
||||||
|
{
|
||||||
|
ByteBuf buffer = Unpooled.buffer();
|
||||||
|
InputStream stream = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
stream = new GZIPInputStream( new ByteBufInputStream( buf, length ) );
|
||||||
|
byte[] swap = new byte[8192];
|
||||||
|
while( true )
|
||||||
|
{
|
||||||
|
int bytes = stream.read( swap );
|
||||||
|
if( bytes == -1 ) break;
|
||||||
|
buffer.writeBytes( swap, 0, bytes );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch( IOException e )
|
||||||
|
{
|
||||||
|
throw new UncheckedIOException( e );
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
IoUtil.closeQuietly( stream );
|
||||||
|
}
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ByteBuf buffer = Unpooled.buffer( length );
|
||||||
|
buf.readBytes( buffer, length );
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -5,12 +5,18 @@
|
|||||||
*/
|
*/
|
||||||
package dan200.computercraft.shared.peripheral.monitor;
|
package dan200.computercraft.shared.peripheral.monitor;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.platform.GLX;
|
||||||
|
import com.mojang.blaze3d.platform.GlStateManager;
|
||||||
import dan200.computercraft.client.gui.FixedWidthFontRenderer;
|
import dan200.computercraft.client.gui.FixedWidthFontRenderer;
|
||||||
import dan200.computercraft.shared.common.ClientTerminal;
|
import dan200.computercraft.shared.common.ClientTerminal;
|
||||||
import net.minecraft.client.renderer.vertex.VertexBuffer;
|
import net.minecraft.client.renderer.vertex.VertexBuffer;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
import org.lwjgl.opengl.GL11;
|
||||||
|
import org.lwjgl.opengl.GL15;
|
||||||
|
import org.lwjgl.opengl.GL30;
|
||||||
|
import org.lwjgl.opengl.GL31;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@@ -25,6 +31,8 @@ public final class ClientMonitor extends ClientTerminal
|
|||||||
public long lastRenderFrame = -1;
|
public long lastRenderFrame = -1;
|
||||||
public BlockPos lastRenderPos = null;
|
public BlockPos lastRenderPos = null;
|
||||||
|
|
||||||
|
public int tboBuffer;
|
||||||
|
public int tboTexture;
|
||||||
public VertexBuffer buffer;
|
public VertexBuffer buffer;
|
||||||
|
|
||||||
public ClientMonitor( boolean colour, TileMonitor origin )
|
public ClientMonitor( boolean colour, TileMonitor origin )
|
||||||
@@ -50,6 +58,26 @@ public final class ClientMonitor extends ClientTerminal
|
|||||||
{
|
{
|
||||||
switch( renderer )
|
switch( renderer )
|
||||||
{
|
{
|
||||||
|
case TBO:
|
||||||
|
{
|
||||||
|
if( tboBuffer != 0 ) return false;
|
||||||
|
|
||||||
|
deleteBuffers();
|
||||||
|
|
||||||
|
tboBuffer = GLX.glGenBuffers();
|
||||||
|
GLX.glBindBuffer( GL31.GL_TEXTURE_BUFFER, tboBuffer );
|
||||||
|
GL15.glBufferData( GL31.GL_TEXTURE_BUFFER, 0, GL15.GL_STATIC_DRAW );
|
||||||
|
tboTexture = GlStateManager.genTexture();
|
||||||
|
GL11.glBindTexture( GL31.GL_TEXTURE_BUFFER, tboTexture );
|
||||||
|
GL31.glTexBuffer( GL31.GL_TEXTURE_BUFFER, GL30.GL_R8, tboBuffer );
|
||||||
|
GL11.glBindTexture( GL31.GL_TEXTURE_BUFFER, 0 );
|
||||||
|
|
||||||
|
GLX.glBindBuffer( GL31.GL_TEXTURE_BUFFER, 0 );
|
||||||
|
|
||||||
|
addMonitor();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
case VBO:
|
case VBO:
|
||||||
if( buffer != null ) return false;
|
if( buffer != null ) return false;
|
||||||
|
|
||||||
@@ -73,6 +101,19 @@ public final class ClientMonitor extends ClientTerminal
|
|||||||
|
|
||||||
private void deleteBuffers()
|
private void deleteBuffers()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
if( tboBuffer != 0 )
|
||||||
|
{
|
||||||
|
GLX.glDeleteBuffers( tboBuffer );
|
||||||
|
tboBuffer = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( tboTexture != 0 )
|
||||||
|
{
|
||||||
|
GlStateManager.deleteTexture( tboTexture );
|
||||||
|
tboTexture = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if( buffer != null )
|
if( buffer != null )
|
||||||
{
|
{
|
||||||
buffer.deleteGlBuffers();
|
buffer.deleteGlBuffers();
|
||||||
@@ -83,7 +124,7 @@ public final class ClientMonitor extends ClientTerminal
|
|||||||
@OnlyIn( Dist.CLIENT )
|
@OnlyIn( Dist.CLIENT )
|
||||||
public void destroy()
|
public void destroy()
|
||||||
{
|
{
|
||||||
if( buffer != null )
|
if( tboBuffer != 0 || buffer != null )
|
||||||
{
|
{
|
||||||
synchronized( allMonitors )
|
synchronized( allMonitors )
|
||||||
{
|
{
|
||||||
|
@@ -6,12 +6,11 @@
|
|||||||
|
|
||||||
package dan200.computercraft.shared.peripheral.monitor;
|
package dan200.computercraft.shared.peripheral.monitor;
|
||||||
|
|
||||||
import com.mojang.blaze3d.platform.GLX;
|
|
||||||
import dan200.computercraft.ComputerCraft;
|
import dan200.computercraft.ComputerCraft;
|
||||||
import dan200.computercraft.client.render.TileEntityMonitorRenderer;
|
import dan200.computercraft.client.render.TileEntityMonitorRenderer;
|
||||||
|
import org.lwjgl.opengl.GL;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The render type to use for monitors.
|
* The render type to use for monitors.
|
||||||
@@ -26,6 +25,13 @@ public enum MonitorRenderer
|
|||||||
*/
|
*/
|
||||||
BEST,
|
BEST,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render using texture buffer objects.
|
||||||
|
*
|
||||||
|
* @see org.lwjgl.opengl.GL31#glTexBuffer(int, int, int)
|
||||||
|
*/
|
||||||
|
TBO,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render using VBOs.
|
* Render using VBOs.
|
||||||
*
|
*
|
||||||
@@ -33,37 +39,6 @@ public enum MonitorRenderer
|
|||||||
*/
|
*/
|
||||||
VBO;
|
VBO;
|
||||||
|
|
||||||
private static final MonitorRenderer[] VALUES = values();
|
|
||||||
public static final String[] NAMES;
|
|
||||||
|
|
||||||
private final String displayName = "gui.computercraft:config.peripheral.monitor_renderer." + name().toLowerCase( Locale.ROOT );
|
|
||||||
|
|
||||||
static
|
|
||||||
{
|
|
||||||
NAMES = new String[VALUES.length];
|
|
||||||
for( int i = 0; i < VALUES.length; i++ ) NAMES[i] = VALUES[i].displayName();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String displayName()
|
|
||||||
{
|
|
||||||
return displayName;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
public static MonitorRenderer ofString( String name )
|
|
||||||
{
|
|
||||||
for( MonitorRenderer backend : VALUES )
|
|
||||||
{
|
|
||||||
if( backend.displayName.equalsIgnoreCase( name ) || backend.name().equalsIgnoreCase( name ) )
|
|
||||||
{
|
|
||||||
return backend;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ComputerCraft.log.warn( "Unknown monitor renderer {}. Falling back to default.", name );
|
|
||||||
return BEST;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current renderer to use.
|
* Get the current renderer to use.
|
||||||
*
|
*
|
||||||
@@ -77,15 +52,16 @@ public enum MonitorRenderer
|
|||||||
{
|
{
|
||||||
case BEST:
|
case BEST:
|
||||||
return best();
|
return best();
|
||||||
case VBO:
|
case TBO:
|
||||||
if( !GLX.useVbo() )
|
checkCapabilities();
|
||||||
|
if( !textureBuffer )
|
||||||
{
|
{
|
||||||
ComputerCraft.log.warn( "VBOs are not supported on your graphics card. Falling back to default." );
|
ComputerCraft.log.warn( "Texture buffers are not supported on your graphics card. Falling back to default." );
|
||||||
ComputerCraft.monitorRenderer = BEST;
|
ComputerCraft.monitorRenderer = BEST;
|
||||||
return best();
|
return best();
|
||||||
}
|
}
|
||||||
|
|
||||||
return VBO;
|
return TBO;
|
||||||
default:
|
default:
|
||||||
return current;
|
return current;
|
||||||
}
|
}
|
||||||
@@ -93,6 +69,18 @@ public enum MonitorRenderer
|
|||||||
|
|
||||||
private static MonitorRenderer best()
|
private static MonitorRenderer best()
|
||||||
{
|
{
|
||||||
return VBO;
|
checkCapabilities();
|
||||||
|
return textureBuffer ? TBO : VBO;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean initialised = false;
|
||||||
|
private static boolean textureBuffer = false;
|
||||||
|
|
||||||
|
private static void checkCapabilities()
|
||||||
|
{
|
||||||
|
if( initialised ) return;
|
||||||
|
|
||||||
|
textureBuffer = GL.getCapabilities().OpenGL31;
|
||||||
|
initialised = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,104 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||||
|
* Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission.
|
||||||
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
package dan200.computercraft.shared.peripheral.monitor;
|
||||||
|
|
||||||
|
import dan200.computercraft.ComputerCraft;
|
||||||
|
import dan200.computercraft.shared.network.NetworkHandler;
|
||||||
|
import dan200.computercraft.shared.network.client.MonitorClientMessage;
|
||||||
|
import dan200.computercraft.shared.network.client.TerminalState;
|
||||||
|
import net.minecraft.tileentity.TileEntity;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.ChunkPos;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraft.world.chunk.Chunk;
|
||||||
|
import net.minecraft.world.server.ServerWorld;
|
||||||
|
import net.minecraftforge.event.TickEvent;
|
||||||
|
import net.minecraftforge.event.world.ChunkWatchEvent;
|
||||||
|
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||||
|
import net.minecraftforge.fml.common.Mod;
|
||||||
|
|
||||||
|
import java.util.ArrayDeque;
|
||||||
|
import java.util.Queue;
|
||||||
|
|
||||||
|
@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID )
|
||||||
|
public final class MonitorWatcher
|
||||||
|
{
|
||||||
|
private static final Queue<TileMonitor> watching = new ArrayDeque<>();
|
||||||
|
|
||||||
|
private MonitorWatcher()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void enqueue( TileMonitor monitor )
|
||||||
|
{
|
||||||
|
if( monitor.enqueued ) return;
|
||||||
|
|
||||||
|
monitor.enqueued = true;
|
||||||
|
monitor.cached = null;
|
||||||
|
watching.add( monitor );
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void onWatch( ChunkWatchEvent.Watch event )
|
||||||
|
{
|
||||||
|
ChunkPos chunkPos = event.getPos();
|
||||||
|
Chunk chunk = event.getWorld().getChunk( chunkPos.x, chunkPos.z );
|
||||||
|
if( chunk == null ) return;
|
||||||
|
|
||||||
|
for( TileEntity te : chunk.getTileEntityMap().values() )
|
||||||
|
{
|
||||||
|
// Find all origin monitors who are not already on the queue.
|
||||||
|
if( !(te instanceof TileMonitor) ) continue;
|
||||||
|
|
||||||
|
TileMonitor monitor = (TileMonitor) te;
|
||||||
|
ServerMonitor serverMonitor = getMonitor( monitor );
|
||||||
|
if( serverMonitor == null || monitor.enqueued ) continue;
|
||||||
|
|
||||||
|
// We use the cached terminal state if available - this is guaranteed to
|
||||||
|
TerminalState state = monitor.cached;
|
||||||
|
if( state == null ) state = monitor.cached = serverMonitor.write();
|
||||||
|
NetworkHandler.sendToPlayer( event.getPlayer(), new MonitorClientMessage( monitor.getPos(), state ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void onTick( TickEvent.ServerTickEvent event )
|
||||||
|
{
|
||||||
|
if( event.phase != TickEvent.Phase.END ) return;
|
||||||
|
|
||||||
|
long limit = ComputerCraft.monitorBandwidth;
|
||||||
|
boolean obeyLimit = limit > 0;
|
||||||
|
|
||||||
|
TileMonitor tile;
|
||||||
|
while( (!obeyLimit || limit > 0) && (tile = watching.poll()) != null )
|
||||||
|
{
|
||||||
|
tile.enqueued = false;
|
||||||
|
ServerMonitor monitor = getMonitor( tile );
|
||||||
|
if( monitor == null ) continue;
|
||||||
|
|
||||||
|
BlockPos pos = tile.getPos();
|
||||||
|
World world = tile.getWorld();
|
||||||
|
if( !(world instanceof ServerWorld) ) continue;
|
||||||
|
|
||||||
|
Chunk chunk = world.getChunkAt( pos );
|
||||||
|
if( !((ServerWorld) world).getChunkProvider().chunkManager.getTrackingPlayers( chunk.getPos(), false ).findAny().isPresent() )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
TerminalState state = tile.cached = monitor.write();
|
||||||
|
NetworkHandler.sendToAllTracking( new MonitorClientMessage( pos, state ), chunk );
|
||||||
|
|
||||||
|
limit -= state.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ServerMonitor getMonitor( TileMonitor monitor )
|
||||||
|
{
|
||||||
|
return !monitor.isRemoved() && monitor.getXIndex() == 0 && monitor.getYIndex() == 0 ? monitor.getCachedServerMonitor() : null;
|
||||||
|
}
|
||||||
|
}
|
@@ -12,6 +12,7 @@ import dan200.computercraft.api.peripheral.IPeripheralTile;
|
|||||||
import dan200.computercraft.core.terminal.Terminal;
|
import dan200.computercraft.core.terminal.Terminal;
|
||||||
import dan200.computercraft.shared.common.ServerTerminal;
|
import dan200.computercraft.shared.common.ServerTerminal;
|
||||||
import dan200.computercraft.shared.common.TileGeneric;
|
import dan200.computercraft.shared.common.TileGeneric;
|
||||||
|
import dan200.computercraft.shared.network.client.TerminalState;
|
||||||
import dan200.computercraft.shared.util.NamedTileEntityType;
|
import dan200.computercraft.shared.util.NamedTileEntityType;
|
||||||
import dan200.computercraft.shared.util.TickScheduler;
|
import dan200.computercraft.shared.util.TickScheduler;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
@@ -63,6 +64,10 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile
|
|||||||
private boolean m_destroyed = false;
|
private boolean m_destroyed = false;
|
||||||
private boolean visiting = false;
|
private boolean visiting = false;
|
||||||
|
|
||||||
|
// MonitorWatcher state.
|
||||||
|
boolean enqueued;
|
||||||
|
TerminalState cached;
|
||||||
|
|
||||||
private int m_width = 1;
|
private int m_width = 1;
|
||||||
private int m_height = 1;
|
private int m_height = 1;
|
||||||
private int m_xIndex = 0;
|
private int m_xIndex = 0;
|
||||||
@@ -170,7 +175,7 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( m_serverMonitor.pollTerminalChanged() ) updateBlock();
|
if( m_serverMonitor.pollTerminalChanged() ) MonitorWatcher.enqueue( this );
|
||||||
}
|
}
|
||||||
|
|
||||||
// IPeripheralTile implementation
|
// IPeripheralTile implementation
|
||||||
@@ -249,16 +254,10 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile
|
|||||||
protected void writeDescription( @Nonnull CompoundNBT nbt )
|
protected void writeDescription( @Nonnull CompoundNBT nbt )
|
||||||
{
|
{
|
||||||
super.writeDescription( nbt );
|
super.writeDescription( nbt );
|
||||||
|
|
||||||
nbt.putInt( NBT_X, m_xIndex );
|
nbt.putInt( NBT_X, m_xIndex );
|
||||||
nbt.putInt( NBT_Y, m_yIndex );
|
nbt.putInt( NBT_Y, m_yIndex );
|
||||||
nbt.putInt( NBT_WIDTH, m_width );
|
nbt.putInt( NBT_WIDTH, m_width );
|
||||||
nbt.putInt( NBT_HEIGHT, m_height );
|
nbt.putInt( NBT_HEIGHT, m_height );
|
||||||
|
|
||||||
if( m_xIndex == 0 && m_yIndex == 0 && m_serverMonitor != null )
|
|
||||||
{
|
|
||||||
m_serverMonitor.writeDescription( nbt );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -286,9 +285,8 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile
|
|||||||
|
|
||||||
if( m_xIndex == 0 && m_yIndex == 0 )
|
if( m_xIndex == 0 && m_yIndex == 0 )
|
||||||
{
|
{
|
||||||
// If we're the origin terminal then read the description
|
// If we're the origin terminal then create it.
|
||||||
if( m_clientMonitor == null ) m_clientMonitor = new ClientMonitor( advanced, this );
|
if( m_clientMonitor == null ) m_clientMonitor = new ClientMonitor( advanced, this );
|
||||||
m_clientMonitor.readDescription( nbt );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( oldXIndex != m_xIndex || oldYIndex != m_yIndex ||
|
if( oldXIndex != m_xIndex || oldYIndex != m_yIndex ||
|
||||||
@@ -299,6 +297,20 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final void read( TerminalState state )
|
||||||
|
{
|
||||||
|
if( m_xIndex != 0 || m_yIndex != 0 )
|
||||||
|
{
|
||||||
|
ComputerCraft.log.warn( "Receiving monitor state for non-origin terminal at {}", getPos() );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( m_clientMonitor == null ) m_clientMonitor = new ClientMonitor( advanced, this );
|
||||||
|
m_clientMonitor.read( state );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sizing and placement stuff
|
||||||
|
|
||||||
private void updateBlockState()
|
private void updateBlockState()
|
||||||
{
|
{
|
||||||
getWorld().setBlockState( getPos(), getBlockState()
|
getWorld().setBlockState( getPos(), getBlockState()
|
||||||
|
@@ -154,4 +154,3 @@ public abstract class SpeakerPeripheral implements IPeripheral
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -78,4 +78,3 @@ public class TileSpeaker extends TileGeneric implements ITickableTileEntity, IPe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -184,7 +184,7 @@ public class ItemPocketComputer extends Item implements IComputerItem, IMedia, I
|
|||||||
@Override
|
@Override
|
||||||
public void addInformation( @Nonnull ItemStack stack, @Nullable World world, List<ITextComponent> list, ITooltipFlag flag )
|
public void addInformation( @Nonnull ItemStack stack, @Nullable World world, List<ITextComponent> list, ITooltipFlag flag )
|
||||||
{
|
{
|
||||||
if( flag.isAdvanced() )
|
if( flag.isAdvanced() || getLabel( stack ) == null )
|
||||||
{
|
{
|
||||||
int id = getComputerID( stack );
|
int id = getComputerID( stack );
|
||||||
if( id >= 0 )
|
if( id >= 0 )
|
||||||
|
@@ -20,6 +20,7 @@ import dan200.computercraft.shared.computer.core.IContainerComputer;
|
|||||||
import dan200.computercraft.shared.computer.core.ServerComputer;
|
import dan200.computercraft.shared.computer.core.ServerComputer;
|
||||||
import dan200.computercraft.shared.data.BlockNamedEntityLootCondition;
|
import dan200.computercraft.shared.data.BlockNamedEntityLootCondition;
|
||||||
import dan200.computercraft.shared.data.ConstantLootConditionSerializer;
|
import dan200.computercraft.shared.data.ConstantLootConditionSerializer;
|
||||||
|
import dan200.computercraft.shared.data.HasComputerIdLootCondition;
|
||||||
import dan200.computercraft.shared.data.PlayerCreativeLootCondition;
|
import dan200.computercraft.shared.data.PlayerCreativeLootCondition;
|
||||||
import dan200.computercraft.shared.media.items.RecordMedia;
|
import dan200.computercraft.shared.media.items.RecordMedia;
|
||||||
import dan200.computercraft.shared.network.NetworkHandler;
|
import dan200.computercraft.shared.network.NetworkHandler;
|
||||||
@@ -72,6 +73,12 @@ public final class ComputerCraftProxyCommon
|
|||||||
PlayerCreativeLootCondition.class,
|
PlayerCreativeLootCondition.class,
|
||||||
PlayerCreativeLootCondition.INSTANCE
|
PlayerCreativeLootCondition.INSTANCE
|
||||||
) );
|
) );
|
||||||
|
|
||||||
|
LootConditionManager.registerCondition( ConstantLootConditionSerializer.of(
|
||||||
|
new ResourceLocation( ComputerCraft.MOD_ID, "has_id" ),
|
||||||
|
HasComputerIdLootCondition.class,
|
||||||
|
HasComputerIdLootCondition.INSTANCE
|
||||||
|
) );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void registerProviders()
|
private static void registerProviders()
|
||||||
|
@@ -19,6 +19,7 @@ import dan200.computercraft.core.tracking.TrackingField;
|
|||||||
import dan200.computercraft.shared.turtle.core.*;
|
import dan200.computercraft.shared.turtle.core.*;
|
||||||
import net.minecraft.item.Item;
|
import net.minecraft.item.Item;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
import net.minecraftforge.common.MinecraftForge;
|
import net.minecraftforge.common.MinecraftForge;
|
||||||
import net.minecraftforge.registries.ForgeRegistries;
|
import net.minecraftforge.registries.ForgeRegistries;
|
||||||
|
|
||||||
@@ -31,8 +32,8 @@ import static dan200.computercraft.api.lua.ArgumentHelper.*;
|
|||||||
|
|
||||||
public class TurtleAPI implements ILuaAPI
|
public class TurtleAPI implements ILuaAPI
|
||||||
{
|
{
|
||||||
private IAPIEnvironment m_environment;
|
private final IAPIEnvironment m_environment;
|
||||||
private ITurtleAccess m_turtle;
|
private final ITurtleAccess m_turtle;
|
||||||
|
|
||||||
public TurtleAPI( IAPIEnvironment environment, ITurtleAccess turtle )
|
public TurtleAPI( IAPIEnvironment environment, ITurtleAccess turtle )
|
||||||
{
|
{
|
||||||
@@ -351,6 +352,10 @@ public class TurtleAPI implements ILuaAPI
|
|||||||
table.put( "name", name );
|
table.put( "name", name );
|
||||||
table.put( "count", count );
|
table.put( "count", count );
|
||||||
|
|
||||||
|
Map<String, Boolean> tags = new HashMap<>();
|
||||||
|
for( ResourceLocation location : item.getTags() ) tags.put( location.toString(), true );
|
||||||
|
table.put( "tags", tags );
|
||||||
|
|
||||||
TurtleActionEvent event = new TurtleInspectItemEvent( m_turtle, stack, table );
|
TurtleActionEvent event = new TurtleInspectItemEvent( m_turtle, stack, table );
|
||||||
if( MinecraftForge.EVENT_BUS.post( event ) ) return new Object[] { false, event.getFailureMessage() };
|
if( MinecraftForge.EVENT_BUS.post( event ) ) return new Object[] { false, event.getFailureMessage() };
|
||||||
|
|
||||||
|
@@ -14,6 +14,7 @@ import net.minecraft.block.Block;
|
|||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.state.IProperty;
|
import net.minecraft.state.IProperty;
|
||||||
import net.minecraft.util.Direction;
|
import net.minecraft.util.Direction;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraftforge.common.MinecraftForge;
|
import net.minecraftforge.common.MinecraftForge;
|
||||||
@@ -64,6 +65,10 @@ public class TurtleInspectCommand implements ITurtleCommand
|
|||||||
}
|
}
|
||||||
table.put( "state", stateTable );
|
table.put( "state", stateTable );
|
||||||
|
|
||||||
|
Map<String, Boolean> tags = new HashMap<>();
|
||||||
|
for( ResourceLocation location : block.getTags() ) tags.put( location.toString(), true );
|
||||||
|
table.put( "tags", tags );
|
||||||
|
|
||||||
// Fire the event, exiting if it is cancelled
|
// Fire the event, exiting if it is cancelled
|
||||||
TurtlePlayer turtlePlayer = TurtlePlaceCommand.createPlayer( turtle, oldPosition, direction );
|
TurtlePlayer turtlePlayer = TurtlePlaceCommand.createPlayer( turtle, oldPosition, direction );
|
||||||
TurtleBlockEvent.Inspect event = new TurtleBlockEvent.Inspect( turtle, turtlePlayer, world, newPosition, state, table );
|
TurtleBlockEvent.Inspect event = new TurtleBlockEvent.Inspect( turtle, turtlePlayer, world, newPosition, state, table );
|
||||||
|
@@ -6,6 +6,7 @@
|
|||||||
package dan200.computercraft.shared.turtle.items;
|
package dan200.computercraft.shared.turtle.items;
|
||||||
|
|
||||||
import dan200.computercraft.ComputerCraft;
|
import dan200.computercraft.ComputerCraft;
|
||||||
|
import dan200.computercraft.api.turtle.ITurtleAccess;
|
||||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||||
import dan200.computercraft.api.turtle.TurtleSide;
|
import dan200.computercraft.api.turtle.TurtleSide;
|
||||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||||
@@ -22,18 +23,13 @@ public final class TurtleItemFactory
|
|||||||
@Nonnull
|
@Nonnull
|
||||||
public static ItemStack create( ITurtleTile turtle )
|
public static ItemStack create( ITurtleTile turtle )
|
||||||
{
|
{
|
||||||
ITurtleUpgrade leftUpgrade = turtle.getAccess().getUpgrade( TurtleSide.Left );
|
ITurtleAccess access = turtle.getAccess();
|
||||||
ITurtleUpgrade rightUpgrade = turtle.getAccess().getUpgrade( TurtleSide.Right );
|
|
||||||
|
|
||||||
String label = turtle.getLabel();
|
return create(
|
||||||
if( label == null )
|
turtle.getComputerID(), turtle.getLabel(), turtle.getColour(), turtle.getFamily(),
|
||||||
{
|
access.getUpgrade( TurtleSide.Left ), access.getUpgrade( TurtleSide.Right ),
|
||||||
return create( -1, null, turtle.getColour(), turtle.getFamily(), leftUpgrade, rightUpgrade, 0, turtle.getOverlay() );
|
access.getFuelLevel(), turtle.getOverlay()
|
||||||
}
|
);
|
||||||
|
|
||||||
int id = turtle.getComputerID();
|
|
||||||
int fuelLevel = turtle.getAccess().getFuelLevel();
|
|
||||||
return create( id, label, turtle.getColour(), turtle.getFamily(), leftUpgrade, rightUpgrade, fuelLevel, turtle.getOverlay() );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
|
@@ -5,6 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
package dan200.computercraft.shared.util;
|
package dan200.computercraft.shared.util;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
@@ -12,11 +13,11 @@ public final class IoUtil
|
|||||||
{
|
{
|
||||||
private IoUtil() {}
|
private IoUtil() {}
|
||||||
|
|
||||||
public static void closeQuietly( Closeable closeable )
|
public static void closeQuietly( @Nullable Closeable closeable )
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
closeable.close();
|
if( closeable != null ) closeable.close();
|
||||||
}
|
}
|
||||||
catch( IOException ignored )
|
catch( IOException ignored )
|
||||||
{
|
{
|
||||||
|
@@ -6,6 +6,7 @@
|
|||||||
package dan200.computercraft.shared.util;
|
package dan200.computercraft.shared.util;
|
||||||
|
|
||||||
import net.minecraft.nbt.CompoundNBT;
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
|
import net.minecraft.network.PacketBuffer;
|
||||||
|
|
||||||
public class Palette
|
public class Palette
|
||||||
{
|
{
|
||||||
@@ -78,6 +79,22 @@ public class Palette
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void write( PacketBuffer buffer )
|
||||||
|
{
|
||||||
|
for( double[] colour : colours )
|
||||||
|
{
|
||||||
|
for( double channel : colour ) buffer.writeByte( (int) (channel * 0xFF) & 0xFF );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void read( PacketBuffer buffer )
|
||||||
|
{
|
||||||
|
for( double[] colour : colours )
|
||||||
|
{
|
||||||
|
for( int i = 0; i < colour.length; i++ ) colour[i] = (buffer.readByte() & 0xFF) / 255.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public CompoundNBT writeToNBT( CompoundNBT nbt )
|
public CompoundNBT writeToNBT( CompoundNBT nbt )
|
||||||
{
|
{
|
||||||
int[] rgb8 = new int[colours.length];
|
int[] rgb8 = new int[colours.length];
|
||||||
|
@@ -6,4 +6,3 @@
|
|||||||
"modem=true,peripheral=true": { "model": "computercraft:block/wired_modem_full_on_peripheral" }
|
"modem=true,peripheral=true": { "model": "computercraft:block/wired_modem_full_on_peripheral" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
55
src/main/resources/assets/computercraft/lang/da_dk.json
Normal file
55
src/main/resources/assets/computercraft/lang/da_dk.json
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
{
|
||||||
|
|
||||||
|
"block.computercraft.computer_normal": "Computer",
|
||||||
|
"block.computercraft.computer_advanced": "Avanceret Computer",
|
||||||
|
"block.computercraft.computer_command": "Kommandocomputer",
|
||||||
|
|
||||||
|
"block.computercraft.disk_drive": "Diskdrev",
|
||||||
|
"block.computercraft.printer": "Printer",
|
||||||
|
"block.computercraft.speaker": "Højttaler",
|
||||||
|
|
||||||
|
"block.computercraft.monitor_normal": "Skærm",
|
||||||
|
"block.computercraft.monitor_advanced": "Avanceret Skærm",
|
||||||
|
|
||||||
|
"block.computercraft.wireless_modem_normal": "Trådløst Modem",
|
||||||
|
"block.computercraft.wireless_modem_advanced": "Endermodem",
|
||||||
|
|
||||||
|
"block.computercraft.wired_modem": "Kablet Modem",
|
||||||
|
"block.computercraft.cable": "Netværkskabel",
|
||||||
|
|
||||||
|
"block.computercraft.turtle_normal": "Turtle",
|
||||||
|
"block.computercraft.turtle_normal.upgraded": "%s Turtle",
|
||||||
|
"block.computercraft.turtle_normal.upgraded_twice": "%s %s Turtle",
|
||||||
|
|
||||||
|
"block.computercraft.turtle_advanced": "Avanceret Turtle",
|
||||||
|
"block.computercraft.turtle_advanced.upgraded": "Avanceret %s Turtle",
|
||||||
|
"block.computercraft.turtle_advanced.upgraded_twice": "Avanceret %s %s Turtle",
|
||||||
|
|
||||||
|
"item.computercraft.disk": "Floppydisk",
|
||||||
|
"item.computercraft.treasure_disk": "Floppydisk",
|
||||||
|
"item.computercraft.printed_page": "Printet Side",
|
||||||
|
"item.computercraft.printed_pages": "Printede Sider",
|
||||||
|
"item.computercraft.printed_book": "Printet Bog",
|
||||||
|
|
||||||
|
"item.computercraft.pocket_computer_normal": "Lommecomputer",
|
||||||
|
"item.computercraft.pocket_computer_normal.upgraded": "%s Lommecomputer",
|
||||||
|
"item.computercraft.pocket_computer_advanced": "Avanceret Lommecomputer",
|
||||||
|
"item.computercraft.pocket_computer_advanced.upgraded": "Avanceret %s Lommecomputer",
|
||||||
|
|
||||||
|
"upgrade.minecraft.diamond_sword.adjective": "Kæmpende",
|
||||||
|
"upgrade.minecraft.diamond_shovel.adjective": "Gravende",
|
||||||
|
"upgrade.minecraft.diamond_pickaxe.adjective": "Brydende",
|
||||||
|
"upgrade.minecraft.diamond_axe.adjective": "Fældende",
|
||||||
|
"upgrade.minecraft.diamond_hoe.adjective": "Dyrkende",
|
||||||
|
"upgrade.minecraft.crafting_table.adjective": "Fremstillende",
|
||||||
|
"upgrade.computercraft.wireless_modem_normal.adjective": "Trådløs",
|
||||||
|
"upgrade.computercraft.wireless_modem_advanced.adjective": "Endertrådløs",
|
||||||
|
"upgrade.computercraft.speaker.adjective": "Larmende",
|
||||||
|
|
||||||
|
"chat.computercraft.wired_modem.peripheral_connected": "Perifer enhed \"%s\" koblet til netværk",
|
||||||
|
"chat.computercraft.wired_modem.peripheral_disconnected": "Perifer enhed \"%s\" koblet fra netværk",
|
||||||
|
|
||||||
|
"gui.computercraft.tooltip.copy": "Kopier til udklipsholder",
|
||||||
|
"gui.computercraft.tooltip.computer_id": "Computer-ID: %s",
|
||||||
|
"gui.computercraft.tooltip.disk_id": "Disk-ID: %s"
|
||||||
|
}
|
@@ -1,48 +0,0 @@
|
|||||||
tile.computercraft:computer.name=Computer
|
|
||||||
tile.computercraft:advanced_computer.name=Avanceret Computer
|
|
||||||
tile.computercraft:drive.name=Diskdrev
|
|
||||||
tile.computercraft:printer.name=Printer
|
|
||||||
tile.computercraft:monitor.name=Skærm
|
|
||||||
tile.computercraft:advanced_monitor.name=Avanceret Skærm
|
|
||||||
tile.computercraft:wireless_modem.name=Trådløst Modem
|
|
||||||
tile.computercraft:wired_modem.name=Kablet Modem
|
|
||||||
tile.computercraft:cable.name=Netværkskabel
|
|
||||||
tile.computercraft:command_computer.name=Kommandocomputer
|
|
||||||
tile.computercraft:advanced_modem.name=Endermodem
|
|
||||||
tile.computercraft:speaker.name=Højttaler
|
|
||||||
|
|
||||||
tile.computercraft:turtle.name=Turtle
|
|
||||||
tile.computercraft:turtle.upgraded.name=%s Turtle
|
|
||||||
tile.computercraft:turtle.upgraded_twice.name=%s %s Turtle
|
|
||||||
tile.computercraft:advanced_turtle.name=Avanceret Turtle
|
|
||||||
tile.computercraft:advanced_turtle.upgraded.name=Avanceret %s Turtle
|
|
||||||
tile.computercraft:advanced_turtle.upgraded_twice.name=Avanceret %s %s Turtle
|
|
||||||
|
|
||||||
item.computercraft:disk.name=Floppydisk
|
|
||||||
item.computercraft:treasure_disk.name=Floppydisk
|
|
||||||
item.computercraft:page.name=Printet Side
|
|
||||||
item.computercraft:pages.name=Printede Sider
|
|
||||||
item.computercraft:book.name=Printet Bog
|
|
||||||
|
|
||||||
item.computercraft:pocket_computer.name=Lommecomputer
|
|
||||||
item.computercraft:pocket_computer.upgraded.name=%s Lommecomputer
|
|
||||||
item.computercraft:advanced_pocket_computer.name=Avanceret Lommecomputer
|
|
||||||
item.computercraft:advanced_pocket_computer.upgraded.name=Avanceret %s Lommecomputer
|
|
||||||
|
|
||||||
upgrade.minecraft:diamond_sword.adjective=Kæmpende
|
|
||||||
upgrade.minecraft:diamond_shovel.adjective=Gravende
|
|
||||||
upgrade.minecraft:diamond_pickaxe.adjective=Brydende
|
|
||||||
upgrade.minecraft:diamond_axe.adjective=Fældende
|
|
||||||
upgrade.minecraft:diamond_hoe.adjective=Dyrkende
|
|
||||||
upgrade.computercraft:wireless_modem.adjective=Trådløs
|
|
||||||
upgrade.minecraft:crafting_table.adjective=Fremstillende
|
|
||||||
upgrade.computercraft:advanced_modem.adjective=Endertrådløs
|
|
||||||
upgrade.computercraft:speaker.adjective=Larmende
|
|
||||||
|
|
||||||
chat.computercraft.wired_modem.peripheral_connected=Perifer enhed "%s" koblet til netværk
|
|
||||||
chat.computercraft.wired_modem.peripheral_disconnected=Perifer enhed "%s" koblet fra netværk
|
|
||||||
|
|
||||||
# Misc tooltips
|
|
||||||
gui.computercraft.tooltip.copy=Kopier til udklipsholder
|
|
||||||
gui.computercraft.tooltip.computer_id=(Computer-ID: %s)
|
|
||||||
gui.computercraft.tooltip.disk_id=(Disk-ID: %s)
|
|
@@ -141,8 +141,8 @@
|
|||||||
"tracking_field.computercraft.coroutines_dead.name": "Koroutinen gelöscht",
|
"tracking_field.computercraft.coroutines_dead.name": "Koroutinen gelöscht",
|
||||||
|
|
||||||
"gui.computercraft.tooltip.copy": "In die Zwischenablage kopieren",
|
"gui.computercraft.tooltip.copy": "In die Zwischenablage kopieren",
|
||||||
"gui.computercraft.tooltip.computer_id": "(Computer ID: %s)",
|
"gui.computercraft.tooltip.computer_id": "Computer ID: %s",
|
||||||
"gui.computercraft.tooltip.disk_id": "(Disketten ID: %s)",
|
"gui.computercraft.tooltip.disk_id": "Disketten ID: %s",
|
||||||
|
|
||||||
"gui.computercraft.config.computer_space_limit": "Speicherplatz von Computern (bytes)",
|
"gui.computercraft.config.computer_space_limit": "Speicherplatz von Computern (bytes)",
|
||||||
"gui.computercraft.config.floppy_space_limit": "Speicherplatz von Disketten (bytes)",
|
"gui.computercraft.config.floppy_space_limit": "Speicherplatz von Disketten (bytes)",
|
||||||
|
@@ -143,8 +143,8 @@
|
|||||||
"tracking_field.computercraft.coroutines_dead.name": "Coroutines disposed",
|
"tracking_field.computercraft.coroutines_dead.name": "Coroutines disposed",
|
||||||
|
|
||||||
"gui.computercraft.tooltip.copy": "Copy to clipboard",
|
"gui.computercraft.tooltip.copy": "Copy to clipboard",
|
||||||
"gui.computercraft.tooltip.computer_id": "(Computer ID: %s)",
|
"gui.computercraft.tooltip.computer_id": "Computer ID: %s",
|
||||||
"gui.computercraft.tooltip.disk_id": "(Disk ID: %s)",
|
"gui.computercraft.tooltip.disk_id": "Disk ID: %s",
|
||||||
|
|
||||||
"gui.computercraft.config.computer_space_limit": "Computer space limit (bytes)",
|
"gui.computercraft.config.computer_space_limit": "Computer space limit (bytes)",
|
||||||
"gui.computercraft.config.floppy_space_limit": "Floppy Disk space limit (bytes)",
|
"gui.computercraft.config.floppy_space_limit": "Floppy Disk space limit (bytes)",
|
||||||
|
185
src/main/resources/assets/computercraft/lang/ko_kr.json
Normal file
185
src/main/resources/assets/computercraft/lang/ko_kr.json
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
{
|
||||||
|
"itemGroup.computercraft": "컴퓨터크래프트",
|
||||||
|
|
||||||
|
"block.computercraft.computer_normal": "컴퓨터",
|
||||||
|
"block.computercraft.computer_advanced": "고급 컴퓨터",
|
||||||
|
"block.computercraft.computer_command": "명령 컴퓨터",
|
||||||
|
|
||||||
|
"block.computercraft.disk_drive": "디스크 드라이브",
|
||||||
|
"block.computercraft.printer": "프린터",
|
||||||
|
"block.computercraft.speaker": "스피커",
|
||||||
|
|
||||||
|
"block.computercraft.monitor_normal": "모니터",
|
||||||
|
"block.computercraft.monitor_advanced": "고급 모니터",
|
||||||
|
|
||||||
|
"block.computercraft.wireless_modem_normal": "무선 모뎀",
|
||||||
|
"block.computercraft.wireless_modem_advanced": "엔더 모뎀",
|
||||||
|
|
||||||
|
"block.computercraft.wired_modem": "유선 모뎀",
|
||||||
|
"block.computercraft.cable": "네트워크 케이블",
|
||||||
|
|
||||||
|
"block.computercraft.turtle_normal": "터틀",
|
||||||
|
"block.computercraft.turtle_normal.upgraded": "%s 터틀",
|
||||||
|
"block.computercraft.turtle_normal.upgraded_twice": "%s %s 터틀",
|
||||||
|
|
||||||
|
"block.computercraft.turtle_advanced": "고급 터틀",
|
||||||
|
"block.computercraft.turtle_advanced.upgraded": "고급 %s 터틀",
|
||||||
|
"block.computercraft.turtle_advanced.upgraded_twice": "고급 %s %s 터틀",
|
||||||
|
|
||||||
|
"item.computercraft.disk": "플로피 디스크",
|
||||||
|
"item.computercraft.treasure_disk": "플로피 디스크",
|
||||||
|
"item.computercraft.printed_page": "인쇄된 페이지",
|
||||||
|
"item.computercraft.printed_pages": "인쇄된 페이지 모음",
|
||||||
|
"item.computercraft.printed_book": "인쇄된 책",
|
||||||
|
|
||||||
|
"item.computercraft.pocket_computer_normal": "포켓 컴퓨터",
|
||||||
|
"item.computercraft.pocket_computer_normal.upgraded": "%s 포켓 컴퓨터",
|
||||||
|
"item.computercraft.pocket_computer_advanced": "고급 포켓 컴퓨터",
|
||||||
|
"item.computercraft.pocket_computer_advanced.upgraded": "고급 %s 포켓 컴퓨터",
|
||||||
|
|
||||||
|
"upgrade.minecraft.diamond_sword.adjective": "난투",
|
||||||
|
"upgrade.minecraft.diamond_shovel.adjective": "굴착",
|
||||||
|
"upgrade.minecraft.diamond_pickaxe.adjective": "채굴",
|
||||||
|
"upgrade.minecraft.diamond_axe.adjective": "벌목",
|
||||||
|
"upgrade.minecraft.diamond_hoe.adjective": "농업",
|
||||||
|
"upgrade.minecraft.crafting_table.adjective": "조합",
|
||||||
|
"upgrade.computercraft.wireless_modem_normal.adjective": "무선",
|
||||||
|
"upgrade.computercraft.wireless_modem_advanced.adjective": "엔더",
|
||||||
|
"upgrade.computercraft.speaker.adjective": "소음",
|
||||||
|
|
||||||
|
"chat.computercraft.wired_modem.peripheral_connected": "주변 \"%s\"이 네트워크에 연결되었습니다.",
|
||||||
|
"chat.computercraft.wired_modem.peripheral_disconnected": "주변 \"%s\"이 네트워크로부터 분리되었습니다.",
|
||||||
|
|
||||||
|
"commands.computercraft.synopsis": "컴퓨터를 제어하기 위한 다양한 명령어",
|
||||||
|
"commands.computercraft.desc": "/computercraft 명령어는 컴퓨터를 제어하고 상호작용하기 위한 다양한 디버깅 및 관리자 도구를 제공합니다.",
|
||||||
|
|
||||||
|
"commands.computercraft.help.synopsis": "특정 명령어에 대한 도움말을 제공하기",
|
||||||
|
"commands.computercraft.help.desc": "",
|
||||||
|
"commands.computercraft.help.no_children": "%s에는 하위 명령어가 없습니다.",
|
||||||
|
"commands.computercraft.help.no_command": "'%s'라는 명령어가 없습니다.",
|
||||||
|
|
||||||
|
"commands.computercraft.dump.synopsis": "컴퓨터의 상태를 보여주기",
|
||||||
|
"commands.computercraft.dump.desc": "모든 시스템의 상태 또는 한 시스템에 대한 특정 정보를 표시합니다. 컴퓨터의 인스턴스 ID(예: 123)나 컴퓨터 ID(예: #123) 또는 라벨(예: \"@My Computer\")을 지정할 수 있습니다.",
|
||||||
|
"commands.computercraft.dump.action": "이 컴퓨터에 대한 추가 정보를 봅니다.",
|
||||||
|
|
||||||
|
"commands.computercraft.shutdown.synopsis": "시스템을 원격으로 종료하기",
|
||||||
|
"commands.computercraft.shutdown.desc": "나열된 시스템 또는 지정된 시스템이 없는 경우 모두 종료합니다. 컴퓨터의 인스턴스 ID(예: 123)나 컴퓨터 ID(예: #123) 또는 라벨(예: \"@My Computer\")을 지정할 수 있습니다.",
|
||||||
|
"commands.computercraft.shutdown.done": "%s/%s 컴퓨터 시스템 종료",
|
||||||
|
|
||||||
|
"commands.computercraft.turn_on.synopsis": "시스템을 원격으로 실행하기",
|
||||||
|
"commands.computercraft.turn_on.desc": "나열된 컴퓨터를 실행합니다. 컴퓨터의 인스턴스 ID(예: 123)나 컴퓨터 ID(예: #123) 또는 라벨(예: \"@My Computer\")을 지정할 수 있습니다.",
|
||||||
|
"commands.computercraft.turn_on.done": "%s/%s 컴퓨터 시스템 실행",
|
||||||
|
|
||||||
|
"commands.computercraft.tp.synopsis": "특정 컴퓨터로 순간이동하기",
|
||||||
|
"commands.computercraft.tp.desc": "컴퓨터의 위치로 순간이동합니다. 컴퓨터의 인스턴스 ID(예: 123) 또는 컴퓨터 ID(예: #123)를 지정할 수 있습니다.",
|
||||||
|
"commands.computercraft.tp.action": "이 컴퓨터로 순간이동하기",
|
||||||
|
"commands.computercraft.tp.not_there": "월드에서 컴퓨터를 위치시킬 수 없습니다.",
|
||||||
|
|
||||||
|
"commands.computercraft.view.synopsis": "컴퓨터의 터미널을 보기",
|
||||||
|
"commands.computercraft.view.desc": "컴퓨터의 원격 제어를 허용하는 컴퓨터의 터미널을 엽니다. 이것은 터틀의 인벤토리에 대한 접근을 제공하지 않습니다. 컴퓨터의 인스턴스 ID(예: 123) 또는 컴퓨터 ID(예: #123)를 지정할 수 있습니다.",
|
||||||
|
"commands.computercraft.view.action": "이 컴퓨터를 봅니다.",
|
||||||
|
"commands.computercraft.view.not_player": "비플레이어한테 터미널을 열 수 없습니다.",
|
||||||
|
|
||||||
|
"commands.computercraft.track.synopsis": "컴퓨터의 실행 시간을 추적하기",
|
||||||
|
"commands.computercraft.track.desc": "컴퓨터가 실행되는 기간과 처리되는 이벤트 수를 추적합니다. 이는 /forge 트랙과 유사한 방법으로 정보를 제공하며 지연 로그에 유용할 수 있습니다.",
|
||||||
|
|
||||||
|
"commands.computercraft.track.start.synopsis": "모든 컴퓨터의 추적을 시작하기",
|
||||||
|
"commands.computercraft.track.start.desc": "모든 컴퓨터의 이벤트 및 실행 시간 추적을 시작합니다. 이는 이전 실행의 결과를 폐기할 것입니다.",
|
||||||
|
"commands.computercraft.track.start.stop": "%s을(를) 실행하여 추적을 중지하고 결과를 확인합니다.",
|
||||||
|
|
||||||
|
"commands.computercraft.track.stop.synopsis": "모든 컴퓨터의 추적을 중지하기",
|
||||||
|
"commands.computercraft.track.stop.desc": "모든 컴퓨터의 이벤트 및 실행 시간 추적을 중지합니다.",
|
||||||
|
"commands.computercraft.track.stop.action": "추적을 중지하려면 클릭하세요.",
|
||||||
|
"commands.computercraft.track.stop.not_enabled": "현재 추적하는 컴퓨터가 없습니다.",
|
||||||
|
|
||||||
|
"commands.computercraft.track.dump.synopsis": "최신 추적 결과를 덤프하기",
|
||||||
|
"commands.computercraft.track.dump.desc": "최신 컴퓨터 추적의 결과를 덤프합니다.",
|
||||||
|
"commands.computercraft.track.dump.no_timings": "사용가능한 시간이 없습니다.",
|
||||||
|
"commands.computercraft.track.dump.computer": "컴퓨터",
|
||||||
|
|
||||||
|
"commands.computercraft.reload.synopsis": "컴퓨터크래프트 구성파일을 리로드하기",
|
||||||
|
"commands.computercraft.reload.desc": "컴퓨터크래프트 구성파일을 리로드합니다.",
|
||||||
|
"commands.computercraft.reload.done": "리로드된 구성",
|
||||||
|
|
||||||
|
"commands.computercraft.queue.synopsis": "computer_command 이벤트를 명령 컴퓨터에 보내기",
|
||||||
|
"commands.computercraft.queue.desc": "computer_command 이벤트를 명령 컴퓨터로 전송하여 추가 인수를 전달합니다. 이는 대부분 지도 제작자를 위해 설계되었으며, 보다 컴퓨터 친화적인 버전의 /trigger 역할을 합니다. 어떤 플레이어든 명령을 실행할 수 있으며, 이는 텍스트 구성 요소의 클릭 이벤트를 통해 수행될 가능성이 가장 높습니다.",
|
||||||
|
|
||||||
|
"commands.computercraft.generic.no_position": "<no pos>",
|
||||||
|
"commands.computercraft.generic.position": "%s, %s, %s",
|
||||||
|
"commands.computercraft.generic.yes": "Y",
|
||||||
|
"commands.computercraft.generic.no": "N",
|
||||||
|
"commands.computercraft.generic.exception": "처리되지 않은 예외 (%s)",
|
||||||
|
"commands.computercraft.generic.additional_rows": "%d개의 추가 행...",
|
||||||
|
|
||||||
|
"argument.computercraft.computer.no_matching": "'%s'와 일치하는 컴퓨터가 없습니다.",
|
||||||
|
"argument.computercraft.computer.many_matching": "'%s'와 일치하는 여러 컴퓨터 (인스턴스 %s)",
|
||||||
|
|
||||||
|
"tracking_field.computercraft.tasks.name": "작업",
|
||||||
|
"tracking_field.computercraft.total.name": "전체 시간",
|
||||||
|
"tracking_field.computercraft.average.name": "평균 시간",
|
||||||
|
"tracking_field.computercraft.max.name": "최대 시간",
|
||||||
|
|
||||||
|
"tracking_field.computercraft.server_count.name": "서버 작업 수",
|
||||||
|
"tracking_field.computercraft.server_time.name": "서버 작업 시간",
|
||||||
|
|
||||||
|
"tracking_field.computercraft.peripheral.name": "주변 호출",
|
||||||
|
"tracking_field.computercraft.fs.name": "파일시스템 작업",
|
||||||
|
"tracking_field.computercraft.turtle.name": "터틀 작업",
|
||||||
|
|
||||||
|
"tracking_field.computercraft.http.name": "HTTP 요청",
|
||||||
|
"tracking_field.computercraft.http_upload.name": "HTTP 업로드",
|
||||||
|
"tracking_field.computercraft.http_download.name": "HTTT 다운로드",
|
||||||
|
|
||||||
|
"tracking_field.computercraft.websocket_incoming.name": "웹소켓 수신",
|
||||||
|
"tracking_field.computercraft.websocket_outgoing.name": "웹소켓 송신",
|
||||||
|
|
||||||
|
"tracking_field.computercraft.coroutines_created.name": "코루틴 생성됨",
|
||||||
|
"tracking_field.computercraft.coroutines_dead.name": "코루틴 처리됨",
|
||||||
|
|
||||||
|
"gui.computercraft.tooltip.copy": "클립보드에 복사",
|
||||||
|
"gui.computercraft.tooltip.computer_id": "컴퓨터 ID: %s",
|
||||||
|
"gui.computercraft.tooltip.disk_id": "디스크 ID: %s",
|
||||||
|
|
||||||
|
"gui.computercraft.config.computer_space_limit": "컴퓨터 공간 제한 (바이트)",
|
||||||
|
"gui.computercraft.config.floppy_space_limit": "플로피 디스크 공간 제한 (바이트)",
|
||||||
|
"gui.computercraft.config.maximum_open_files": "컴퓨터당 최대 파일 열기",
|
||||||
|
"gui.computercraft.config.disable_lua51_features": "Lua 5.1 기능 미사용",
|
||||||
|
"gui.computercraft.config.default_computer_settings": "기본 컴퓨터 설정",
|
||||||
|
"gui.computercraft.config.debug_enabled": "디버그 라이브러리 사용",
|
||||||
|
"gui.computercraft.config.log_computer_errors": "컴퓨터 오류 로그",
|
||||||
|
|
||||||
|
"gui.computercraft.config.execution": "실행",
|
||||||
|
"gui.computercraft.config.execution.computer_threads": "컴퓨터 쓰레드",
|
||||||
|
"gui.computercraft.config.execution.max_main_global_time": "전역 시간 당 서버 제한",
|
||||||
|
"gui.computercraft.config.execution.max_main_computer_time": "컴퓨터 시간 당 서버 제한",
|
||||||
|
|
||||||
|
"gui.computercraft.config.http": "HTTP",
|
||||||
|
"gui.computercraft.config.http.enabled": "HTTP API 사용하기",
|
||||||
|
"gui.computercraft.config.http.websocket_enabled": "웹소켓 사용",
|
||||||
|
|
||||||
|
"gui.computercraft.config.http.timeout": "타임아웃",
|
||||||
|
"gui.computercraft.config.http.max_requests": "최대 동시 요청 수",
|
||||||
|
"gui.computercraft.config.http.max_download": "최대 응답 크기",
|
||||||
|
"gui.computercraft.config.http.max_upload": "최대 요청 크기",
|
||||||
|
"gui.computercraft.config.http.max_websockets": "최대 동시 웹소켓 수",
|
||||||
|
"gui.computercraft.config.http.max_websocket_message": "최대 웹 포켓 메시지 크기",
|
||||||
|
|
||||||
|
"gui.computercraft.config.peripheral": "주변",
|
||||||
|
"gui.computercraft.config.peripheral.command_block_enabled": "명령 블록 주변 장치 사용",
|
||||||
|
"gui.computercraft.config.peripheral.modem_range": "모뎀 범위(기본값)",
|
||||||
|
"gui.computercraft.config.peripheral.modem_high_altitude_range": "모뎀 범위(높은 고도)",
|
||||||
|
"gui.computercraft.config.peripheral.modem_range_during_storm": "모뎀 범위(나쁜 날씨)",
|
||||||
|
"gui.computercraft.config.peripheral.modem_high_altitude_range_during_storm": "모뎀 범위(높은 고도, 나쁜 날씨)",
|
||||||
|
"gui.computercraft.config.peripheral.max_notes_per_tick": "컴퓨터가 한 번에 재생할 수 있는 최대 소리 수",
|
||||||
|
|
||||||
|
"gui.computercraft.config.turtle": "터틀",
|
||||||
|
"gui.computercraft.config.turtle.need_fuel": "연료 사용",
|
||||||
|
"gui.computercraft.config.turtle.normal_fuel_limit": "터틀 연료 제한",
|
||||||
|
"gui.computercraft.config.turtle.advanced_fuel_limit": "고급 터틀 연료 제한",
|
||||||
|
"gui.computercraft.config.turtle.obey_block_protection": "터틀이 블록 보호에 따르기",
|
||||||
|
"gui.computercraft.config.turtle.can_push": "터틀이 엔티티 밀어내기",
|
||||||
|
"gui.computercraft.config.turtle.disabled_actions": "터틀 액션 미사용",
|
||||||
|
|
||||||
|
"gui.computercraft.config.http.allowed_domains": "허용된 도메인",
|
||||||
|
"gui.computercraft.config.http.blocked_domains": "차단된 도메인"
|
||||||
|
}
|
@@ -1,195 +0,0 @@
|
|||||||
itemGroup.computercraft=컴퓨터크래프트
|
|
||||||
|
|
||||||
tile.computercraft:computer.name=컴퓨터
|
|
||||||
tile.computercraft:advanced_computer.name=고급 컴퓨터
|
|
||||||
tile.computercraft:drive.name=디스크 드라이브
|
|
||||||
tile.computercraft:printer.name=프린터
|
|
||||||
tile.computercraft:monitor.name=모니터
|
|
||||||
tile.computercraft:advanced_monitor.name=고급 모니터
|
|
||||||
tile.computercraft:wireless_modem.name=무선 모뎀
|
|
||||||
tile.computercraft:wired_modem.name=유선 모뎀
|
|
||||||
tile.computercraft:cable.name=네트워크 케이블
|
|
||||||
tile.computercraft:command_computer.name=명령 컴퓨터
|
|
||||||
tile.computercraft:advanced_modem.name=엔더 모뎀
|
|
||||||
tile.computercraft:speaker.name=스피커
|
|
||||||
|
|
||||||
tile.computercraft:turtle.name=터틀
|
|
||||||
tile.computercraft:turtle.upgraded.name=%s 터틀
|
|
||||||
tile.computercraft:turtle.upgraded_twice.name=%s %s 터틀
|
|
||||||
tile.computercraft:advanced_turtle.name=고급 터틀
|
|
||||||
tile.computercraft:advanced_turtle.upgraded.name=고급 %s 터틀
|
|
||||||
tile.computercraft:advanced_turtle.upgraded_twice.name=고급 %s %s 터틀
|
|
||||||
|
|
||||||
item.computercraft:disk.name=플로피 디스크
|
|
||||||
item.computercraft:treasure_disk.name=플로피 디스크
|
|
||||||
item.computercraft:page.name=인쇄된 페이지
|
|
||||||
item.computercraft:pages.name=인쇄된 페이지 모음
|
|
||||||
item.computercraft:book.name=인쇄된 책
|
|
||||||
|
|
||||||
item.computercraft:pocket_computer.name=포켓 컴퓨터
|
|
||||||
item.computercraft:pocket_computer.upgraded.name=%s 포켓 컴퓨터
|
|
||||||
item.computercraft:advanced_pocket_computer.name=고급 포켓 컴퓨터
|
|
||||||
item.computercraft:advanced_pocket_computer.upgraded.name=고급 %s 포켓 컴퓨터
|
|
||||||
|
|
||||||
upgrade.minecraft:diamond_sword.adjective=난투
|
|
||||||
upgrade.minecraft:diamond_shovel.adjective=굴착
|
|
||||||
upgrade.minecraft:diamond_pickaxe.adjective=채굴
|
|
||||||
upgrade.minecraft:diamond_axe.adjective=벌목
|
|
||||||
upgrade.minecraft:diamond_hoe.adjective=농업
|
|
||||||
upgrade.computercraft:wireless_modem.adjective=무선
|
|
||||||
upgrade.minecraft:crafting_table.adjective=조합
|
|
||||||
upgrade.computercraft:advanced_modem.adjective=엔더
|
|
||||||
upgrade.computercraft:speaker.adjective=소음
|
|
||||||
|
|
||||||
chat.computercraft.wired_modem.peripheral_connected=주변 "%s"이 네트워크에 연결되었습니다.
|
|
||||||
chat.computercraft.wired_modem.peripheral_disconnected=주변 "%s"이 네트워크로부터 분리되었습니다.
|
|
||||||
|
|
||||||
# Command descriptions, usage and any additional messages.
|
|
||||||
commands.computercraft.synopsis=컴퓨터를 제어하기 위한 다양한 명령어
|
|
||||||
commands.computercraft.desc=/computercraft 명령어는 컴퓨터를 제어하고 상호작용하기 위한 다양한 디버깅 및 관리자 도구를 제공합니다.
|
|
||||||
|
|
||||||
commands.computercraft.help.synopsis=특정 명령어에 대한 도움말을 제공하기
|
|
||||||
commands.computercraft.help.desc=
|
|
||||||
commands.computercraft.help.usage=[command]
|
|
||||||
commands.computercraft.help.no_children=%s에는 하위 명령어가 없습니다.
|
|
||||||
commands.computercraft.help.no_command='%s'라는 명령어가 없습니다.
|
|
||||||
|
|
||||||
commands.computercraft.dump.synopsis=컴퓨터의 상태를 보여주기
|
|
||||||
commands.computercraft.dump.desc=모든 시스템의 상태 또는 한 시스템에 대한 특정 정보를 표시합니다. 컴퓨터의 인스턴스 ID(예: 123)나 컴퓨터 ID(예: #123) 또는 라벨(예: "@My Computer")을 지정할 수 있습니다.
|
|
||||||
commands.computercraft.dump.usage=[id]
|
|
||||||
commands.computercraft.dump.action=이 컴퓨터에 대한 추가 정보를 봅니다.
|
|
||||||
|
|
||||||
commands.computercraft.shutdown.synopsis=시스템을 원격으로 종료하기
|
|
||||||
commands.computercraft.shutdown.desc=나열된 시스템 또는 지정된 시스템이 없는 경우 모두 종료합니다. 컴퓨터의 인스턴스 ID(예: 123)나 컴퓨터 ID(예: #123) 또는 라벨(예: "@My Computer")을 지정할 수 있습니다.
|
|
||||||
commands.computercraft.shutdown.usage=[ids...]
|
|
||||||
commands.computercraft.shutdown.done=%s/%s 컴퓨터 시스템 종료
|
|
||||||
|
|
||||||
commands.computercraft.turn_on.synopsis=시스템을 원격으로 실행하기
|
|
||||||
commands.computercraft.turn_on.desc=나열된 컴퓨터를 실행합니다. 컴퓨터의 인스턴스 ID(예: 123)나 컴퓨터 ID(예: #123) 또는 라벨(예: "@My Computer")을 지정할 수 있습니다.
|
|
||||||
commands.computercraft.turn_on.usage=[ids...]
|
|
||||||
commands.computercraft.turn_on.done=%s/%s 컴퓨터 시스템 실행
|
|
||||||
|
|
||||||
commands.computercraft.tp.synopsis=특정 컴퓨터로 순간이동하기
|
|
||||||
commands.computercraft.tp.desc=컴퓨터의 위치로 순간이동합니다. 컴퓨터의 인스턴스 ID(예: 123) 또는 컴퓨터 ID(예: #123)를 지정할 수 있습니다.
|
|
||||||
commands.computercraft.tp.usage=<id>
|
|
||||||
commands.computercraft.tp.action=이 컴퓨터로 순간이동하기
|
|
||||||
commands.computercraft.tp.not_entity=비플레이어한테 터미널을 열 수 없습니다.
|
|
||||||
commands.computercraft.tp.not_there=월드에서 컴퓨터를 위치시킬 수 없습니다.
|
|
||||||
|
|
||||||
commands.computercraft.view.synopsis=컴퓨터의 터미널을 보기
|
|
||||||
commands.computercraft.view.desc=컴퓨터의 원격 제어를 허용하는 컴퓨터의 터미널을 엽니다. 이것은 터틀의 인벤토리에 대한 접근을 제공하지 않습니다. 컴퓨터의 인스턴스 ID(예: 123) 또는 컴퓨터 ID(예: #123)를 지정할 수 있습니다.
|
|
||||||
commands.computercraft.view.usage=<id>
|
|
||||||
commands.computercraft.view.action=이 컴퓨터를 봅니다.
|
|
||||||
commands.computercraft.view.not_player=비플레이어한테 터미널을 열 수 없습니다.
|
|
||||||
|
|
||||||
commands.computercraft.track.synopsis=컴퓨터의 실행 시간을 추적하기
|
|
||||||
commands.computercraft.track.desc=컴퓨터가 실행되는 기간과 처리되는 이벤트 수를 추적합니다. 이는 /forge 트랙과 유사한 방법으로 정보를 제공하며 지연 로그에 유용할 수 있습니다.
|
|
||||||
|
|
||||||
commands.computercraft.track.start.synopsis=모든 컴퓨터의 추적을 시작하기
|
|
||||||
commands.computercraft.track.start.desc=모든 컴퓨터의 이벤트 및 실행 시간 추적을 시작합니다. 이는 이전 실행의 결과를 폐기할 것입니다.
|
|
||||||
commands.computercraft.track.start.usage=
|
|
||||||
commands.computercraft.track.start.stop=%s을(를) 실행하여 추적을 중지하고 결과를 확인합니다.
|
|
||||||
|
|
||||||
commands.computercraft.track.stop.synopsis=모든 컴퓨터의 추적을 중지하기
|
|
||||||
commands.computercraft.track.stop.desc=모든 컴퓨터의 이벤트 및 실행 시간 추적을 중지합니다.
|
|
||||||
commands.computercraft.track.stop.usage=
|
|
||||||
commands.computercraft.track.stop.action=추적을 중지하려면 클릭하세요.
|
|
||||||
commands.computercraft.track.stop.not_enabled=현재 추적하는 컴퓨터가 없습니다.
|
|
||||||
|
|
||||||
commands.computercraft.track.dump.synopsis=최신 추적 결과를 덤프하기
|
|
||||||
commands.computercraft.track.dump.desc=최신 컴퓨터 추적의 결과를 덤프합니다.
|
|
||||||
commands.computercraft.track.dump.usage=[kind]
|
|
||||||
commands.computercraft.track.dump.no_timings=사용가능한 시간이 없습니다.
|
|
||||||
commands.computercraft.track.dump.no_field=알 수 없는 필드 '%s'
|
|
||||||
commands.computercraft.track.dump.computer=컴퓨터
|
|
||||||
|
|
||||||
commands.computercraft.reload.synopsis=컴퓨터크래프트 구성파일을 리로드하기
|
|
||||||
commands.computercraft.reload.desc=컴퓨터크래프트 구성파일을 리로드합니다.
|
|
||||||
commands.computercraft.reload.usage=
|
|
||||||
commands.computercraft.reload.done=리로드된 구성
|
|
||||||
|
|
||||||
commands.computercraft.queue.synopsis=computer_command 이벤트를 명령 컴퓨터에 보내기
|
|
||||||
commands.computercraft.queue.desc=computer_command 이벤트를 명령 컴퓨터로 전송하여 추가 인수를 전달합니다. 이는 대부분 지도 제작자를 위해 설계되었으며, 보다 컴퓨터 친화적인 버전의 /trigger 역할을 합니다. 어떤 플레이어든 명령을 실행할 수 있으며, 이는 텍스트 구성 요소의 클릭 이벤트를 통해 수행될 가능성이 가장 높습니다.
|
|
||||||
commands.computercraft.queue.usage=<id> [args...]
|
|
||||||
|
|
||||||
commands.computercraft.generic.no_position=<no pos>
|
|
||||||
commands.computercraft.generic.position=%s, %s, %s
|
|
||||||
commands.computercraft.generic.yes=Y
|
|
||||||
commands.computercraft.generic.no=N
|
|
||||||
commands.computercraft.generic.exception=처리되지 않은 예외 (%s)
|
|
||||||
commands.computercraft.generic.additional_rows=%d개의 추가 행...
|
|
||||||
|
|
||||||
commands.computercraft.argument.no_matching='%s'와 일치하는 컴퓨터가 없습니다.
|
|
||||||
commands.computercraft.argument.many_matching='%s'와 일치하는 여러 컴퓨터 (인스턴스 %s)
|
|
||||||
commands.computercraft.argument.not_number='%s'는 숫자가 아닙니다.
|
|
||||||
|
|
||||||
# Names for the various tracking fields.
|
|
||||||
tracking_field.computercraft.tasks.name=작업
|
|
||||||
tracking_field.computercraft.total.name=전체 시간
|
|
||||||
tracking_field.computercraft.average.name=평균 시간
|
|
||||||
tracking_field.computercraft.max.name=최대 시간
|
|
||||||
|
|
||||||
tracking_field.computercraft.server_count.name=서버 작업 수
|
|
||||||
tracking_field.computercraft.server_time.name=서버 작업 시간
|
|
||||||
|
|
||||||
tracking_field.computercraft.peripheral.name=주변 호출
|
|
||||||
tracking_field.computercraft.fs.name=파일시스템 작업
|
|
||||||
tracking_field.computercraft.turtle.name=터틀 작업
|
|
||||||
|
|
||||||
tracking_field.computercraft.http.name=HTTP 요청
|
|
||||||
tracking_field.computercraft.http_upload.name=HTTP 업로드
|
|
||||||
tracking_field.computercraft.http_download.name=HTTT 다운로드
|
|
||||||
|
|
||||||
tracking_field.computercraft.websocket_incoming.name=웹소켓 수신
|
|
||||||
tracking_field.computercraft.websocket_outgoing.name=웹소켓 송신
|
|
||||||
|
|
||||||
tracking_field.computercraft.coroutines_created.name=코루틴 생성됨
|
|
||||||
tracking_field.computercraft.coroutines_dead.name=코루틴 처리됨
|
|
||||||
|
|
||||||
# Misc tooltips
|
|
||||||
gui.computercraft.tooltip.copy=클립보드에 복사
|
|
||||||
gui.computercraft.tooltip.computer_id=(컴퓨터 ID: %s)
|
|
||||||
gui.computercraft.tooltip.disk_id=(디스크 ID: %s)
|
|
||||||
|
|
||||||
# Config options
|
|
||||||
gui.computercraft:config.computer_space_limit=컴퓨터 공간 제한 (바이트)
|
|
||||||
gui.computercraft:config.floppy_space_limit=플로피 디스크 공간 제한 (바이트)
|
|
||||||
gui.computercraft:config.maximum_open_files=컴퓨터당 최대 파일 열기
|
|
||||||
gui.computercraft:config.disable_lua51_features=Lua 5.1 기능 미사용
|
|
||||||
gui.computercraft:config.default_computer_settings=기본 컴퓨터 설정
|
|
||||||
gui.computercraft:config.debug_enabled=디버그 라이브러리 사용
|
|
||||||
gui.computercraft:config.log_computer_errors=컴퓨터 오류 로그
|
|
||||||
|
|
||||||
gui.computercraft:config.execution=실행
|
|
||||||
gui.computercraft:config.execution.computer_threads=컴퓨터 쓰레드
|
|
||||||
gui.computercraft:config.execution.max_main_global_time=전역 시간 당 서버 제한
|
|
||||||
gui.computercraft:config.execution.max_main_computer_time=컴퓨터 시간 당 서버 제한
|
|
||||||
|
|
||||||
gui.computercraft:config.http=HTTP
|
|
||||||
gui.computercraft:config.http.enabled=HTTP API 사용하기
|
|
||||||
gui.computercraft:config.http.websocket_enabled=웹소켓 사용
|
|
||||||
gui.computercraft:config.http.allowed_domains=허용된 도메인
|
|
||||||
gui.computercraft:config.http.blocked_domains=차단된 도메인
|
|
||||||
|
|
||||||
gui.computercraft:config.http.timeout=타임아웃
|
|
||||||
gui.computercraft:config.http.max_requests=최대 동시 요청 수
|
|
||||||
gui.computercraft:config.http.max_download=최대 응답 크기
|
|
||||||
gui.computercraft:config.http.max_upload=최대 요청 크기
|
|
||||||
gui.computercraft:config.http.max_websockets=최대 동시 웹소켓 수
|
|
||||||
gui.computercraft:config.http.max_websocket_message=최대 웹 포켓 메시지 크기
|
|
||||||
|
|
||||||
gui.computercraft:config.peripheral=주변
|
|
||||||
gui.computercraft:config.peripheral.command_block_enabled=명령 블록 주변 장치 사용
|
|
||||||
gui.computercraft:config.peripheral.modem_range=모뎀 범위(기본값)
|
|
||||||
gui.computercraft:config.peripheral.modem_high_altitude_range=모뎀 범위(높은 고도)
|
|
||||||
gui.computercraft:config.peripheral.modem_range_during_storm=모뎀 범위(나쁜 날씨)
|
|
||||||
gui.computercraft:config.peripheral.modem_high_altitude_range_during_storm=모뎀 범위(높은 고도, 나쁜 날씨)
|
|
||||||
gui.computercraft:config.peripheral.max_notes_per_tick=컴퓨터가 한 번에 재생할 수 있는 최대 소리 수
|
|
||||||
|
|
||||||
gui.computercraft:config.turtle=터틀
|
|
||||||
gui.computercraft:config.turtle.need_fuel=연료 사용
|
|
||||||
gui.computercraft:config.turtle.normal_fuel_limit=터틀 연료 제한
|
|
||||||
gui.computercraft:config.turtle.advanced_fuel_limit=고급 터틀 연료 제한
|
|
||||||
gui.computercraft:config.turtle.obey_block_protection=터틀이 블록 보호에 따르기
|
|
||||||
gui.computercraft:config.turtle.can_push=터틀이 엔티티 밀어내기
|
|
||||||
gui.computercraft:config.turtle.disabled_actions=터틀 액션 미사용
|
|
@@ -143,8 +143,8 @@
|
|||||||
"tracking_field.computercraft.coroutines_dead.name": "协同处理",
|
"tracking_field.computercraft.coroutines_dead.name": "协同处理",
|
||||||
|
|
||||||
"gui.computercraft.tooltip.copy": "复制到剪贴板",
|
"gui.computercraft.tooltip.copy": "复制到剪贴板",
|
||||||
"gui.computercraft.tooltip.computer_id": "(计算机ID: %s)",
|
"gui.computercraft.tooltip.computer_id": "计算机ID: %s",
|
||||||
"gui.computercraft.tooltip.disk_id": "(磁盘ID: %s)",
|
"gui.computercraft.tooltip.disk_id": "磁盘ID: %s",
|
||||||
|
|
||||||
"gui.computercraft.config.computer_space_limit": "计算机空间限制(字节)",
|
"gui.computercraft.config.computer_space_limit": "计算机空间限制(字节)",
|
||||||
"gui.computercraft.config.floppy_space_limit": "软盘空间限制(字节)",
|
"gui.computercraft.config.floppy_space_limit": "软盘空间限制(字节)",
|
||||||
|
@@ -1,195 +0,0 @@
|
|||||||
itemGroup.computercraft=CC: Tweaked
|
|
||||||
|
|
||||||
tile.computercraft:computer.name=计算机
|
|
||||||
tile.computercraft:advanced_computer.name=高级计算机
|
|
||||||
tile.computercraft:drive.name=磁盘驱动器
|
|
||||||
tile.computercraft:printer.name=打印机
|
|
||||||
tile.computercraft:monitor.name=显示器
|
|
||||||
tile.computercraft:advanced_monitor.name=高级显示器
|
|
||||||
tile.computercraft:wireless_modem.name=无线调制解调器
|
|
||||||
tile.computercraft:wired_modem.name=有线调制解调器
|
|
||||||
tile.computercraft:cable.name=网络电缆
|
|
||||||
tile.computercraft:command_computer.name=命令电脑
|
|
||||||
tile.computercraft:advanced_modem.name=末影调制解调器
|
|
||||||
tile.computercraft:speaker.name=扬声器
|
|
||||||
|
|
||||||
tile.computercraft:turtle.name=海龟
|
|
||||||
tile.computercraft:turtle.upgraded.name=%s海龟
|
|
||||||
tile.computercraft:turtle.upgraded_twice.name=%s%s海龟
|
|
||||||
tile.computercraft:advanced_turtle.name=高级海龟
|
|
||||||
tile.computercraft:advanced_turtle.upgraded.name=高级%s海龟
|
|
||||||
tile.computercraft:advanced_turtle.upgraded_twice.name=高级%s%s海龟
|
|
||||||
|
|
||||||
item.computercraft:disk.name=软盘
|
|
||||||
item.computercraft:treasure_disk.name=软盘
|
|
||||||
item.computercraft:page.name=打印纸
|
|
||||||
item.computercraft:pages.name=打印纸
|
|
||||||
item.computercraft:book.name=打印书
|
|
||||||
|
|
||||||
item.computercraft:pocket_computer.name=手提计算机
|
|
||||||
item.computercraft:pocket_computer.upgraded.name=%s手提计算机
|
|
||||||
item.computercraft:advanced_pocket_computer.name=高级手提计算机
|
|
||||||
item.computercraft:advanced_pocket_computer.upgraded.name=高级%s手提计算机
|
|
||||||
|
|
||||||
upgrade.minecraft:diamond_sword.adjective=战斗
|
|
||||||
upgrade.minecraft:diamond_shovel.adjective=挖掘
|
|
||||||
upgrade.minecraft:diamond_pickaxe.adjective=采掘
|
|
||||||
upgrade.minecraft:diamond_axe.adjective=伐木
|
|
||||||
upgrade.minecraft:diamond_hoe.adjective=耕种
|
|
||||||
upgrade.computercraft:wireless_modem.adjective=无线
|
|
||||||
upgrade.minecraft:crafting_table.adjective=合成
|
|
||||||
upgrade.computercraft:advanced_modem.adjective=末影
|
|
||||||
upgrade.computercraft:speaker.adjective=喧闹
|
|
||||||
|
|
||||||
chat.computercraft.wired_modem.peripheral_connected=Peripheral "%s"连接到网络
|
|
||||||
chat.computercraft.wired_modem.peripheral_disconnected=Peripheral "%s"与网络断开连接
|
|
||||||
|
|
||||||
# Command descriptions, usage and any additional messages.
|
|
||||||
commands.computercraft.synopsis=各种控制计算机的命令.
|
|
||||||
commands.computercraft.desc=/computercraft命令提供各种调试和管理工具,用于控制和与计算机交互.
|
|
||||||
|
|
||||||
commands.computercraft.help.synopsis=为特定的命令提供帮助
|
|
||||||
commands.computercraft.help.desc=
|
|
||||||
commands.computercraft.help.usage=[command]
|
|
||||||
commands.computercraft.help.no_children=%s没有子命令
|
|
||||||
commands.computercraft.help.no_command=没有这样的命令'%s'
|
|
||||||
|
|
||||||
commands.computercraft.dump.synopsis=显示计算机的状态.
|
|
||||||
commands.computercraft.dump.desc=显示所有计算机的状态或某台计算机的特定信息. 你可以指定计算机的实例id (例如. 123), 计算机id (例如. #123)或标签(例如. "@My Computer").
|
|
||||||
commands.computercraft.dump.usage=[id]
|
|
||||||
commands.computercraft.dump.action=查看有关此计算机的更多信息
|
|
||||||
|
|
||||||
commands.computercraft.shutdown.synopsis=远程关闭计算机.
|
|
||||||
commands.computercraft.shutdown.desc=关闭列出的计算机或全部计算机(如果未指定). 你可以指定计算机的实例id (例如. 123), 计算机id (例如. #123)或标签(例如. "@My Computer").
|
|
||||||
commands.computercraft.shutdown.usage=[ids...]
|
|
||||||
commands.computercraft.shutdown.done=关闭%s/%s计算机
|
|
||||||
|
|
||||||
commands.computercraft.turn_on.synopsis=远程打开计算机.
|
|
||||||
commands.computercraft.turn_on.desc=打开列出的计算机. 你可以指定计算机的实例id (例如. 123), 计算机id (例如. #123)或标签(例如. "@My Computer").
|
|
||||||
commands.computercraft.turn_on.usage=[ids...]
|
|
||||||
commands.computercraft.turn_on.done=打开%s/%s计算机
|
|
||||||
|
|
||||||
commands.computercraft.tp.synopsis=传送到特定的计算机.
|
|
||||||
commands.computercraft.tp.desc=传送到计算机的位置. 你可以指定计算机的实例id (例如. 123)或计算机id (例如. #123).
|
|
||||||
commands.computercraft.tp.usage=<id>
|
|
||||||
commands.computercraft.tp.action=传送到这台电脑
|
|
||||||
commands.computercraft.tp.not_entity=无法为非玩家打开终端
|
|
||||||
commands.computercraft.tp.not_there=无法在世界上定位电脑
|
|
||||||
|
|
||||||
commands.computercraft.view.synopsis=查看计算机的终端.
|
|
||||||
commands.computercraft.view.desc=打开计算机的终端,允许远程控制计算机. 这不提供对海龟库存的访问. 你可以指定计算机的实例id (例如. 123)或计算机id (例如. #123).
|
|
||||||
commands.computercraft.view.usage=<id>
|
|
||||||
commands.computercraft.view.action=查看此计算机
|
|
||||||
commands.computercraft.view.not_player=无法为非玩家打开终端
|
|
||||||
|
|
||||||
commands.computercraft.track.synopsis=跟踪计算机的执行时间.
|
|
||||||
commands.computercraft.track.desc=跟踪计算机执行的时间以及它们处理的事件数. 这以/forge track类似的方式呈现信息,可用于诊断滞后.
|
|
||||||
|
|
||||||
commands.computercraft.track.start.synopsis=开始跟踪所有计算机
|
|
||||||
commands.computercraft.track.start.desc=开始跟踪所有计算机的执行时间和事件计数. 这将放弃先前运行的结果.
|
|
||||||
commands.computercraft.track.start.usage=
|
|
||||||
commands.computercraft.track.start.stop=运行%s以停止跟踪并查看结果
|
|
||||||
|
|
||||||
commands.computercraft.track.stop.synopsis=停止跟踪所有计算机
|
|
||||||
commands.computercraft.track.stop.desc=停止跟踪所有计算机的事件和执行时间
|
|
||||||
commands.computercraft.track.stop.usage=
|
|
||||||
commands.computercraft.track.stop.action=点击停止跟踪
|
|
||||||
commands.computercraft.track.stop.not_enabled=目前没有跟踪计算机
|
|
||||||
|
|
||||||
commands.computercraft.track.dump.synopsis=输出最新的跟踪结果
|
|
||||||
commands.computercraft.track.dump.desc=输出计算机跟踪的最新结果.
|
|
||||||
commands.computercraft.track.dump.usage=[kind]
|
|
||||||
commands.computercraft.track.dump.no_timings=没有时间可用
|
|
||||||
commands.computercraft.track.dump.no_field=未知字节'%s'
|
|
||||||
commands.computercraft.track.dump.computer=计算器
|
|
||||||
|
|
||||||
commands.computercraft.reload.synopsis=重新加载ComputerCraft配置文件
|
|
||||||
commands.computercraft.reload.desc=重新加载ComputerCraft配置文件
|
|
||||||
commands.computercraft.reload.usage=
|
|
||||||
commands.computercraft.reload.done=重新加载配置
|
|
||||||
|
|
||||||
commands.computercraft.queue.synopsis=将computer_command事件发送到命令计算机
|
|
||||||
commands.computercraft.queue.desc=发送computer_command事件到命令计算机,并传递其他参数. 这主要是为地图制作者设计的, 作为/trigger更加计算机友好的版本. 任何玩家都可以运行命令, 这很可能是通过文本组件的点击事件完成的.
|
|
||||||
commands.computercraft.queue.usage=<id> [args...]
|
|
||||||
|
|
||||||
commands.computercraft.generic.no_position=<无位置>
|
|
||||||
commands.computercraft.generic.position=%s, %s, %s
|
|
||||||
commands.computercraft.generic.yes=Y
|
|
||||||
commands.computercraft.generic.no=N
|
|
||||||
commands.computercraft.generic.exception=未处理的异常(%s)
|
|
||||||
commands.computercraft.generic.additional_rows=%d额外的行…
|
|
||||||
|
|
||||||
commands.computercraft.argument.no_matching=没有计算机匹配'%s'
|
|
||||||
commands.computercraft.argument.many_matching=多台计算机匹配'%s' (实例%s)
|
|
||||||
commands.computercraft.argument.not_number='%s'不是一个数字
|
|
||||||
|
|
||||||
# Names for the various tracking fields.
|
|
||||||
tracking_field.computercraft.tasks.name=任务
|
|
||||||
tracking_field.computercraft.total.name=总计时间
|
|
||||||
tracking_field.computercraft.average.name=平均时间
|
|
||||||
tracking_field.computercraft.max.name=最大时间
|
|
||||||
|
|
||||||
tracking_field.computercraft.server_count.name=服务器任务计数
|
|
||||||
tracking_field.computercraft.server_time.name=服务器任务时间
|
|
||||||
|
|
||||||
tracking_field.computercraft.peripheral.name=外围设备呼叫
|
|
||||||
tracking_field.computercraft.fs.name=文件系统操作
|
|
||||||
tracking_field.computercraft.turtle.name=海龟行动
|
|
||||||
|
|
||||||
tracking_field.computercraft.http.name=HTTP需求
|
|
||||||
tracking_field.computercraft.http_upload.name=HTTP上传
|
|
||||||
tracking_field.computercraft.http_download.name=HTTP下载
|
|
||||||
|
|
||||||
tracking_field.computercraft.websocket_incoming.name=Websocket传入
|
|
||||||
tracking_field.computercraft.websocket_outgoing.name=Websocket传出
|
|
||||||
|
|
||||||
tracking_field.computercraft.coroutines_created.name=协同创建
|
|
||||||
tracking_field.computercraft.coroutines_dead.name=协同处理
|
|
||||||
|
|
||||||
# Misc tooltips
|
|
||||||
gui.computercraft.tooltip.copy=复制到剪贴板
|
|
||||||
gui.computercraft.tooltip.computer_id=(计算机ID: %s)
|
|
||||||
gui.computercraft.tooltip.disk_id=(磁盘ID: %s)
|
|
||||||
|
|
||||||
# Config options
|
|
||||||
gui.computercraft:config.computer_space_limit=计算机空间限制(字节)
|
|
||||||
gui.computercraft:config.floppy_space_limit=软盘空间限制(字节)
|
|
||||||
gui.computercraft:config.maximum_open_files=每台计算机打开的最大文件数
|
|
||||||
gui.computercraft:config.disable_lua51_features=禁用Lua 5.1功能
|
|
||||||
gui.computercraft:config.default_computer_settings=默认计算机设置
|
|
||||||
gui.computercraft:config.debug_enabled=启用debug库
|
|
||||||
gui.computercraft:config.log_computer_errors=记录计算机错误
|
|
||||||
|
|
||||||
gui.computercraft:config.execution=执行
|
|
||||||
gui.computercraft:config.execution.computer_threads=计算机线程数
|
|
||||||
gui.computercraft:config.execution.max_main_global_time=服务器全局tick时间限制
|
|
||||||
gui.computercraft:config.execution.max_main_computer_time=服务器计算机tick时间限制
|
|
||||||
|
|
||||||
gui.computercraft:config.http=HTTP
|
|
||||||
gui.computercraft:config.http.enabled=启用HTTP API
|
|
||||||
gui.computercraft:config.http.websocket_enabled=启用websockets
|
|
||||||
gui.computercraft:config.http.whitelist=HTTP白名单
|
|
||||||
gui.computercraft:config.http.blacklist=HTTP黑名单
|
|
||||||
|
|
||||||
gui.computercraft:config.http.timeout=Timeout
|
|
||||||
gui.computercraft:config.http.max_requests=最大并发请求数
|
|
||||||
gui.computercraft:config.http.max_download=最大响应数据大小
|
|
||||||
gui.computercraft:config.http.max_upload=最大请求数据大小
|
|
||||||
gui.computercraft:config.http.max_websockets=最大并发websockets数
|
|
||||||
gui.computercraft:config.http.max_websocket_message=最大websockets消息大小
|
|
||||||
|
|
||||||
gui.computercraft:config.peripheral=外围设备
|
|
||||||
gui.computercraft:config.peripheral.command_block_enabled=启用命令方块外设
|
|
||||||
gui.computercraft:config.peripheral.modem_range=调制解调器范围(默认)
|
|
||||||
gui.computercraft:config.peripheral.modem_high_altitude_range=调制解调器范围(高海拔)
|
|
||||||
gui.computercraft:config.peripheral.modem_range_during_storm=调制解调器范围(恶劣天气)
|
|
||||||
gui.computercraft:config.peripheral.modem_high_altitude_range_during_storm=调制解调器范围(高海拔, 恶劣天气)
|
|
||||||
gui.computercraft:config.peripheral.max_notes_per_tick=计算机一次可以播放的最大音符数量
|
|
||||||
|
|
||||||
gui.computercraft:config.turtle=海龟
|
|
||||||
gui.computercraft:config.turtle.need_fuel=启用燃料
|
|
||||||
gui.computercraft:config.turtle.normal_fuel_limit=海龟燃料限制
|
|
||||||
gui.computercraft:config.turtle.advanced_fuel_limit=高级海龟燃料限制
|
|
||||||
gui.computercraft:config.turtle.obey_block_protection=海龟服从方块保护
|
|
||||||
gui.computercraft:config.turtle.can_push=海龟可以推动实体
|
|
||||||
gui.computercraft:config.turtle.disabled_actions=禁用海龟动作
|
|
40
src/main/resources/assets/computercraft/shaders/monitor.frag
Normal file
40
src/main/resources/assets/computercraft/shaders/monitor.frag
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#version 140
|
||||||
|
|
||||||
|
#define FONT_WIDTH 6.0
|
||||||
|
#define FONT_HEIGHT 9.0
|
||||||
|
|
||||||
|
uniform sampler2D u_font;
|
||||||
|
uniform int u_width;
|
||||||
|
uniform int u_height;
|
||||||
|
uniform samplerBuffer u_tbo;
|
||||||
|
uniform vec3 u_palette[16];
|
||||||
|
|
||||||
|
in vec2 f_pos;
|
||||||
|
|
||||||
|
out vec4 colour;
|
||||||
|
|
||||||
|
vec2 texture_corner(int index) {
|
||||||
|
float x = 1.0 + float(index % 16) * (FONT_WIDTH + 2.0);
|
||||||
|
float y = 1.0 + float(index / 16) * (FONT_HEIGHT + 2.0);
|
||||||
|
return vec2(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec2 term_pos = vec2(f_pos.x / FONT_WIDTH, f_pos.y / FONT_HEIGHT);
|
||||||
|
vec2 corner = floor(term_pos);
|
||||||
|
|
||||||
|
ivec2 cell = ivec2(corner);
|
||||||
|
int index = 3 * (clamp(cell.x, 0, u_width - 1) + clamp(cell.y, 0, u_height - 1) * u_width);
|
||||||
|
|
||||||
|
// 1 if 0 <= x, y < width, height, 0 otherwise
|
||||||
|
vec2 outside = step(vec2(0.0, 0.0), vec2(cell)) * step(vec2(cell), vec2(float(u_width) - 1.0, float(u_height) - 1.0));
|
||||||
|
float mult = outside.x * outside.y;
|
||||||
|
|
||||||
|
int character = int(texelFetch(u_tbo, index).r * 255.0);
|
||||||
|
int fg = int(texelFetch(u_tbo, index + 1).r * 255.0);
|
||||||
|
int bg = int(texelFetch(u_tbo, index + 2).r * 255.0);
|
||||||
|
|
||||||
|
vec2 pos = (term_pos - corner) * vec2(FONT_WIDTH, FONT_HEIGHT);
|
||||||
|
vec4 img = texture(u_font, (texture_corner(character) + pos) / 256.0);
|
||||||
|
colour = vec4(mix(u_palette[bg], img.rgb * u_palette[fg], img.a * mult), 1.0);
|
||||||
|
}
|
10
src/main/resources/assets/computercraft/shaders/monitor.vert
Normal file
10
src/main/resources/assets/computercraft/shaders/monitor.vert
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#version 130
|
||||||
|
|
||||||
|
in vec3 v_pos;
|
||||||
|
|
||||||
|
out vec2 f_pos;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
gl_Position = gl_ModelViewProjectionMatrix * vec4(v_pos.x, v_pos.y, 0, 1);
|
||||||
|
f_pos = v_pos.xy;
|
||||||
|
}
|
@@ -797,6 +797,12 @@ function fs.complete(sPath, sLocation, bIncludeFiles, bIncludeDirs)
|
|||||||
return tEmpty
|
return tEmpty
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function fs.isDriveRoot(sPath)
|
||||||
|
expect(1, sPath, "string")
|
||||||
|
-- Force the root directory to be a mount.
|
||||||
|
return fs.getDir(sPath) == ".." or fs.getDrive(sPath) ~= fs.getDrive(fs.getDir(sPath))
|
||||||
|
end
|
||||||
|
|
||||||
-- Load APIs
|
-- Load APIs
|
||||||
local bAPIError = false
|
local bAPIError = false
|
||||||
local tApis = fs.list("rom/apis")
|
local tApis = fs.list("rom/apis")
|
||||||
@@ -932,6 +938,23 @@ settings.define("motd.path", {
|
|||||||
description = [[The path to load random messages from. Should be a colon (":") separated string of file paths.]],
|
description = [[The path to load random messages from. Should be a colon (":") separated string of file paths.]],
|
||||||
type = "string",
|
type = "string",
|
||||||
})
|
})
|
||||||
|
|
||||||
|
settings.define("lua.warn_against_use_of_local", {
|
||||||
|
default = true,
|
||||||
|
description = [[Print a message when input in the Lua REPL starts with the word 'local'. Local variables defined in the Lua REPL are be inaccessable on the next input.]],
|
||||||
|
type = "boolean",
|
||||||
|
})
|
||||||
|
settings.define("lua.function_args", {
|
||||||
|
default = true,
|
||||||
|
description = "Show function arguments when printing functions.",
|
||||||
|
type = "boolean",
|
||||||
|
})
|
||||||
|
settings.define("lua.function_source", {
|
||||||
|
default = false,
|
||||||
|
description = "Show where a function was defined when printing functions.",
|
||||||
|
type = "boolean",
|
||||||
|
})
|
||||||
|
|
||||||
if term.isColour() then
|
if term.isColour() then
|
||||||
settings.define("bios.use_multishell", {
|
settings.define("bios.use_multishell", {
|
||||||
default = true,
|
default = true,
|
||||||
|
@@ -12,6 +12,9 @@
|
|||||||
-- [mc]: https://minecraft.gamepedia.com/Commands
|
-- [mc]: https://minecraft.gamepedia.com/Commands
|
||||||
--
|
--
|
||||||
-- @module commands
|
-- @module commands
|
||||||
|
-- @usage Set the block above this computer to stone:
|
||||||
|
--
|
||||||
|
-- commands.setblock("~", "~1", "~", "minecraft:stone")
|
||||||
|
|
||||||
if not commands then
|
if not commands then
|
||||||
error("Cannot load command API on normal computer", 2)
|
error("Cannot load command API on normal computer", 2)
|
||||||
@@ -97,4 +100,13 @@ for _, sCommandName in ipairs(native.list()) do
|
|||||||
tAsync[sCommandName] = mk_command({ sCommandName }, bJSONIsNBT, native.execAsync)
|
tAsync[sCommandName] = mk_command({ sCommandName }, bJSONIsNBT, native.execAsync)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- A table containing asynchronous wrappers for all commands.
|
||||||
|
--
|
||||||
|
-- As with @{commands.execAsync}, this returns the "task id" of the enqueued
|
||||||
|
-- command.
|
||||||
|
-- @see execAsync
|
||||||
|
-- @usage Asynchronously sets the block above the computer to stone.
|
||||||
|
--
|
||||||
|
-- commands.async.setblock("~", "~1", "~", "minecraft:stone")
|
||||||
env.async = tAsync
|
env.async = tAsync
|
||||||
|
@@ -75,7 +75,10 @@ handleMetatable = {
|
|||||||
if not handle.read then return nil, "file is not readable" end
|
if not handle.read then return nil, "file is not readable" end
|
||||||
|
|
||||||
local args = table.pack(...)
|
local args = table.pack(...)
|
||||||
return function() return checkResult(self, self:read(table.unpack(args, 1, args.n))) end
|
return function()
|
||||||
|
if self._closed then error("file is already closed", 2) end
|
||||||
|
return checkResult(self, self:read(table.unpack(args, 1, args.n)))
|
||||||
|
end
|
||||||
end,
|
end,
|
||||||
|
|
||||||
read = function(self, ...)
|
read = function(self, ...)
|
||||||
@@ -259,12 +262,13 @@ end
|
|||||||
-- instead. In this case, the handle is not used.
|
-- instead. In this case, the handle is not used.
|
||||||
--
|
--
|
||||||
-- @tparam[opt] string filename The name of the file to extract lines from
|
-- @tparam[opt] string filename The name of the file to extract lines from
|
||||||
|
-- @param ... The argument to pass to @{Handle:read} for each line.
|
||||||
-- @treturn function():string|nil The line iterator.
|
-- @treturn function():string|nil The line iterator.
|
||||||
-- @throws If the file cannot be opened for reading
|
-- @throws If the file cannot be opened for reading
|
||||||
--
|
--
|
||||||
-- @see Handle:lines
|
-- @see Handle:lines
|
||||||
-- @see io.input
|
-- @see io.input
|
||||||
function lines(filename)
|
function lines(filename, ...)
|
||||||
expect(1, filename, "string", "nil")
|
expect(1, filename, "string", "nil")
|
||||||
if filename then
|
if filename then
|
||||||
local ok, err = open(filename, "rb")
|
local ok, err = open(filename, "rb")
|
||||||
@@ -273,9 +277,9 @@ function lines(filename)
|
|||||||
-- We set this magic flag to mark this file as being opened by io.lines and so should be
|
-- We set this magic flag to mark this file as being opened by io.lines and so should be
|
||||||
-- closed automatically
|
-- closed automatically
|
||||||
ok._autoclose = true
|
ok._autoclose = true
|
||||||
return ok:lines()
|
return ok:lines(...)
|
||||||
else
|
else
|
||||||
return currentInput:lines()
|
return currentInput:lines(...)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -313,7 +317,7 @@ end
|
|||||||
-- @throws If the provided filename cannot be opened for writing.
|
-- @throws If the provided filename cannot be opened for writing.
|
||||||
function output(file)
|
function output(file)
|
||||||
if type_of(file) == "string" then
|
if type_of(file) == "string" then
|
||||||
local res, err = open(file, "w")
|
local res, err = open(file, "wb")
|
||||||
if not res then error(err, 2) end
|
if not res then error(err, 2) end
|
||||||
currentOutput = res
|
currentOutput = res
|
||||||
elseif type_of(file) == "table" and getmetatable(file) == handleMetatable then
|
elseif type_of(file) == "table" and getmetatable(file) == handleMetatable then
|
||||||
|
@@ -64,24 +64,33 @@ function isPresent(name)
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Get the type of the peripheral with the given name.
|
--- Get the type of a wrapped peripheral, or a peripheral with the given name.
|
||||||
--
|
--
|
||||||
-- @tparam string name The name of the peripheral to find.
|
-- @tparam string|table peripheral The name of the peripheral to find, or a
|
||||||
|
-- wrapped peripheral instance.
|
||||||
-- @treturn string|nil The peripheral's type, or `nil` if it is not present.
|
-- @treturn string|nil The peripheral's type, or `nil` if it is not present.
|
||||||
function getType(name)
|
function getType(peripheral)
|
||||||
expect(1, name, "string")
|
expect(1, peripheral, "string", "table")
|
||||||
if native.isPresent(name) then
|
if type(peripheral) == "string" then -- Peripheral name passed
|
||||||
return native.getType(name)
|
if native.isPresent(peripheral) then
|
||||||
end
|
return native.getType(peripheral)
|
||||||
for n = 1, #sides do
|
|
||||||
local side = sides[n]
|
|
||||||
if native.getType(side) == "modem" and not native.call(side, "isWireless") and
|
|
||||||
native.call(side, "isPresentRemote", name)
|
|
||||||
then
|
|
||||||
return native.call(side, "getTypeRemote", name)
|
|
||||||
end
|
end
|
||||||
|
for n = 1, #sides do
|
||||||
|
local side = sides[n]
|
||||||
|
if native.getType(side) == "modem" and not native.call(side, "isWireless") and
|
||||||
|
native.call(side, "isPresentRemote", peripheral)
|
||||||
|
then
|
||||||
|
return native.call(side, "getTypeRemote", peripheral)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
else
|
||||||
|
local mt = getmetatable(peripheral)
|
||||||
|
if not mt or mt.__name ~= "peripheral" or type(mt.type) ~= "string" then
|
||||||
|
error("bad argument #1 (table is not a peripheral)", 2)
|
||||||
|
end
|
||||||
|
return mt.type
|
||||||
end
|
end
|
||||||
return nil
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Get all available methods for the peripheral with the given name.
|
--- Get all available methods for the peripheral with the given name.
|
||||||
@@ -105,6 +114,19 @@ function getMethods(name)
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get the name of a peripheral wrapped with @{peripheral.wrap}.
|
||||||
|
--
|
||||||
|
-- @tparam table peripheral The peripheral to get the name of.
|
||||||
|
-- @treturn string The name of the given peripheral.
|
||||||
|
function getName(peripheral)
|
||||||
|
expect(1, peripheral, "table")
|
||||||
|
local mt = getmetatable(peripheral)
|
||||||
|
if not mt or mt.__name ~= "peripheral" or type(mt.name) ~= "string" then
|
||||||
|
error("bad argument #1 (table is not a peripheral)", 2)
|
||||||
|
end
|
||||||
|
return mt.name
|
||||||
|
end
|
||||||
|
|
||||||
--- Call a method on the peripheral with the given name.
|
--- Call a method on the peripheral with the given name.
|
||||||
--
|
--
|
||||||
-- @tparam string name The name of the peripheral to invoke the method on.
|
-- @tparam string name The name of the peripheral to invoke the method on.
|
||||||
@@ -148,7 +170,11 @@ function wrap(name)
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
local result = {}
|
local result = setmetatable({}, {
|
||||||
|
__name = "peripheral",
|
||||||
|
name = name,
|
||||||
|
type = peripheral.getType(name),
|
||||||
|
})
|
||||||
for _, method in ipairs(methods) do
|
for _, method in ipairs(methods) do
|
||||||
result[method] = function(...)
|
result[method] = function(...)
|
||||||
return peripheral.call(name, method, ...)
|
return peripheral.call(name, method, ...)
|
||||||
|
@@ -29,7 +29,7 @@ local tReceivedMessageTimeouts = {}
|
|||||||
local tHostnames = {}
|
local tHostnames = {}
|
||||||
|
|
||||||
--- Opens a modem with the given @{peripheral} name, allowing it to send and
|
--- Opens a modem with the given @{peripheral} name, allowing it to send and
|
||||||
--- receive messages over rednet.
|
-- receive messages over rednet.
|
||||||
--
|
--
|
||||||
-- This will open the modem on two channels: one which has the same
|
-- This will open the modem on two channels: one which has the same
|
||||||
-- @{os.getComputerID|ID} as the computer, and another on
|
-- @{os.getComputerID|ID} as the computer, and another on
|
||||||
@@ -246,7 +246,7 @@ function host(sProtocol, sHostname)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Stop @{rednet.host|hosting} a specific protocol, meaning it will no longer
|
--- Stop @{rednet.host|hosting} a specific protocol, meaning it will no longer
|
||||||
--- respond to @{rednet.lookup} requests.
|
-- respond to @{rednet.lookup} requests.
|
||||||
--
|
--
|
||||||
-- @tparam string sProtocol The protocol to unregister your self from.
|
-- @tparam string sProtocol The protocol to unregister your self from.
|
||||||
function unhost(sProtocol)
|
function unhost(sProtocol)
|
||||||
@@ -334,7 +334,11 @@ end
|
|||||||
|
|
||||||
local bRunning = false
|
local bRunning = false
|
||||||
|
|
||||||
--- @local
|
--- Listen for modem messages and converts them into rednet messages, which may
|
||||||
|
-- then be @{receive|received}.
|
||||||
|
--
|
||||||
|
-- This is automatically started in the background on computer startup, and
|
||||||
|
-- should not be called manually.
|
||||||
function run()
|
function run()
|
||||||
if bRunning then
|
if bRunning then
|
||||||
error("rednet is already running", 2)
|
error("rednet is already running", 2)
|
||||||
|
@@ -205,9 +205,9 @@ function load(sPath)
|
|||||||
end
|
end
|
||||||
|
|
||||||
for k, v in pairs(tFile) do
|
for k, v in pairs(tFile) do
|
||||||
local ty_v = type(k)
|
local ty_v = type(v)
|
||||||
if type(k) == "string" and (ty_v == "string" or ty_v == "number" or ty_v == "boolean" or ty_v == "table") then
|
if type(k) == "string" and (ty_v == "string" or ty_v == "number" or ty_v == "boolean" or ty_v == "table") then
|
||||||
local opt = details[name]
|
local opt = details[k]
|
||||||
if not opt or not opt.type or ty_v == opt.type then
|
if not opt or not opt.type or ty_v == opt.type then
|
||||||
set_value(k, v)
|
set_value(k, v)
|
||||||
end
|
end
|
||||||
|
@@ -5,7 +5,12 @@
|
|||||||
if not turtle then
|
if not turtle then
|
||||||
error("Cannot load turtle API on computer", 2)
|
error("Cannot load turtle API on computer", 2)
|
||||||
end
|
end
|
||||||
native = turtle.native or turtle --- @local
|
|
||||||
|
--- The builtin turtle API, without any generated helper functions.
|
||||||
|
--
|
||||||
|
-- Generally you should not need to use this table - it only exists for
|
||||||
|
-- backwards compatibility reasons.
|
||||||
|
native = turtle.native or turtle
|
||||||
|
|
||||||
local function addCraftMethod(object)
|
local function addCraftMethod(object)
|
||||||
if peripheral.getType("left") == "workbench" then
|
if peripheral.getType("left") == "workbench" then
|
||||||
|
@@ -1,3 +1,30 @@
|
|||||||
|
# New features in CC: Tweaked 1.89.0
|
||||||
|
|
||||||
|
* Compress monitor data, reducing network traffic by a significant amount.
|
||||||
|
* Allow limiting the bandwidth monitor updates use.
|
||||||
|
* Several optimisations to monitor rendering (@Lignum).
|
||||||
|
* Expose block and item tags to turtle.inspect and turtle.getItemDetail.
|
||||||
|
|
||||||
|
And several bug fixes:
|
||||||
|
* Fix settings.load failing on defined settings.
|
||||||
|
|
||||||
|
# New features in CC: Tweaked 1.88.0
|
||||||
|
|
||||||
|
* Computers and turtles now preserve their ID when broken.
|
||||||
|
* Add `peripheral.getName` - returns the name of a wrapped peripheral.
|
||||||
|
* Reduce network overhead of monitors and terminals.
|
||||||
|
* Add a TBO backend for monitors, with a significant performance boost.
|
||||||
|
* The Lua REPL warns when declaring locals (lupus590, exerro)
|
||||||
|
* Add config to allow using command computers in survival.
|
||||||
|
* Add fs.isDriveRoot - checks if a path is the root of a drive.
|
||||||
|
* `cc.pretty` can now display a function's arguments and where it was defined. The Lua REPL will show arguments by default.
|
||||||
|
* Move the shell's `require`/`package` implementation to a separate `cc.require` module.
|
||||||
|
|
||||||
|
And several bug fixes:
|
||||||
|
* Fix io.lines not accepting arguments.
|
||||||
|
* Fix settings.load using an unknown global (MCJack123).
|
||||||
|
* Prevent computers scanning peripherals twice.
|
||||||
|
|
||||||
# New features in CC: Tweaked 1.87.1
|
# New features in CC: Tweaked 1.87.1
|
||||||
|
|
||||||
* Fix blocks not dropping items in survival.
|
* Fix blocks not dropping items in survival.
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
ComputerCraft was created by Daniel "dan200" Ratcliffe, with additional code by Aaron "Cloudy" Mills.
|
ComputerCraft was created by Daniel "dan200" Ratcliffe, with additional code by Aaron "Cloudy" Mills.
|
||||||
Thanks to nitrogenfingers, GopherATL and RamiLego for program contributions.
|
Thanks to nitrogenfingers, GopherATL and RamiLego for program contributions.
|
||||||
Thanks to Mojang, the Forge team, and the MCP team.
|
Thanks to Mojang, the Forge team, and the MCP team.
|
||||||
|
@@ -3,6 +3,7 @@ The peripheral API is for interacting with external peripheral devices. Type "he
|
|||||||
Functions in the peripheral API:
|
Functions in the peripheral API:
|
||||||
peripheral.getNames()
|
peripheral.getNames()
|
||||||
peripheral.isPresent( name )
|
peripheral.isPresent( name )
|
||||||
|
peripheral.getName( peripheral )
|
||||||
peripheral.getType( name )
|
peripheral.getType( name )
|
||||||
peripheral.getMethods( name )
|
peripheral.getMethods( name )
|
||||||
peripheral.call( name, methodName, param1, param2, etc )
|
peripheral.call( name, methodName, param1, param2, etc )
|
||||||
|
@@ -1,5 +1,11 @@
|
|||||||
New features in CC: Tweaked 1.87.1
|
New features in CC: Tweaked 1.89.0
|
||||||
|
|
||||||
* Fix blocks not dropping items in survival.
|
* Compress monitor data, reducing network traffic by a significant amount.
|
||||||
|
* Allow limiting the bandwidth monitor updates use.
|
||||||
|
* Several optimisations to monitor rendering (@Lignum).
|
||||||
|
* Expose block and item tags to turtle.inspect and turtle.getItemDetail.
|
||||||
|
|
||||||
|
And several bug fixes:
|
||||||
|
* Fix settings.load failing on defined settings.
|
||||||
|
|
||||||
Type "help changelog" to see the full version history.
|
Type "help changelog" to see the full version history.
|
||||||
|
@@ -19,8 +19,12 @@
|
|||||||
-- local pretty = require "cc.pretty"
|
-- local pretty = require "cc.pretty"
|
||||||
-- pretty.write(pretty.group(pretty.text("hello") .. pretty.space_line .. pretty.text("world")))
|
-- pretty.write(pretty.group(pretty.text("hello") .. pretty.space_line .. pretty.text("world")))
|
||||||
|
|
||||||
local expect = require "cc.expect".expect
|
local expect = require "cc.expect"
|
||||||
local type, getmetatable, setmetatable, colours, str_write = type, getmetatable, setmetatable, colours, write
|
local expect, field = expect.expect, expect.field
|
||||||
|
|
||||||
|
local type, getmetatable, setmetatable, colours, str_write, tostring = type, getmetatable, setmetatable, colours, write, tostring
|
||||||
|
local debug_info = type(debug) == "table" and type(debug.getinfo) == "function" and debug.getinfo
|
||||||
|
local debug_local = type(debug) == "table" and type(debug.getlocal) == "function" and debug.getlocal
|
||||||
|
|
||||||
--- @{table.insert} alternative, but with the length stored inline.
|
--- @{table.insert} alternative, but with the length stored inline.
|
||||||
local function append(out, value)
|
local function append(out, value)
|
||||||
@@ -343,13 +347,38 @@ local function key_compare(a, b)
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
local function pretty_impl(obj, tracking)
|
local function show_function(fn, options)
|
||||||
|
local info = debug_info and debug_info(fn, "Su")
|
||||||
|
|
||||||
|
-- Include function source position if available
|
||||||
|
local name
|
||||||
|
if options.function_source and info and info.short_src and info.linedefined and info.linedefined >= 1 then
|
||||||
|
name = "function<" .. info.short_src .. ":" .. info.linedefined .. ">"
|
||||||
|
else
|
||||||
|
name = tostring(fn)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Include arguments if a Lua function and if available. Lua will report "C"
|
||||||
|
-- functions as variadic.
|
||||||
|
if options.function_args and info and info.what == "Lua" and info.nparams and debug_local then
|
||||||
|
local args = {}
|
||||||
|
for i = 1, info.nparams do args[i] = debug_local(fn, i) or "?" end
|
||||||
|
if info.isvararg then args[#args + 1] = "..." end
|
||||||
|
name = name .. "(" .. table.concat(args, ", ") .. ")"
|
||||||
|
end
|
||||||
|
|
||||||
|
return name
|
||||||
|
end
|
||||||
|
|
||||||
|
local function pretty_impl(obj, options, tracking)
|
||||||
local obj_type = type(obj)
|
local obj_type = type(obj)
|
||||||
if obj_type == "string" then
|
if obj_type == "string" then
|
||||||
local formatted = ("%q"):format(obj):gsub("\\\n", "\\n")
|
local formatted = ("%q"):format(obj):gsub("\\\n", "\\n")
|
||||||
return text(formatted, colours.red)
|
return text(formatted, colours.red)
|
||||||
elseif obj_type == "number" then
|
elseif obj_type == "number" then
|
||||||
return text(tostring(obj), colours.magenta)
|
return text(tostring(obj), colours.magenta)
|
||||||
|
elseif obj_type == "function" then
|
||||||
|
return text(show_function(obj, options), colours.lightGrey)
|
||||||
elseif obj_type ~= "table" or tracking[obj] then
|
elseif obj_type ~= "table" or tracking[obj] then
|
||||||
return text(tostring(obj), colours.lightGrey)
|
return text(tostring(obj), colours.lightGrey)
|
||||||
elseif getmetatable(obj) ~= nil and getmetatable(obj).__tostring then
|
elseif getmetatable(obj) ~= nil and getmetatable(obj).__tostring then
|
||||||
@@ -371,20 +400,20 @@ local function pretty_impl(obj, tracking)
|
|||||||
local v = obj[k]
|
local v = obj[k]
|
||||||
local ty = type(k)
|
local ty = type(k)
|
||||||
if ty == "number" and k % 1 == 0 and k >= 1 and k <= length then
|
if ty == "number" and k % 1 == 0 and k >= 1 and k <= length then
|
||||||
append(doc, pretty_impl(v, tracking))
|
append(doc, pretty_impl(v, options, tracking))
|
||||||
elseif ty == "string" and not keywords[k] and k:match("^[%a_][%a%d_]*$") then
|
elseif ty == "string" and not keywords[k] and k:match("^[%a_][%a%d_]*$") then
|
||||||
append(doc, text(k .. " = "))
|
append(doc, text(k .. " = "))
|
||||||
append(doc, pretty_impl(v, tracking))
|
append(doc, pretty_impl(v, options, tracking))
|
||||||
else
|
else
|
||||||
append(doc, obracket)
|
append(doc, obracket)
|
||||||
append(doc, pretty_impl(k, tracking))
|
append(doc, pretty_impl(k, options, tracking))
|
||||||
append(doc, cbracket)
|
append(doc, cbracket)
|
||||||
append(doc, pretty_impl(v, tracking))
|
append(doc, pretty_impl(v, options, tracking))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
tracking[obj] = nil
|
tracking[obj] = nil
|
||||||
return group(concat(obrace, nest(2, concat(table.unpack(doc, 1, n))), space_line, cbrace))
|
return group(concat(obrace, nest(2, concat(table.unpack(doc, 1, doc.n))), space_line, cbrace))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -393,12 +422,24 @@ end
|
|||||||
-- This can then be rendered with @{write} or @{print}.
|
-- This can then be rendered with @{write} or @{print}.
|
||||||
--
|
--
|
||||||
-- @param obj The object to pretty-print.
|
-- @param obj The object to pretty-print.
|
||||||
|
-- @tparam[opt] { function_args = boolean, function_source = boolean } options
|
||||||
|
-- Controls how various properties are displayed.
|
||||||
|
-- - `function_args`: Show the arguments to a function if known (`false` by default).
|
||||||
|
-- - `function_source`: Show where the function was defined, instead of
|
||||||
|
-- `function: xxxxxxxx` (`false` by default).
|
||||||
-- @treturn Doc The object formatted as a document.
|
-- @treturn Doc The object formatted as a document.
|
||||||
-- @usage Display a table on the screen
|
-- @usage Display a table on the screen
|
||||||
-- local pretty = require "cc.pretty"
|
-- local pretty = require "cc.pretty"
|
||||||
-- pretty.print(pretty.pretty({ 1, 2, 3 }))
|
-- pretty.print(pretty.pretty({ 1, 2, 3 }))
|
||||||
local function pretty(obj)
|
local function pretty(obj, options)
|
||||||
return pretty_impl(obj, {})
|
expect(2, options, "table", "nil")
|
||||||
|
options = options or {}
|
||||||
|
|
||||||
|
local actual_options = {
|
||||||
|
function_source = field(options, "function_source", "boolean", "nil") or false,
|
||||||
|
function_args = field(options, "function_args", "boolean", "nil") or false,
|
||||||
|
}
|
||||||
|
return pretty_impl(obj, actual_options, {})
|
||||||
end
|
end
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@@ -0,0 +1,121 @@
|
|||||||
|
--- This provides a pure Lua implementation of the builtin @{require} function
|
||||||
|
-- and @{package} library.
|
||||||
|
--
|
||||||
|
-- Generally you do not need to use this module - it is injected into the
|
||||||
|
-- every program's environment. However, it may be useful when building a
|
||||||
|
-- custom shell or when running programs yourself.
|
||||||
|
--
|
||||||
|
-- @module cc.require
|
||||||
|
-- @usage Construct the package and require function, and insert them into a
|
||||||
|
-- custom environment.
|
||||||
|
--
|
||||||
|
-- local env = setmetatable({}, { __index = _ENV })
|
||||||
|
-- local r = require "cc.require"
|
||||||
|
-- env.require, env.package = r.make(env, "/")
|
||||||
|
|
||||||
|
local expect = require and require("cc.expect") or dofile("rom/modules/main/cc/expect.lua")
|
||||||
|
local expect = expect.expect
|
||||||
|
|
||||||
|
local function preload(package)
|
||||||
|
return function(name)
|
||||||
|
if package.preload[name] then
|
||||||
|
return package.preload[name]
|
||||||
|
else
|
||||||
|
return nil, "no field package.preload['" .. name .. "']"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function from_file(package, env, dir)
|
||||||
|
return function(name)
|
||||||
|
local fname = string.gsub(name, "%.", "/")
|
||||||
|
local sError = ""
|
||||||
|
for pattern in string.gmatch(package.path, "[^;]+") do
|
||||||
|
local sPath = string.gsub(pattern, "%?", fname)
|
||||||
|
if sPath:sub(1, 1) ~= "/" then
|
||||||
|
sPath = fs.combine(dir, sPath)
|
||||||
|
end
|
||||||
|
if fs.exists(sPath) and not fs.isDir(sPath) then
|
||||||
|
local fnFile, sError = loadfile(sPath, nil, env)
|
||||||
|
if fnFile then
|
||||||
|
return fnFile, sPath
|
||||||
|
else
|
||||||
|
return nil, sError
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if #sError > 0 then
|
||||||
|
sError = sError .. "\n "
|
||||||
|
end
|
||||||
|
sError = sError .. "no file '" .. sPath .. "'"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil, sError
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function make_require(package)
|
||||||
|
local sentinel = {}
|
||||||
|
return function(name)
|
||||||
|
expect(1, name, "string")
|
||||||
|
|
||||||
|
if package.loaded[name] == sentinel then
|
||||||
|
error("loop or previous error loading module '" .. name .. "'", 0)
|
||||||
|
end
|
||||||
|
|
||||||
|
if package.loaded[name] then
|
||||||
|
return package.loaded[name]
|
||||||
|
end
|
||||||
|
|
||||||
|
local sError = "module '" .. name .. "' not found:"
|
||||||
|
for _, searcher in ipairs(package.loaders) do
|
||||||
|
local loader = table.pack(searcher(name))
|
||||||
|
if loader[1] then
|
||||||
|
package.loaded[name] = sentinel
|
||||||
|
local result = loader[1](name, table.unpack(loader, 2, loader.n))
|
||||||
|
if result == nil then result = true end
|
||||||
|
|
||||||
|
package.loaded[name] = result
|
||||||
|
return result
|
||||||
|
else
|
||||||
|
sError = sError .. "\n " .. loader[2]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
error(sError, 2)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Build an implementation of Lua's @{package} library, and a @{require}
|
||||||
|
-- function to load modules within it.
|
||||||
|
--
|
||||||
|
-- @tparam table env The environment to load packages into.
|
||||||
|
-- @tparam string dir The directory that relative packages are loaded from.
|
||||||
|
-- @treturn function The new @{require} function.
|
||||||
|
-- @treturn table The new @{package} library.
|
||||||
|
local function make_package(env, dir)
|
||||||
|
expect(1, env, "table")
|
||||||
|
expect(2, dir, "string")
|
||||||
|
|
||||||
|
local package = {}
|
||||||
|
package.loaded = {
|
||||||
|
_G = _G,
|
||||||
|
bit32 = bit32,
|
||||||
|
coroutine = coroutine,
|
||||||
|
math = math,
|
||||||
|
package = package,
|
||||||
|
string = string,
|
||||||
|
table = table,
|
||||||
|
}
|
||||||
|
package.path = "?;?.lua;?/init.lua;/rom/modules/main/?;/rom/modules/main/?.lua;/rom/modules/main/?/init.lua"
|
||||||
|
if turtle then
|
||||||
|
package.path = package.path .. ";/rom/modules/turtle/?;/rom/modules/turtle/?.lua;/rom/modules/turtle/?/init.lua"
|
||||||
|
elseif commands then
|
||||||
|
package.path = package.path .. ";/rom/modules/command/?;/rom/modules/command/?.lua;/rom/modules/command/?/init.lua"
|
||||||
|
end
|
||||||
|
package.config = "/\n;\n?\n!\n-"
|
||||||
|
package.preload = {}
|
||||||
|
package.loaders = { preload(package), from_file(package, env, dir) }
|
||||||
|
|
||||||
|
return make_require(package), package
|
||||||
|
end
|
||||||
|
|
||||||
|
return { make = make_package }
|
@@ -141,12 +141,12 @@ return {
|
|||||||
program = program,
|
program = program,
|
||||||
|
|
||||||
-- Re-export various other functions
|
-- Re-export various other functions
|
||||||
help = wrap(help.completeTopic),
|
help = wrap(help.completeTopic), --- Wraps @{help.completeTopic} as a @{build} compatible function.
|
||||||
choice = wrap(completion.choice),
|
choice = wrap(completion.choice), --- Wraps @{cc.completion.choice} as a @{build} compatible function.
|
||||||
peripheral = wrap(completion.peripheral),
|
peripheral = wrap(completion.peripheral), --- Wraps @{cc.completion.peripheral} as a @{build} compatible function.
|
||||||
side = wrap(completion.side),
|
side = wrap(completion.side), --- Wraps @{cc.completion.side} as a @{build} compatible function.
|
||||||
setting = wrap(completion.setting),
|
setting = wrap(completion.setting), --- Wraps @{cc.completion.setting} as a @{build} compatible function.
|
||||||
command = wrap(completion.command),
|
command = wrap(completion.command), --- Wraps @{cc.completion.command} as a @{build} compatible function.
|
||||||
|
|
||||||
build = build,
|
build = build,
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
if not shell.openTab then
|
if not shell.openTab then
|
||||||
printError("Requires multishell")
|
printError("Requires multishell")
|
||||||
return
|
return
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
if not shell.openTab then
|
if not shell.openTab then
|
||||||
printError("Requires multishell")
|
printError("Requires multishell")
|
||||||
return
|
return
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
local tArgs = { ... }
|
local tArgs = { ... }
|
||||||
if #tArgs > 2 then
|
if #tArgs > 2 then
|
||||||
print("Usage: alias <alias> <program>")
|
print("Usage: alias <alias> <program>")
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
local tApis = {}
|
local tApis = {}
|
||||||
for k, v in pairs(_G) do
|
for k, v in pairs(_G) do
|
||||||
if type(k) == "string" and type(v) == "table" and k ~= "_G" then
|
if type(k) == "string" and type(v) == "table" and k ~= "_G" then
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
local tArgs = { ... }
|
local tArgs = { ... }
|
||||||
if #tArgs < 1 then
|
if #tArgs < 1 then
|
||||||
print("Usage: cd <path>")
|
print("Usage: cd <path>")
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
if not commands then
|
if not commands then
|
||||||
printError("Requires a Command Computer.")
|
printError("Requires a Command Computer.")
|
||||||
return
|
return
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
local tArgs = { ... }
|
local tArgs = { ... }
|
||||||
if not commands then
|
if not commands then
|
||||||
printError("Requires a Command Computer.")
|
printError("Requires a Command Computer.")
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
local tArgs = { ... }
|
local tArgs = { ... }
|
||||||
if #tArgs < 2 then
|
if #tArgs < 2 then
|
||||||
print("Usage: cp <source> <destination>")
|
print("Usage: cp <source> <destination>")
|
||||||
|
@@ -9,9 +9,18 @@ for i = 1, args.n do
|
|||||||
local files = fs.find(shell.resolve(args[i]))
|
local files = fs.find(shell.resolve(args[i]))
|
||||||
if #files > 0 then
|
if #files > 0 then
|
||||||
for _, file in ipairs(files) do
|
for _, file in ipairs(files) do
|
||||||
local ok, err = pcall(fs.delete, file)
|
if fs.isReadOnly(file) then
|
||||||
if not ok then
|
printError("Cannot delete read-only file /" .. file)
|
||||||
printError((err:gsub("^pcall: ", "")))
|
elseif fs.isDriveRoot(file) then
|
||||||
|
printError("Cannot delete mount /" .. file)
|
||||||
|
if fs.isDir(file) then
|
||||||
|
print("To delete its contents run rm /" .. fs.combine(file, "*"))
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local ok, err = pcall(fs.delete, file)
|
||||||
|
if not ok then
|
||||||
|
printError((err:gsub("^pcall: ", "")))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
-- Get arguments
|
-- Get arguments
|
||||||
local tArgs = { ... }
|
local tArgs = { ... }
|
||||||
if #tArgs == 0 then
|
if #tArgs == 0 then
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
local tBiomes = {
|
local tBiomes = {
|
||||||
"in a forest",
|
"in a forest",
|
||||||
"in a pine forest",
|
"in a pine forest",
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
-- Display the start screen
|
-- Display the start screen
|
||||||
local w, h = term.getSize()
|
local w, h = term.getSize()
|
||||||
|
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
local function printUsage()
|
local function printUsage()
|
||||||
print("Usages:")
|
print("Usages:")
|
||||||
print("gps host")
|
print("gps host")
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
local function printUsage()
|
local function printUsage()
|
||||||
print("Usages:")
|
print("Usages:")
|
||||||
print("pastebin put <filename>")
|
print("pastebin put <filename>")
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
local function printUsage()
|
local function printUsage()
|
||||||
print("Usage:")
|
print("Usage:")
|
||||||
print("wget <url> [filename]")
|
print("wget <url> [filename]")
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
local sDrive = nil
|
local sDrive = nil
|
||||||
local tArgs = { ... }
|
local tArgs = { ... }
|
||||||
if #tArgs > 0 then
|
if #tArgs > 0 then
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
local function printUsage()
|
local function printUsage()
|
||||||
print("Usages:")
|
print("Usages:")
|
||||||
print("label get")
|
print("label get")
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
local tArgs = { ... }
|
local tArgs = { ... }
|
||||||
|
|
||||||
-- Get all the files in the directory
|
-- Get all the files in the directory
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
local tArgs = { ... }
|
local tArgs = { ... }
|
||||||
if #tArgs > 0 then
|
if #tArgs > 0 then
|
||||||
print("This is an interactive Lua prompt.")
|
print("This is an interactive Lua prompt.")
|
||||||
@@ -67,6 +66,13 @@ while bRunning do
|
|||||||
if s:match("%S") and tCommandHistory[#tCommandHistory] ~= s then
|
if s:match("%S") and tCommandHistory[#tCommandHistory] ~= s then
|
||||||
table.insert(tCommandHistory, s)
|
table.insert(tCommandHistory, s)
|
||||||
end
|
end
|
||||||
|
if settings.get("lua.warn_against_use_of_local") and s:match("^%s*local%s+") then
|
||||||
|
if term.isColour() then
|
||||||
|
term.setTextColour(colours.yellow)
|
||||||
|
end
|
||||||
|
print("To access local variables in later inputs, remove the local keyword.")
|
||||||
|
term.setTextColour(colours.white)
|
||||||
|
end
|
||||||
|
|
||||||
local nForcePrint = 0
|
local nForcePrint = 0
|
||||||
local func, e = load(s, "=lua", "t", tEnv)
|
local func, e = load(s, "=lua", "t", tEnv)
|
||||||
@@ -89,7 +95,10 @@ while bRunning do
|
|||||||
local n = 1
|
local n = 1
|
||||||
while n < tResults.n or n <= nForcePrint do
|
while n < tResults.n or n <= nForcePrint do
|
||||||
local value = tResults[n + 1]
|
local value = tResults[n + 1]
|
||||||
local ok, serialised = pcall(pretty.pretty, value)
|
local ok, serialised = pcall(pretty.pretty, value, {
|
||||||
|
function_args = settings.get("lua.function_args"),
|
||||||
|
function_source = settings.get("lua.function_source"),
|
||||||
|
})
|
||||||
if ok then
|
if ok then
|
||||||
pretty.print(serialised)
|
pretty.print(serialised)
|
||||||
else
|
else
|
||||||
|
@@ -28,7 +28,7 @@ local monitor = peripheral.wrap(sName)
|
|||||||
local previousTerm = term.redirect(monitor)
|
local previousTerm = term.redirect(monitor)
|
||||||
|
|
||||||
local co = coroutine.create(function()
|
local co = coroutine.create(function()
|
||||||
shell.run(sProgram, table.unpack(tArgs, 3))
|
(shell.execute or shell.run)(sProgram, table.unpack(tArgs, 3))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
local function resume(...)
|
local function resume(...)
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
local tArgs = { ... }
|
local tArgs = { ... }
|
||||||
if #tArgs < 2 then
|
if #tArgs < 2 then
|
||||||
print("Usage: mv <source> <destination>")
|
print("Usage: mv <source> <destination>")
|
||||||
@@ -8,12 +7,35 @@ end
|
|||||||
local sSource = shell.resolve(tArgs[1])
|
local sSource = shell.resolve(tArgs[1])
|
||||||
local sDest = shell.resolve(tArgs[2])
|
local sDest = shell.resolve(tArgs[2])
|
||||||
local tFiles = fs.find(sSource)
|
local tFiles = fs.find(sSource)
|
||||||
|
|
||||||
|
local function sanity_checks(source, dest)
|
||||||
|
if fs.exists(dest) then
|
||||||
|
printError("Destination exists")
|
||||||
|
return false
|
||||||
|
elseif fs.isReadOnly(dest) then
|
||||||
|
printError("Destination is read-only")
|
||||||
|
return false
|
||||||
|
elseif fs.isDriveRoot(source) then
|
||||||
|
printError("Cannot move mount /" .. source)
|
||||||
|
return false
|
||||||
|
elseif fs.isReadOnly(source) then
|
||||||
|
printError("Cannot move read-only file /" .. source)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
if #tFiles > 0 then
|
if #tFiles > 0 then
|
||||||
for _, sFile in ipairs(tFiles) do
|
for _, sFile in ipairs(tFiles) do
|
||||||
if fs.isDir(sDest) then
|
if fs.isDir(sDest) then
|
||||||
fs.move(sFile, fs.combine(sDest, fs.getName(sFile)))
|
local dest = fs.combine(sDest, fs.getName(sFile))
|
||||||
|
if sanity_checks(sFile, dest) then
|
||||||
|
fs.move(sFile, dest)
|
||||||
|
end
|
||||||
elseif #tFiles == 1 then
|
elseif #tFiles == 1 then
|
||||||
fs.move(sFile, sDest)
|
if sanity_checks(sFile, sDest) then
|
||||||
|
fs.move(sFile, sDest)
|
||||||
|
end
|
||||||
else
|
else
|
||||||
printError("Cannot overwrite file multiple times")
|
printError("Cannot overwrite file multiple times")
|
||||||
return
|
return
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user