1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-10-17 23:17:38 +00:00

Compare commits

..

51 Commits

Author SHA1 Message Date
SquidDev
83df64e520 Merge branch 'mc-1.15.x' into mc-1.16.x 2020-11-07 12:46:10 +00:00
SquidDev
74ac5bb3d1 Bump to 1.94.0 2020-11-07 12:43:57 +00:00
Lupus590
d13bd2cce8 use arg[0] in all usage printouts (#571) 2020-11-04 14:03:08 +00:00
SquidDev
ab232bd689 Update to MC 1.16.4
Just some mapping changes really
2020-11-03 15:33:10 +00:00
SquidDev
cc96e41d3e Remove stray copy-paste error from changelog 2020-11-03 14:37:24 +00:00
Drew Lemmy
741adfa7bb Use blit to draw boxes, add colors.toBlit (#570) 2020-11-01 19:28:18 +00:00
SquidDev
666e83cf4f Fix JSON objects failing to pass
Maybe I should run the whole test suite, not just the things I think
matter? Nah....
2020-11-01 11:48:19 +00:00
SquidDev
e2a635b6e5 Don't fail when codecov is being finicky 2020-11-01 11:36:53 +00:00
SquidDev
c58441b29c Various SNBT parsing improvements
Correctly handle:
 - Typed arrays ([I; 1, 2, 3])
 - All suffixed numbers (1.2d)
 - Single-quoted strings

Fixes #559
2020-11-01 11:36:48 +00:00
SquidDev
a6fcfb6af2 Draw in-hand pocket computers with blending
It might be worth switching to RenderTypes here, rather than a pure
Tesselator, but this'll do for now.

Fixes Zundrel/cc-tweaked-fabric#20.
2020-11-01 11:12:28 +00:00
SquidDev
17a9329207 Bump cct-javadoc version
Documentation will now be sorted (somewhat) correctly!
2020-10-31 12:50:03 +00:00
SquidDev
f6160bdc57 Fix players not getting advancements when they own turtles
When we construct a new ServerPlayerEntity (and thus TurtlePlayer), we
get the current (global) advancement state and call .setPlayer() on it.

As grantCriterion blocks FakePlayers from getting advancements, this
means a player will no longer receive any advancements, as the "wrong"
player object is being consulted.

As a temporary work around, we attempt to restore the previous player to
the advancement store. I'll try to upstream something into Forge to
resolve this properly.

Fixes #564
2020-10-31 10:59:24 +00:00
SquidDev
6aae4e5766 Remove superfluous imports
Hah, this is embarassing
2020-10-31 10:09:54 +00:00
SquidDev
84a6bb1cf3 Make generic peripherals on by default
This is a long way away from "feature complete" as it were. However,
it's definitely at a point where it's suitable for general usage - I'm
happy with the API, and don't think I'm going to be breaking things any
time soon.

That said, things aren't exposed yet for Java-side public consumption. I
was kinda waiting until working on Plethora to actually do that, but not
sure if/when that'll happen.

If someone else wants to work on an integration mod (or just adding
integrations for their own mod), do get in touch and I can work out how
to expose this.

Closes #452
2020-10-31 10:03:09 +00:00
SquidDev
c334423d42 Add function to get window visibility
Closes #562

Co-authored-by: devomaa <lmao@distruzione.org>
2020-10-31 09:54:38 +00:00
Jonathan Coates
113b560a20 Update configuration to match latest illuaminate
Ooooooh, it's all fancy now. Well, that or horrifically broken.
2020-10-27 22:20:01 +00:00
SquidDev
5bf367af9f Merge branch 'mc-1.15.x' into mc-1.16.x 2020-10-23 17:45:11 +01:00
SquidDev
61fb4caaad Bump to 1.93.1 2020-10-23 17:44:52 +01:00
Jonathan Coates
6734af6e4a Merge pull request #560 from Lemmmy/lemmmy/fix-monitor-tbo
Fix TBO normalisation issues on old GPUs
2020-10-22 12:14:27 +01:00
Drew Lemmy
bf6053906d Fix TBO norm issues on old GPUs 2020-10-21 10:28:12 +01:00
SquidDev
4766833cf2 Bump JEI/crafttweaker versions
In my defence, they weren't out when I started the 1.15 update.
2020-10-20 17:38:59 +01:00
Drew Lemmy
01d81cb91d Update illuaminate CSS for deprecation (#556) 2020-10-14 22:05:56 +01:00
Drew Lemmy
93068402a2 Document remaining OS functions (#554) 2020-10-11 22:38:18 +01:00
Drew Lemmy
34a2c835d4 Add color table to docs (#553) 2020-10-11 21:37:56 +01:00
Jonathan Coates
30d35883b8 Fix my docs
Thanks @plt-hokusai. Kinda embarrassing this slipped through - I
evidently need to lint examples too.
2020-10-08 09:48:36 +01:00
SquidDev
71563a52ff Let's make this a proper release 2020-10-04 11:31:06 +01:00
SquidDev
0c6e7b5db5 Merge branch 'mc-1.15.x' into mc-1.16.x 2020-10-04 11:24:42 +01:00
SquidDev
334ca65482 Bump to 1.93.0 2020-10-04 11:19:43 +01:00
Jonathan Coates
8472112fc1 Don't propagate adjacent redstone signals for computers (#549)
Minecraft propagates "strong" redstone signals (such as those directly
from comparators or repeaters) through solid blocks. This includes
computers, which is a little annoying as it means one cannot feed
redstone wire from one side and a repeater from another.

This changes computers to not propagate strong redstone signals, in the
same way transparent blocks like glass do.

Closes #548.
2020-10-04 11:14:22 +01:00
SquidDev
84036d97d9 Fix io.open documentation
Well, that was silly.
2020-10-02 21:21:53 +01:00
Weblate
0832974725 Translations for Swedish
Co-authored-by: David Isaksson <davidisaksson93@gmail.com>
2020-09-30 08:25:57 +00:00
SquidDev
6cee4efcd3 Fix incorrect open container check
Was this always broken, or did it happen in a Minecraft update? Don't
know, but it's a very silly mistake either way. Fixes #544
2020-09-24 17:47:30 +01:00
SquidDev
6f868849ab Use tags to check if something is a dye
We half did this already, just needed to change a couple of checks.
Closes #541.
2020-09-16 21:27:59 +01:00
SquidDev
275ca58a82 HTTP rules now allow filtering by port
The HTTP filtering system becomes even more complex! Though in this
case, it's pretty minimal, and definitely worth doing.

For instance, the following rule will allow connecting to localhost on
port :8080.

    [[http.rules]]
    host = "127.0.0.1"
    port = 8080
    action = "allow"

    # Other rules as before.

Closes #540
2020-09-15 22:05:27 +01:00
SquidDev
87393e8aef Fix additional - in docs
Why isn't this automatically stripped! Bad squid.
2020-09-13 17:56:12 +01:00
SquidDev
86bf57e3cd My inability to spell will be immortalsied in the changelog 2020-09-12 11:03:18 +01:00
SquidDev
72c1d451fe Mark the release as beta-quality 2020-09-12 10:47:19 +01:00
SquidDev
8b4a01df27 Update to Minecraft 1.16.3
I hope the Fabric folks now realise this is gonna be a race of who can
update first :p. Either way, this was a very easy update - only changes
were due to unrelated Forge changes.
2020-09-12 10:45:59 +01:00
SquidDev
d0a973fa46 Merge branch 'mc-1.15.x' into mc-1.16.x 2020-09-12 09:29:21 +01:00
SquidDev
748ebbe66b Bump to 1.92.0
A tiny release, but there's new features so it's technically a minor
bump.
2020-09-12 09:27:47 +01:00
SquidDev
59de21eae2 Handle tabs when parsing JSON
Fixes #539
2020-09-11 18:02:23 +01:00
SquidDev
50473afea8 Fix Gradle example for depending on CC:T
See #405
2020-09-09 08:39:28 +01:00
SquidDev
37f925de0a Remove references to cc.crzd.me's maven
As CC only exists on 1.12.2, it's a bit meaningless to talk about it on
1.15+!
2020-09-08 18:37:40 +01:00
SquidDev
cefde3f003 Also block 0.0.0.0/8
See MightyPirates/OpenComputers#3356
2020-09-08 18:12:20 +01:00
Weblate
ae6124d1f4 Translations for Vietnamese
Co-authored-by: Boom <boom@flyingpackets.net>
2020-09-08 03:57:52 +00:00
Weblate
7e121ff72f Translations for Vietnamese
Co-authored-by: Boom <boom@flyingpackets.net>
2020-09-07 06:37:58 +00:00
Weblate
5155e18de2 Added translation for Vietnamese
Co-authored-by: Boom <boom@flyingpackets.net>
2020-09-07 03:33:36 +00:00
SquidDev
7365741088 Don't use entity.captureDrops at all.
This really should have been removed in 9e2232d240.
Otherwise we don't drop these items into the world at all. Fixes #537.
2020-09-05 11:02:24 +01:00
JackMacWindows
d5368d0719 Add date-specific MOTDs (like Minecraft) (#533) 2020-09-04 17:35:46 +01:00
Jonathan Coates
04509cefec Merge pull request #529 from Bluenaxela/mc-1.15.x
Pretty sure FileSystemWrapperMount.isDirectory() should call Filesystem.isDir(), not Filesystem.exists()
2020-08-25 08:11:13 +01:00
Bluenaxela
74b9f5dcb0 Fix FileSystemWrapperMount.isDirectory()
Pretty sure FileSystemWrapperMount.isDirectory() should call Filesystem.isDir(), not Filesystem.exists()
2020-08-24 23:55:24 -07:00
107 changed files with 1061 additions and 471 deletions

View File

@@ -34,6 +34,7 @@ jobs:
- name: Upload Coverage
run: bash <(curl -s https://codecov.io/bash)
continue-on-error: true
- name: Generate Java documentation stubs
run: ./gradlew luaJavadoc --no-daemon

View File

@@ -12,5 +12,5 @@ chmod 600 "$HOME/.ssh/key"
# And upload
rsync -avc -e "ssh -i $HOME/.ssh/key -o StrictHostKeyChecking=no -p $SSH_PORT" \
"$GITHUB_WORKSPACE/doc/" \
"$GITHUB_WORKSPACE/doc/out/" \
"$SSH_USER@$SSH_HOST:/var/www/tweaked.cc/$DEST"

3
.gitignore vendored
View File

@@ -3,9 +3,8 @@
/logs
/build
/out
/doc/**/*.html
/doc/out/
/doc/javadoc/
/doc/index.json
# Runtime directories
/run

View File

@@ -50,12 +50,12 @@ I'd generally recommend you don't contact me directly (email, DM, etc...) unless
report exploits). You'll get a far quicker response if you ask the whole community!
## Using
If you want to depend on CC: Tweaked, we have a maven repo. However, you should be wary that some functionality is only
exposed by CC:T's API and not vanilla ComputerCraft. If you wish to support all variations of ComputerCraft, I recommend
using [cc.crzd.me's maven](https://cc.crzd.me/maven/) instead.
CC: Tweaked is hosted on my maven repo, and so is relatively simple to depend on. You may wish to add a soft (or hard)
dependency in your `mods.toml` file, with the appropriate version bounds, to ensure that API functionality you depend
on is present.
```groovy
dependencies {
repositories {
maven { url 'https://squiddev.cc/maven/' }
}

View File

@@ -9,7 +9,7 @@ buildscript {
}
dependencies {
classpath 'com.google.code.gson:gson:2.8.1'
classpath 'net.minecraftforge.gradle:ForgeGradle:3.0.181'
classpath 'net.minecraftforge.gradle:ForgeGradle:3.0.187'
classpath 'net.sf.proguard:proguard-gradle:6.1.0beta2'
classpath 'org.ajoberstar.grgit:grgit-gradle:3.0.0'
}
@@ -106,10 +106,10 @@ dependencies {
minecraft "net.minecraftforge:forge:${mc_version}-${forge_version}"
compileOnly fg.deobf("mezz.jei:jei-1.15.2:6.0.0.3:api")
compileOnly fg.deobf("com.blamejared.crafttweaker:CraftTweaker-1.15.2:6.0.0.9")
compileOnly fg.deobf("mezz.jei:jei-1.16.3:7.6.0.49:api")
compileOnly fg.deobf("com.blamejared.crafttweaker:CraftTweaker-1.16.3:7.0.0.48")
// runtimeOnly fg.deobf("mezz.jei:jei-1.15.2:6.0.0.3")
runtimeOnly fg.deobf("mezz.jei:jei-1.16.3:7.6.0.49")
compileOnly 'com.google.auto.service:auto-service:1.0-rc7'
annotationProcessor 'com.google.auto.service:auto-service:1.0-rc7'
@@ -122,7 +122,7 @@ dependencies {
deployerJars "org.apache.maven.wagon:wagon-ssh:3.0.0"
cctJavadoc 'cc.tweaked:cct-javadoc:1.1.0'
cctJavadoc 'cc.tweaked:cct-javadoc:1.2.1'
}
// Compile tasks
@@ -409,7 +409,7 @@ curseforge {
apiKey = project.hasProperty('curseForgeApiKey') ? project.curseForgeApiKey : ''
project {
id = '282001'
releaseType = 'alpha'
releaseType = 'release'
changelog = "Release notes can be found on the GitHub repository (https://github.com/SquidDev-CC/CC-Tweaked/releases/tag/v${mc_version}-${mod_version})."
relations {
@@ -487,7 +487,7 @@ githubRelease {
.takeWhile { it != 'Type "help changelog" to see the full version history.' }
.join("\n").trim()
}
prerelease true
prerelease false
}
def uploadTasks = ["uploadArchives", "curseforge", "githubRelease"]

55
doc/stub/global.lua Normal file
View File

@@ -0,0 +1,55 @@
--[[-
Global functions defined by `bios.lua`. This does not include standard Lua
functions.
@module _G
]]
--[[- Pauses execution for the specified number of seconds.
As it waits for a fixed amount of world ticks, `time` will automatically be
rounded up to the nearest multiple of 0.05 seconds. If you are using coroutines
or the @{parallel|parallel API}, it will only pause execution of the current
thread, not the whole program.
**Note** Because sleep internally uses timers, it is a function that yields.
This means that you can use it to prevent "Too long without yielding" errors,
however, as the minimum sleep time is 0.05 seconds, it will slow your program
down.
**Warning** Internally, this function queues and waits for a timer event (using
@{os.startTimer}), however it does not listen for any other events. This means
that any event that occurs while sleeping will be entirely discarded. If you
need to receive events while sleeping, consider using @{os.startTimer|timers},
or the @{parallel|parallel API}.
@tparam number time The number of seconds to sleep for, rounded up to the
nearest multiple of 0.05.
@see os.startTimer
]]
function sleep(time) end
function write(text) end
function print(...) end
function printError(...) end
function read(replaceChar, history, completeFn, default) end
--- The ComputerCraft and Minecraft version of the current computer environment.
--
-- For example, `ComputerCraft 1.93.0 (Minecraft 1.15.2)`.
_HOST = _HOST
--[[- The default computer settings as defined in the ComputerCraft
configuration.
This is a comma-separated list of settings pairs defined by the mod
configuration or server owner. By default, it is empty.
An example value to disable autocompletion:
shell.autocomplete=false,lua.autocomplete=false,edit.autocomplete=false
]]
_CC_DEFAULT_SETTINGS = _CC_DEFAULT_SETTINGS

View File

@@ -1,8 +1,6 @@
--- The http library allows communicating with web servers, sending and
-- receiving data from them.
--
-- #### `http_check` event
--
-- @module http
--- Asynchronously make a HTTP request to the given url.

View File

@@ -1,6 +1,121 @@
-- Defined in bios.lua
--[[- Loads the given API into the global environment.
**Warning** This function is deprecated. Use of this function will pollute the
global table, use @{require} instead.
This function loads and executes the file at the given path, and all global
variables and functions exported by it will by available through the use of
`myAPI.<function name>`, where `myAPI` is the base name of the API file.
@tparam string path The path of the API to load.
@treturn boolean Whether or not the API was successfully loaded.
@deprecated Use @{require}.
]]
function loadAPI(path) end
--- Unloads an API which was loaded by @{os.loadAPI}.
--
-- This effectively removes the specified table from `_G`.
--
-- @tparam string name The name of the API to unload.
-- @deprecated Use @{require}.
function unloadAPI(name) end
--[[- Pause execution of the current thread and waits for any events matching
`filter`.
This function @{coroutine.yield|yields} the current process and waits for it
to be resumed with a vararg list where the first element matches `filter`.
If no `filter` is supplied, this will match all events.
Unlike @{os.pullEventRaw}, it will stop the application upon a "terminate"
event, printing the error "Terminated".
@tparam[opt] string filter Event to filter for.
@treturn string event The name of the event that fired.
@treturn any param... Optional additional parameters of the event.
@usage Listen for `mouse_click` events.
while true do
local event, button, x, y = os.pullEvent("mouse_click")
print("Button", button, "was clicked at", x, ",", y)
end
@usage Listen for multiple events.
while true do
local eventData = {os.pullEvent()}
local event = eventData[1]
if event == "mouse_click" then
print("Button", eventData[2], "was clicked at", eventData[3], ",", eventData[4])
elseif event == "key" then
print("Key code", eventData[2], "was pressed")
end
end
@see os.pullEventRaw To pull the terminate event.
]]
function pullEvent(filter) end
--[[- Pause execution of the current thread and waits for events, including the
`terminate` event.
This behaves almost the same as @{os.pullEvent}, except it allows you to handle
the `terminate` event yourself - the program will not stop execution when
<kbd>Ctrl+T</kbd> is pressed.
@tparam[opt] string filter Event to filter for.
@treturn string event The name of the event that fired.
@treturn any param... Optional additional parameters of the event.
@usage Listen for `terminate` events.
while true do
local event = os.pullEventRaw()
if event == "terminate" then
print("Caught terminate event!")
end
end
@see os.pullEvent To pull events normally.
]]
function pullEventRaw(filter) end
--- Pauses execution for the specified number of seconds, alias of @{_G.sleep}.
function sleep(time) end
--- Get the current CraftOS version (for example, `CraftOS 1.8`).
--
-- This is defined by `bios.lua`. For the current version of CC:Tweaked, this
-- should return `CraftOS 1.8`.
--
-- @treturn string The current CraftOS version.
function version() end
--[[- Run the program at the given path with the specified environment and
arguments.
This function does not resolve program names like the shell does. This means
that, for example, `os.run("edit")` will not work. As well as this, it does not
provide access to the @{shell} API in the environment. For this behaviour, use
@{shell.run} instead.
If the program cannot be found, or failed to run, it will print the error and
return `false`. If you want to handle this more gracefully, use an alternative
such as @{loadfile}.
@tparam table env The environment to run the program with.
@tparam string path The exact path of the program to run.
@param ... The arguments to pass to the program.
@treturn boolean Whether or not the program ran successfully.
@usage Run the default shell from within your program:
os.run({}, "/rom/programs/shell")
@see shell.run
@see loadfile
]]
function run(env, path, ...) end

View File

@@ -1,191 +1,14 @@
/* Basic reset on elements */
h1, h2, h3, h4, p, table, div, body {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* Make the page a little more airy */
body {
margin: 20px auto;
max-width: 1200px;
padding: 0 10px;
line-height: 1.6;
color: #222;
background: #fff;
}
/* Try to use system default fonts. */
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans",
"Droid Sans", "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
}
code, pre, .parameter, .type, .definition-name, .reference-code {
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
}
/* Some definitions of basic tags */
code {
color: #c7254e;
background-color: #f9f2f4;
}
p {
margin: 0.9em 0;
}
h1 {
font-size: 1.5em;
font-weight: lighter;
border-bottom: solid 1px #aaa;
}
h2, h3, h4 { margin: 1.4em 0 0.3em;}
h2 { font-size: 1.25em; }
h3 { font-size: 1.15em; font-weight: bold; }
h4 { font-size: 1.06em; }
a, a:visited, a:active { font-weight: bold; color: #004080; text-decoration: none; }
a:hover { text-decoration: underline; }
blockquote {
padding: 0.3em;
margin: 1em 0;
background: #f0f0f0;
border-left: solid 0.5em #ccc;
}
/* Stop sublists from having initial vertical space */
ul ul { margin-top: 0px; }
ol ul { margin-top: 0px; }
ol ol { margin-top: 0px; }
ul ol { margin-top: 0px; }
/* Make the target distinct; helps when we're navigating to a function */
a:target + * { background-color: #FFFF99; }
/* Allow linking to any subsection */
a[name]::before { content: "#"; }
/* Layout */
#main {
display: flex;
flex-wrap: nowrap;
justify-content: space-between;
min-height: calc(100vh - 100px);
}
#main > nav {
flex-basis: 30%;
min-width: 150px;
max-width: 250px;
background-color: #f0f0f0;
}
nav h1, nav ul { padding: 0em 10px; }
nav h2 {
background-color:#e7e7e7;
font-size: 1.1em;
color:#000000;
padding: 5px 10px;
}
nav ul {
list-style-type: none;
margin: 0;
}
#content {
flex-shrink: 1;
flex-basis: 80%;
padding: 0px 10px;
}
footer {
text-align: right;
font-size: 0.8em;
}
/* The definition lists at the top of each page */
table.definition-list {
/* Pretty tables, mostly inherited from table.definition-list */
table.pretty-table {
border-collapse: collapse;
width: 100%;
}
table.definition-list td, table.definition-list th {
table.pretty-table td, table.pretty-table th {
border: 1px solid #cccccc;
padding: 5px;
padding: 2px 4px;
}
table.definition-list th {
table.pretty-table th {
background-color: #f0f0f0;
min-width: 200px;
white-space: nowrap;
text-align: right;
}
table.definition-list td { width: 100%; }
dl.definition dt {
border-top: 1px solid #ccc;
padding-top: 1em;
display: flex;
}
dl.definition dt .definition-name {
padding: 0 0.1em;
margin: 0 0.1em;
flex-grow: 1;
}
dl.definition dd {
padding-bottom: 1em;
margin: 10px 0 0 20px;
}
dl.definition h3 {
font-size: .95em;
}
/* Links to source-code */
.source-link { font-size: 0.8em; }
.source-link::before { content: '[' }
.source-link::after { content: ']' }
a.source-link, a.source-link:visited, a.source-link:active { color: #505050; }
/* Method definitions */
span.parameter:after { content:":"; padding-left: 0.3em; }
.optional { text-decoration: underline dotted; }
/** Fancy colour display. */
.colour-ref {
display: inline-block;
width: 0.8em;
height: 0.8em;
margin: 0.1em 0.1em 0.3em 0.1em; /* Terrrible hack to force vertical alignment. */
border: solid 1px black;
box-sizing: border-box;
vertical-align: middle;
}
/* styles for prettification of source */
.highlight .comment { color: #558817; }
.highlight .constant { color: #a8660d; }
.highlight .escape { color: #844631; }
.highlight .keyword { color: #aa5050; font-weight: bold; }
.highlight .library { color: #0e7c6b; }
.highlight .marker { color: #512b1e; background: #fedc56; font-weight: bold; }
.highlight .string { color: #8080ff; }
.highlight .literal-kw { color: #8080ff; }
.highlight .number { color: #f8660d; }
.highlight .operator { color: #2239a8; font-weight: bold; }
.highlight .preprocessor, pre .prepro { color: #a33243; }
.highlight .global { color: #800080; }
.highlight .user-keyword { color: #800080; }
.highlight .prompt { color: #558817; }
.highlight .url { color: #272fc2; text-decoration: underline; }

View File

@@ -1,7 +1,7 @@
# Mod properties
mod_version=1.91.1
mod_version=1.94.0
# Minecraft properties (update mods.toml when changing)
mc_version=1.16.2
forge_version=33.0.37
mappings_version=20200723-1.16.1
mc_version=1.16.4
forge_version=35.0.1
mappings_version=20201028-1.16.3

View File

@@ -10,7 +10,10 @@
(doc
(title "CC: Tweaked")
(destination doc/out)
(logo src/main/resources/pack.png)
(index doc/index.md)
(styles doc/styles.css)
(source-link https://github.com/SquidDev-CC/CC-Tweaked/blob/${commit}/${path}#L${line})
(module-kinds
@@ -50,7 +53,7 @@
;; colours imports from colors, and we don't handle that right now.
;; keys is entirely dynamic, so we skip it.
(dynamic-modules colours keys)
(dynamic-modules colours keys _G)
(globals
:max
@@ -79,6 +82,7 @@
/doc/stub/http.lua
/doc/stub/os.lua
/doc/stub/turtle.lua
/doc/stub/global.lua
; Java generated APIs
/doc/javadoc/turtle.lua
; Peripherals
@@ -100,6 +104,10 @@
/doc/stub/fs.lua)
(linters -doc:unresolved-reference))
;; Suppress warnings for the BIOS using its own deprecated members for now.
(at /src/main/resources/*/computercraft/lua/bios.lua
(linters -var:deprecated))
(at /src/test/resources/test-rom
; We should still be able to test deprecated members.
(linters -var:deprecated)

View File

@@ -39,6 +39,7 @@ public final class ComputerCraft
public static final String[] DEFAULT_HTTP_ALLOW = new String[] { "*" };
public static final String[] DEFAULT_HTTP_DENY = new String[] {
"127.0.0.0/8",
"0.0.0.0/8",
"10.0.0.0/8",
"172.16.0.0/12",
"192.168.0.0/16",
@@ -62,10 +63,10 @@ public final class ComputerCraft
public static boolean httpWebsocketEnabled = true;
public static List<AddressRule> httpRules = Collections.unmodifiableList( Stream.concat(
Stream.of( DEFAULT_HTTP_DENY )
.map( x -> AddressRule.parse( x, Action.DENY.toPartial() ) )
.map( x -> AddressRule.parse( x, null, Action.DENY.toPartial() ) )
.filter( Objects::nonNull ),
Stream.of( DEFAULT_HTTP_ALLOW )
.map( x -> AddressRule.parse( x, Action.ALLOW.toPartial() ) )
.map( x -> AddressRule.parse( x, null, Action.ALLOW.toPartial() ) )
.filter( Objects::nonNull )
).collect( Collectors.toList() ) );
@@ -89,8 +90,6 @@ public final class ComputerCraft
public static boolean turtlesCanPush = true;
public static EnumSet<TurtleAction> turtleDisabledActions = EnumSet.noneOf( TurtleAction.class );
public static boolean genericPeripheral = false;
public static int computerTermWidth = 51;
public static int computerTermHeight = 19;

View File

@@ -139,7 +139,7 @@ public interface ITurtleAccess
*
* @return This turtle's owner.
*/
@Nonnull
@Nullable
GameProfile getOwningPlayer();
/**

View File

@@ -23,7 +23,7 @@ public class ClientTableFormatter implements TableFormatter
{
public static final ClientTableFormatter INSTANCE = new ClientTableFormatter();
private static Int2IntOpenHashMap lastHeights = new Int2IntOpenHashMap();
private static final Int2IntOpenHashMap lastHeights = new Int2IntOpenHashMap();
private static FontRenderer renderer()
{
@@ -55,7 +55,7 @@ public class ClientTableFormatter implements TableFormatter
@Override
public int getWidth( ITextComponent component )
{
return renderer().func_238414_a_( component );
return renderer().getStringPropertyWidth( component );
}
@Override

View File

@@ -141,7 +141,7 @@ public final class GuiComputer<T extends ContainerComputerBase> extends Containe
public void render( @Nonnull MatrixStack stack, int mouseX, int mouseY, float partialTicks )
{
super.render( stack, mouseX, mouseY, partialTicks );
func_230459_a_( stack, mouseX, mouseY );
renderHoveredTooltip( stack, mouseX, mouseY );
}
@Override

View File

@@ -37,6 +37,6 @@ public class GuiDiskDrive extends ContainerScreen<ContainerDiskDrive>
{
renderBackground( transform );
super.render( transform, mouseX, mouseY, partialTicks );
func_230459_a_( transform, mouseX, mouseY );
renderHoveredTooltip( transform, mouseX, mouseY );
}
}

View File

@@ -47,6 +47,6 @@ public class GuiPrinter extends ContainerScreen<ContainerPrinter>
{
renderBackground( stack );
super.render( stack, mouseX, mouseY, partialTicks );
func_230459_a_( stack, mouseX, mouseY );
renderHoveredTooltip( stack, mouseX, mouseY );
}
}

View File

@@ -126,7 +126,7 @@ public class GuiTurtle extends ContainerScreen<ContainerTurtle>
{
renderBackground( stack );
super.render( stack, mouseX, mouseY, partialTicks );
func_230459_a_( stack, mouseX, mouseY );
renderHoveredTooltip( stack, mouseX, mouseY );
}
@Override

View File

@@ -75,7 +75,7 @@ public final class ComputerCraftProxyClient
ResourceLocation id = new ResourceLocation( ComputerCraft.MOD_ID, name );
for( Supplier<? extends Item> item : items )
{
ItemModelsProperties.func_239418_a_( item.get(), id, getter );
ItemModelsProperties.registerProperty( item.get(), id, getter );
}
}

View File

@@ -119,6 +119,7 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
private static void renderFrame( Matrix4f transform, ComputerFamily family, int colour, int width, int height )
{
RenderSystem.enableBlend();
Minecraft.getInstance().getTextureManager()
.bindTexture( colour != -1 ? ComputerBorderRenderer.BACKGROUND_COLOUR : ComputerBorderRenderer.getTexture( family ) );
@@ -137,7 +138,6 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
private static void renderLight( Matrix4f transform, int colour, int width, int height )
{
RenderSystem.enableBlend();
RenderSystem.disableTexture();
float r = ((colour >>> 16) & 0xFF) / 255.0f;

View File

@@ -108,9 +108,9 @@ public class TurtleMultiModel implements IBakedModel
}
@Override
public boolean func_230044_c_()
public boolean isSideLit()
{
return m_baseModel.func_230044_c_();
return m_baseModel.isSideLit();
}
@Nonnull

View File

@@ -109,7 +109,7 @@ public class TurtleSmartItemModel implements IBakedModel
{
@Nonnull
@Override
public IBakedModel func_239290_a_( @Nonnull IBakedModel originalModel, @Nonnull ItemStack stack, @Nullable ClientWorld world, @Nullable LivingEntity entity )
public IBakedModel getOverrideModel( @Nonnull IBakedModel originalModel, @Nonnull ItemStack stack, @Nullable ClientWorld world, @Nullable LivingEntity entity )
{
ItemTurtle turtle = (ItemTurtle) stack.getItem();
int colour = turtle.getColour( stack );
@@ -184,9 +184,9 @@ public class TurtleSmartItemModel implements IBakedModel
}
@Override
public boolean func_230044_c_()
public boolean isSideLit()
{
return familyModel.func_230044_c_();
return familyModel.isSideLit();
}
@Nonnull

View File

@@ -171,12 +171,18 @@ public class OSAPI implements ILuaAPI
/**
* Starts a timer that will run for the specified number of seconds. Once
* the timer fires, a timer event will be added to the queue with the ID
* returned from this function as the first parameter.
* the timer fires, a {@code timer} event will be added to the queue with
* the ID returned from this function as the first parameter.
*
* As with @{os.sleep|sleep}, {@code timer} will automatically be rounded up
* to the nearest multiple of 0.05 seconds, as it waits for a fixed amount
* of world ticks.
*
* @param timer The number of seconds until the timer fires.
* @return The ID of the new timer.
* @return The ID of the new timer. This can be used to filter the
* {@code timer} event, or {@link #cancelTimer cancel the timer}.
* @throws LuaException If the time is below zero.
* @see #cancelTimer To cancel a timer.
*/
@LuaFunction
public final int startTimer( double timer ) throws LuaException
@@ -199,11 +205,14 @@ public class OSAPI implements ILuaAPI
/**
* Sets an alarm that will fire at the specified world time. When it fires,
* an alarm event will be added to the event queue.
* an {@code alarm} event will be added to the event queue with the ID
* returned from this function as the first parameter.
*
* @param time The time at which to fire the alarm, in the range [0.0, 24.0).
* @return The ID of the alarm that was set.
* @return The ID of the new alarm. This can be used to filter the
* {@code alarm} event, or {@link #cancelAlarm cancel the alarm}.
* @throws LuaException If the time is out of range.
* @see #cancelAlarm To cancel an alarm.
*/
@LuaFunction
public final int setAlarm( double time ) throws LuaException

View File

@@ -24,14 +24,14 @@ public class CheckUrl extends Resource<CheckUrl>
private final IAPIEnvironment environment;
private final String address;
private final String host;
private final URI uri;
public CheckUrl( ResourceGroup<CheckUrl> limiter, IAPIEnvironment environment, String address, URI uri )
{
super( limiter );
this.environment = environment;
this.address = address;
host = uri.getHost();
this.uri = uri;
}
public void run()
@@ -47,8 +47,9 @@ public class CheckUrl extends Resource<CheckUrl>
try
{
InetSocketAddress netAddress = NetworkUtils.getAddress( host, 80, false );
NetworkUtils.getOptions( host, netAddress );
boolean ssl = uri.getScheme().equalsIgnoreCase( "https" );
InetSocketAddress netAddress = NetworkUtils.getAddress( uri, ssl );
NetworkUtils.getOptions( uri.getHost(), netAddress );
if( tryClose() ) environment.queueEvent( EVENT, address, true );
}

View File

@@ -19,6 +19,7 @@ import io.netty.handler.ssl.SslContextBuilder;
import javax.net.ssl.SSLException;
import javax.net.ssl.TrustManagerFactory;
import java.net.InetSocketAddress;
import java.net.URI;
import java.security.KeyStore;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.SynchronousQueue;
@@ -99,6 +100,21 @@ public final class NetworkUtils
}
}
/**
* Create a {@link InetSocketAddress} from a {@link java.net.URI}.
*
* Note, this may require a DNS lookup, and so should not be executed on the main CC thread.
*
* @param uri The URI to fetch.
* @param ssl Whether to connect with SSL. This is used to find the default port if not otherwise specified.
* @return The resolved address.
* @throws HTTPRequestException If the host is not malformed.
*/
public static InetSocketAddress getAddress( URI uri, boolean ssl ) throws HTTPRequestException
{
return getAddress( uri.getHost(), uri.getPort(), ssl );
}
/**
* Create a {@link InetSocketAddress} from the resolved {@code host} and port.
*
@@ -128,7 +144,7 @@ public final class NetworkUtils
*/
public static Options getOptions( String host, InetSocketAddress address ) throws HTTPRequestException
{
Options options = AddressRule.apply( ComputerCraft.httpRules, host, address.getAddress() );
Options options = AddressRule.apply( ComputerCraft.httpRules, host, address );
if( options.action == Action.DENY ) throw new HTTPRequestException( "Domain not permitted" );
return options;
}

View File

@@ -12,6 +12,7 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.regex.Pattern;
/**
@@ -52,17 +53,23 @@ public final class AddressRule
private final HostRange ip;
private final Pattern domainPattern;
private final Integer port;
private final PartialOptions partial;
private AddressRule( @Nullable HostRange ip, @Nullable Pattern domainPattern, @Nonnull PartialOptions partial )
private AddressRule(
@Nullable HostRange ip,
@Nullable Pattern domainPattern,
@Nullable Integer port,
@Nonnull PartialOptions partial )
{
this.ip = ip;
this.domainPattern = domainPattern;
this.partial = partial;
this.port = port;
}
@Nullable
public static AddressRule parse( String filter, @Nonnull PartialOptions partial )
public static AddressRule parse( String filter, @Nullable Integer port, @Nonnull PartialOptions partial )
{
int cidr = filter.indexOf( '/' );
if( cidr >= 0 )
@@ -117,24 +124,27 @@ public final class AddressRule
size -= 8;
}
return new AddressRule( new HostRange( minBytes, maxBytes ), null, partial );
return new AddressRule( new HostRange( minBytes, maxBytes ), null, port, partial );
}
else
{
Pattern pattern = Pattern.compile( "^\\Q" + filter.replaceAll( "\\*", "\\\\E.*\\\\Q" ) + "\\E$" );
return new AddressRule( null, pattern, partial );
return new AddressRule( null, pattern, port, partial );
}
}
/**
* Determine whether the given address matches a series of patterns.
*
* @param domain The domain to match
* @param address The address to check.
* @param domain The domain to match
* @param socketAddress The address to check.
* @return Whether it matches any of these patterns.
*/
private boolean matches( String domain, InetAddress address )
private boolean matches( String domain, InetSocketAddress socketAddress )
{
InetAddress address = socketAddress.getAddress();
if( port != null && port != socketAddress.getPort() ) return false;
if( domainPattern != null )
{
if( domainPattern.matcher( domain ).matches() ) return true;
@@ -155,7 +165,7 @@ public final class AddressRule
return ip != null && ip.contains( address );
}
public static Options apply( Iterable<? extends AddressRule> rules, String domain, InetAddress address )
public static Options apply( Iterable<? extends AddressRule> rules, String domain, InetSocketAddress address )
{
PartialOptions options = null;
boolean hasMany = false;

View File

@@ -49,12 +49,14 @@ public class AddressRuleConfig
public static boolean checkRule( UnmodifiableConfig builder )
{
String hostObj = get( builder, "host", String.class ).orElse( null );
Integer port = get( builder, "port", Number.class ).map( Number::intValue ).orElse( null );
return hostObj != null && checkEnum( builder, "action", Action.class )
&& check( builder, "port", Number.class )
&& check( builder, "timeout", Number.class )
&& check( builder, "max_upload", Number.class )
&& check( builder, "max_download", Number.class )
&& check( builder, "websocket_message", Number.class )
&& AddressRule.parse( hostObj, PartialOptions.DEFAULT ) != null;
&& AddressRule.parse( hostObj, port, PartialOptions.DEFAULT ) != null;
}
@Nullable
@@ -64,6 +66,7 @@ public class AddressRuleConfig
if( hostObj == null ) return null;
Action action = getEnum( builder, "action", Action.class ).orElse( null );
Integer port = get( builder, "port", Number.class ).map( Number::intValue ).orElse( null );
Integer timeout = get( builder, "timeout", Number.class ).map( Number::intValue ).orElse( null );
Long maxUpload = get( builder, "max_upload", Number.class ).map( Number::longValue ).orElse( null );
Long maxDownload = get( builder, "max_download", Number.class ).map( Number::longValue ).orElse( null );
@@ -77,7 +80,7 @@ public class AddressRuleConfig
websocketMessage
);
return AddressRule.parse( hostObj, options );
return AddressRule.parse( hostObj, port, options );
}
private static <T> boolean check( UnmodifiableConfig config, String field, Class<T> klass )

View File

@@ -136,7 +136,7 @@ public class HttpRequest extends Resource<HttpRequest>
try
{
boolean ssl = uri.getScheme().equalsIgnoreCase( "https" );
InetSocketAddress socketAddress = NetworkUtils.getAddress( uri.getHost(), uri.getPort(), ssl );
InetSocketAddress socketAddress = NetworkUtils.getAddress( uri, ssl );
Options options = NetworkUtils.getOptions( uri.getHost(), socketAddress );
SslContext sslContext = ssl ? NetworkUtils.getSslContext() : null;

View File

@@ -129,8 +129,7 @@ public class Websocket extends Resource<Websocket>
try
{
boolean ssl = uri.getScheme().equalsIgnoreCase( "wss" );
InetSocketAddress socketAddress = NetworkUtils.getAddress( uri.getHost(), uri.getPort(), ssl );
InetSocketAddress socketAddress = NetworkUtils.getAddress( uri, ssl );
Options options = NetworkUtils.getOptions( uri.getHost(), socketAddress );
SslContext sslContext = ssl ? NetworkUtils.getSslContext() : null;

View File

@@ -124,7 +124,7 @@ public class FileSystemWrapperMount implements IFileSystem
{
try
{
return m_filesystem.exists( path );
return m_filesystem.isDir( path );
}
catch( FileSystemException e )
{

View File

@@ -7,7 +7,6 @@
package dan200.computercraft.data;
import dan200.computercraft.shared.proxy.ComputerCraftProxyCommon;
import net.minecraft.data.BlockTagsProvider;
import net.minecraft.data.DataGenerator;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
@@ -24,6 +23,6 @@ public class Generators
DataGenerator generator = event.getGenerator();
generator.addProvider( new Recipes( generator ) );
generator.addProvider( new LootTables( generator ) );
generator.addProvider( new Tags( generator, new BlockTagsProvider( generator ) ) );
generator.addProvider( new Tags( generator, event.getExistingFileHelper() ) );
}
}

View File

@@ -51,7 +51,7 @@ public abstract class LootTableProvider implements IDataProvider
tables.put( id, table );
} );
tables.forEach( ( key, value ) -> LootTableManager.func_227508_a_( validation, key, value ) );
tables.forEach( ( key, value ) -> LootTableManager.validateLootTable( validation, key, value ) );
Multimap<String, String> problems = validation.getProblems();
if( !problems.isEmpty() )

View File

@@ -15,12 +15,13 @@ import net.minecraft.item.Item;
import net.minecraft.tags.ITag;
import net.minecraft.tags.ItemTags;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.common.data.ExistingFileHelper;
import static dan200.computercraft.data.Tags.CCTags.*;
public class Tags extends ItemTagsProvider
{
private static final ITag.INamedTag<Item> PIGLIN_LOVED = ItemTags.field_232903_N_;
private static final ITag.INamedTag<Item> PIGLIN_LOVED = ItemTags.PIGLIN_LOVED;
public static class CCTags
{
@@ -30,9 +31,9 @@ public class Tags extends ItemTagsProvider
public static final ITag.INamedTag<Item> MONITOR = item( "monitor" );
}
public Tags( DataGenerator generator, BlockTagsProvider tags )
public Tags( DataGenerator generator, ExistingFileHelper helper )
{
super( generator, tags );
super( generator, new BlockTagsProvider( generator, ComputerCraft.MOD_ID, helper ), ComputerCraft.MOD_ID, helper );
}
@Override

View File

@@ -82,8 +82,6 @@ public final class Config
private static final ConfigValue<Integer> monitorWidth;
private static final ConfigValue<Integer> monitorHeight;
private static final ConfigValue<Boolean> genericPeripheral;
private static final ConfigValue<MonitorRenderer> monitorRenderer;
private static final ConfigValue<Integer> monitorDistance;
@@ -294,17 +292,6 @@ public final class Config
builder.pop();
}
{
builder.comment( "Options for various experimental features. These are not guaranteed to be stable, and may change or be removed across versions." );
builder.push( "experimental" );
genericPeripheral = builder
.comment( "Attempt to make any existing block (or tile entity) a peripheral.\n" +
"This provides peripheral methods for any inventory, fluid tank or energy storage block. It will" +
"_not_ provide methods which have an existing peripheral provider." )
.define( "generic_peripherals", false );
}
serverSpec = builder.build();
Builder clientBuilder = new Builder();
@@ -379,9 +366,6 @@ public final class Config
ComputerCraft.monitorWidth = monitorWidth.get();
ComputerCraft.monitorHeight = monitorHeight.get();
// Experimental
ComputerCraft.genericPeripheral = genericPeripheral.get();
// Client
ComputerCraft.monitorRenderer = monitorRenderer.get();
ComputerCraft.monitorDistanceSq = monitorDistance.get() * monitorDistance.get();

View File

@@ -116,7 +116,6 @@ public class CommandAPI implements ILuaAPI
* @param command The command to execute.
* @return The "task id". When this command has been executed, it will queue a `task_complete` event with a matching id.
* @throws LuaException (hidden) If the task cannot be created.
* @cc.tparam string command The command to execute.
* @cc.usage Asynchronously sets the block above the computer to stone.
* <pre>
* commands.execAsync("~ ~1 ~ minecraft:stone")

View File

@@ -27,6 +27,7 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorldReader;
import net.minecraft.world.World;
import net.minecraft.world.server.ServerWorld;
import net.minecraftforge.fml.RegistryObject;
@@ -182,4 +183,10 @@ public abstract class BlockComputerBase<T extends TileComputerBase> extends Bloc
if( label != null ) computer.setLabel( label );
}
}
@Override
public boolean shouldCheckWeakPower( BlockState state, IWorldReader world, BlockPos pos, Direction side )
{
return false;
}
}

View File

@@ -29,13 +29,13 @@ public final class ConstantLootConditionSerializer<T extends ILootCondition> imp
}
@Override
public void func_230424_a_( @Nonnull JsonObject json, @Nonnull T object, @Nonnull JsonSerializationContext context )
public void serialize( @Nonnull JsonObject json, @Nonnull T object, @Nonnull JsonSerializationContext context )
{
}
@Nonnull
@Override
public T func_230423_a_( @Nonnull JsonObject json, @Nonnull JsonDeserializationContext context )
public T deserialize( @Nonnull JsonObject json, @Nonnull JsonDeserializationContext context )
{
return instance;
}

View File

@@ -78,7 +78,7 @@ public final class NetworkHandler
public static void sendToAllAround( NetworkMessage packet, World world, Vector3d pos, double range )
{
PacketDistributor.TargetPoint target = new PacketDistributor.TargetPoint( pos.x, pos.y, pos.z, range, world.func_234923_W_() );
PacketDistributor.TargetPoint target = new PacketDistributor.TargetPoint( pos.x, pos.y, pos.z, range, world.getDimensionKey() );
network.send( PacketDistributor.NEAR.with( () -> target ), packet );
}

View File

@@ -140,7 +140,8 @@ public class DiskDrivePeripheral implements IPeripheral
/**
* Returns the title of the inserted audio disk.
*
* @return The title of the audio, or {@code nil} if no audio disk is inserted.
* @return The title of the audio, or {@code false} if no audio disk is inserted.
* @cc.treturn string|nil|false The title of the audio, {@code false} if no disk is inserted, or {@code nil} if the disk has no audio.
*/
@LuaFunction
@Nullable

View File

@@ -125,7 +125,7 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory
public void read( @Nonnull BlockState state, @Nonnull CompoundNBT nbt )
{
super.read( state, nbt );
customName = nbt.contains( NBT_NAME ) ? ITextComponent.Serializer.func_240643_a_( nbt.getString( NBT_NAME ) ) : null;
customName = nbt.contains( NBT_NAME ) ? ITextComponent.Serializer.getComponentFromJson( nbt.getString( NBT_NAME ) ) : null;
if( nbt.contains( NBT_ITEM ) )
{
CompoundNBT item = nbt.getCompound( NBT_ITEM );

View File

@@ -6,7 +6,6 @@
package dan200.computercraft.shared.peripheral.generic;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.core.asm.NamedMethod;
import dan200.computercraft.core.asm.PeripheralMethod;
@@ -35,8 +34,6 @@ public class GenericPeripheralProvider
@Nonnull
public static LazyOptional<IPeripheral> getPeripheral( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side )
{
if( !ComputerCraft.genericPeripheral ) return LazyOptional.empty();
TileEntity tile = world.getTileEntity( pos );
if( tile == null ) return LazyOptional.empty();

View File

@@ -7,7 +7,6 @@
package dan200.computercraft.shared.peripheral.generic.data;
import com.google.gson.JsonParseException;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.util.NBTUtil;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.enchantment.EnchantmentHelper;
@@ -26,9 +25,6 @@ import java.util.stream.Collectors;
/**
* Data providers for items.
*
* We guard using {@link ComputerCraft#genericPeripheral} in several places, as advanced functionality should not be
* exposed for {@code turtle.getItemDetail} when generic peripehrals are disabled.
*/
public class ItemData
{
@@ -73,8 +69,6 @@ public class ItemData
data.put( "tags", DataHelpers.getTags( stack.getItem().getTags() ) );
if( !ComputerCraft.genericPeripheral ) return data;
CompoundNBT tag = stack.getTag();
if( tag != null && tag.contains( "display", Constants.NBT.TAG_COMPOUND ) )
{
@@ -113,7 +107,7 @@ public class ItemData
{
try
{
return ITextComponent.Serializer.func_240643_a_( x.getString() );
return ITextComponent.Serializer.getComponentFromJson( x.getString() );
}
catch( JsonParseException e )
{

View File

@@ -69,7 +69,7 @@ public final class ClientMonitor extends ClientTerminal
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 );
GL31.glTexBuffer( GL31.GL_TEXTURE_BUFFER, GL30.GL_R8UI, tboBuffer );
GL11.glBindTexture( GL31.GL_TEXTURE_BUFFER, 0 );
GlStateManager.bindBuffer( GL31.GL_TEXTURE_BUFFER, 0 );

View File

@@ -13,7 +13,6 @@ import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.Inventory;
import net.minecraft.inventory.container.Container;
import net.minecraft.inventory.container.Slot;
import net.minecraft.item.DyeItem;
import net.minecraft.item.ItemStack;
import net.minecraft.util.IIntArray;
import net.minecraft.util.IntArray;
@@ -95,7 +94,7 @@ public class ContainerPrinter extends Container
else
{
// Transfer from inventory to printer
if( stack.getItem() instanceof DyeItem )
if( TilePrinter.isInk( stack ) )
{
if( !mergeItemStack( stack, 0, 1, false ) ) return ItemStack.EMPTY;
}

View File

@@ -95,7 +95,7 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent
{
super.read( state, nbt );
customName = nbt.contains( NBT_NAME ) ? ITextComponent.Serializer.func_240643_a_( nbt.getString( NBT_NAME ) ) : null;
customName = nbt.contains( NBT_NAME ) ? ITextComponent.Serializer.getComponentFromJson( nbt.getString( NBT_NAME ) ) : null;
// Read page
synchronized( m_page )
@@ -300,9 +300,9 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent
}
}
private static boolean isInk( @Nonnull ItemStack stack )
static boolean isInk( @Nonnull ItemStack stack )
{
return stack.getItem() instanceof DyeItem;
return ColourUtils.getStackColour( stack ) != null;
}
private static boolean isPaper( @Nonnull ItemStack stack )
@@ -321,7 +321,8 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent
private boolean inputPage()
{
ItemStack inkStack = m_inventory.get( 0 );
if( !isInk( inkStack ) ) return false;
DyeColor dye = ColourUtils.getStackColour( inkStack );
if( dye == null ) return false;
for( int i = 1; i < 7; i++ )
{
@@ -329,8 +330,7 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent
if( paperStack.isEmpty() || !isPaper( paperStack ) ) continue;
// Setup the new page
DyeColor dye = ColourUtils.getStackColour( inkStack );
m_page.setTextColour( dye != null ? dye.getId() : 15 );
m_page.setTextColour( dye.getId() );
m_page.clear();
if( paperStack.getItem() instanceof ItemPrintout )

View File

@@ -152,7 +152,7 @@ public abstract class SpeakerPeripheral implements IPeripheral
float adjVolume = Math.min( volume, 3.0f );
server.getPlayerList().sendToAllNearExcept(
null, pos.x, pos.y, pos.z, adjVolume > 1.0f ? 16 * adjVolume : 16.0, world.func_234923_W_(),
null, pos.x, pos.y, pos.z, adjVolume > 1.0f ? 16 * adjVolume : 16.0, world.getDimensionKey(),
new SPlaySoundPacket( name, SoundCategory.RECORDS, pos, adjVolume, pitch )
);
return null;

View File

@@ -45,6 +45,7 @@ import net.minecraftforge.items.IItemHandlerModifiable;
import net.minecraftforge.items.wrapper.InvWrapper;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.*;
import java.util.concurrent.TimeUnit;
@@ -598,7 +599,7 @@ public class TurtleBrain implements ITurtleAccess
m_owningPlayer = profile;
}
@Nonnull
@Nullable
@Override
public GameProfile getOwningPlayer()
{

View File

@@ -17,6 +17,7 @@ import net.minecraft.entity.EntitySize;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.Pose;
import net.minecraft.entity.passive.horse.AbstractHorseEntity;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.container.INamedContainerProvider;
import net.minecraft.item.ItemStack;
@@ -41,11 +42,30 @@ public final class TurtlePlayer extends FakePlayer
"[ComputerCraft]"
);
private TurtlePlayer( ITurtleAccess turtle )
private TurtlePlayer( ServerWorld world, GameProfile name )
{
super( (ServerWorld) turtle.getWorld(), getProfile( turtle.getOwningPlayer() ) );
this.connection = new FakeNetHandler( this );
setState( turtle );
super( world, name );
}
private static TurtlePlayer create( ITurtleAccess turtle )
{
ServerWorld world = (ServerWorld) turtle.getWorld();
GameProfile profile = turtle.getOwningPlayer();
TurtlePlayer player = new TurtlePlayer( world, getProfile( profile ) );
player.connection = new FakeNetHandler( player );
player.setState( turtle );
if( profile != null && profile.getId() != null )
{
// Constructing a player overrides the "active player" variable in advancements. As fake players cannot
// get advancements, this prevents a normal player who has placed a turtle from getting advancements.
// We try to locate the "actual" player and restore them.
ServerPlayerEntity actualPlayer = world.getServer().getPlayerList().getPlayerByUUID( profile.getId() );
if( actualPlayer != null ) player.getAdvancements().setPlayer( actualPlayer );
}
return player;
}
private static GameProfile getProfile( @Nullable GameProfile profile )
@@ -55,11 +75,10 @@ public final class TurtlePlayer extends FakePlayer
private void setState( ITurtleAccess turtle )
{
if( openContainer != null )
if( openContainer != container )
{
ComputerCraft.log.warn( "Turtle has open container ({})", openContainer );
openContainer.onContainerClosed( this );
openContainer = null;
closeContainer();
}
BlockPos position = turtle.getPosition();
@@ -73,14 +92,14 @@ public final class TurtlePlayer extends FakePlayer
public static TurtlePlayer get( ITurtleAccess access )
{
if( !(access instanceof TurtleBrain) ) return new TurtlePlayer( access );
if( !(access instanceof TurtleBrain) ) return create( access );
TurtleBrain brain = (TurtleBrain) access;
TurtlePlayer player = brain.m_cachedPlayer;
if( player == null || player.getGameProfile() != getProfile( access.getOwningPlayer() )
|| player.getEntityWorld() != access.getWorld() )
{
player = brain.m_cachedPlayer = new TurtlePlayer( brain );
player = brain.m_cachedPlayer = create( brain );
}
else
{

View File

@@ -100,7 +100,7 @@ public class TurtleTool extends AbstractTurtleUpgrade
protected boolean canBreakBlock( BlockState state, World world, BlockPos pos, TurtlePlayer player )
{
Block block = state.getBlock();
return !state.isAir( world, pos )
return !state.isAir()
&& block != Blocks.BEDROCK
&& state.getPlayerRelativeBlockHardness( player, world, pos ) > 0
&& block.canEntityDestroy( state, world, pos, player );

View File

@@ -40,6 +40,8 @@ public final class ColourUtils
public static DyeColor getStackColour( ItemStack stack )
{
if( stack.isEmpty() ) return null;
for( int i = 0; i < DYES.length; i++ )
{
ITag<Item> dye = DYES[i];

View File

@@ -42,8 +42,6 @@ public final class DropConsumer
dropEntity = entity;
dropWorld = entity.world;
dropBounds = new AxisAlignedBB( entity.getPosition() ).grow( 2, 2, 2 );
entity.captureDrops( new ArrayList<>() );
}
public static void set( World world, BlockPos pos, Function<ItemStack, ItemStack> consumer )
@@ -86,7 +84,7 @@ public final class DropConsumer
}
}
@SubscribeEvent
@SubscribeEvent( priority = EventPriority.LOW )
public static void onLivingDrops( LivingDropsEvent drops )
{
if( dropEntity == null || drops.getEntity() != dropEntity ) return;

View File

@@ -16,7 +16,6 @@ import net.minecraftforge.common.util.FakePlayer;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.crypto.SecretKey;
public class FakeNetHandler extends ServerPlayNetHandler
{
@@ -322,11 +321,6 @@ public class FakeNetHandler extends ServerPlayNetHandler
this.closeReason = message;
}
@Override
public void enableEncryption( @Nonnull SecretKey key )
{
}
@Nonnull
@Override
public INetHandler getNetHandler()

View File

@@ -1,5 +1,5 @@
modLoader="javafml"
loaderVersion="[33,34)"
loaderVersion="[35,36)"
issueTrackerURL="https://github.com/SquidDev-CC/CC-Tweaked/issues"
displayURL="https://github.com/SquidDev-CC/CC-Tweaked"
@@ -20,6 +20,6 @@ CC: Tweaked is a fork of ComputerCraft, adding programmable computers, turtles a
[[dependencies.computercraft]]
modId="forge"
mandatory=true
versionRange="[33.0.20,34)"
versionRange="[35.0.1,36)"
ordering="NONE"
side="BOTH"

View File

@@ -1,14 +1,14 @@
{
"block.computercraft.computer_normal": "Dator",
"block.computercraft.computer_advanced": "Avancerad Dator",
"block.computercraft.computer_command": "Kommando Dator",
"block.computercraft.computer_command": "Kommandodator",
"block.computercraft.disk_drive": "Diskettläsare",
"block.computercraft.printer": "Skrivare",
"block.computercraft.speaker": "Högtalare",
"block.computercraft.monitor_normal": "Skärm",
"block.computercraft.monitor_advanced": "Avancerad Skärm",
"block.computercraft.wireless_modem_normal": "Trådlöst Modem",
"block.computercraft.wireless_modem_advanced": "Ender Modem",
"block.computercraft.wireless_modem_advanced": "Endermodem",
"block.computercraft.wired_modem": "Trådat Modem",
"block.computercraft.cable": "Nätverkskabel",
"block.computercraft.wired_modem_full": "Trådat Modem",
@@ -38,5 +38,76 @@
"upgrade.computercraft.speaker.adjective": "Högljudd",
"chat.computercraft.wired_modem.peripheral_connected": "Kringutrustning \"%s\" är kopplad till nätverket",
"chat.computercraft.wired_modem.peripheral_disconnected": "Kringutrustning \"%s\" är frånkopplad från nätverket",
"gui.computercraft.tooltip.copy": "Kopiera till urklipp"
"gui.computercraft.tooltip.copy": "Kopiera till urklipp",
"gui.computercraft.tooltip.disk_id": "Diskett-ID: %s",
"gui.computercraft.tooltip.computer_id": "Dator-ID: %s",
"tracking_field.computercraft.coroutines_dead.name": "Coroutines borttagna",
"tracking_field.computercraft.coroutines_created.name": "Coroutines skapade",
"tracking_field.computercraft.websocket_outgoing.name": "Websocket utgående",
"tracking_field.computercraft.websocket_incoming.name": "Websocket ingående",
"tracking_field.computercraft.http_download.name": "HTTP-nedladdning",
"tracking_field.computercraft.http_upload.name": "HTTP-uppladdning",
"tracking_field.computercraft.http.name": "HTTP-förfrågningar",
"tracking_field.computercraft.turtle.name": "Turtle-operationer",
"tracking_field.computercraft.fs.name": "Filsystemoperationer",
"tracking_field.computercraft.peripheral.name": "Samtal till kringutrustning",
"tracking_field.computercraft.server_time.name": "Serveraktivitetstid",
"tracking_field.computercraft.server_count.name": "Antal serveruppgifter",
"tracking_field.computercraft.max.name": "Max tid",
"tracking_field.computercraft.average.name": "Genomsnittlig tid",
"tracking_field.computercraft.total.name": "Total tid",
"tracking_field.computercraft.tasks.name": "Uppgifter",
"argument.computercraft.argument_expected": "Argument förväntas",
"argument.computercraft.tracking_field.no_field": "Okänt fält '%s'",
"argument.computercraft.computer.many_matching": "Flera datorer matchar '%s' (%s träffar)",
"argument.computercraft.computer.no_matching": "Inga datorer matchar '%s'",
"commands.computercraft.generic.additional_rows": "%d ytterligare rader…",
"commands.computercraft.generic.exception": "Ohanterat felfall (%s)",
"commands.computercraft.generic.no": "N",
"commands.computercraft.generic.yes": "J",
"commands.computercraft.generic.position": "%s, %s, %s",
"commands.computercraft.generic.no_position": "<no pos>",
"commands.computercraft.queue.desc": "Skicka ett computer_command event till en kommandodator, skicka vidare ytterligare argument. Detta är mestadels utformat för kartmarkörer som fungerar som en mer datorvänlig version av /trigger. Alla spelare kan köra kommandot, vilket sannolikt skulle göras genom en textkomponents klick-event.",
"commands.computercraft.queue.synopsis": "Skicka ett computer_command event till en kommandodator",
"commands.computercraft.reload.done": "Konfiguration omladdad",
"commands.computercraft.reload.desc": "Ladda om ComputerCrafts konfigurationsfil",
"commands.computercraft.reload.synopsis": "Ladda om ComputerCrafts konfigurationsfil",
"commands.computercraft.track.dump.computer": "Dator",
"commands.computercraft.track.dump.no_timings": "Inga tidtagningar tillgängliga",
"commands.computercraft.track.dump.desc": "Dumpa de senaste resultaten av datorspårning.",
"commands.computercraft.track.dump.synopsis": "Dumpa de senaste spårningsresultaten",
"commands.computercraft.track.stop.not_enabled": "Spårar för tillfället inga datorer",
"commands.computercraft.track.stop.action": "Klicka för att stoppa spårning",
"commands.computercraft.track.stop.desc": "Stoppa spårning av alla datorers körtider och eventräkningar",
"commands.computercraft.track.stop.synopsis": "Stoppa spårning för alla datorer",
"commands.computercraft.track.start.stop": "Kör %s för att stoppa spårning och visa resultaten",
"commands.computercraft.track.start.desc": "Börja spåra alla dators körtider och eventräkningar. Detta kommer återställa resultaten från tidigare körningar.",
"commands.computercraft.track.start.synopsis": "Starta spårning för alla datorer",
"commands.computercraft.track.desc": "Spåra hur länge datorer exekverar, och även hur många event de hanterar. Detta presenterar information på liknande sätt som /forge track och kan vara användbart för att undersöka lagg.",
"commands.computercraft.track.synopsis": "Spåra körningstider för denna dator.",
"commands.computercraft.view.not_player": "Kan inte öppna terminalen för en ickespelare",
"commands.computercraft.view.action": "Titta på denna dator",
"commands.computercraft.view.desc": "Öppna datorns terminal för att möjligöra fjärrstyrning. Detta ger inte tillgång till turtlens inventory. Du kan ange en dators instans-id (t.ex. 123) eller dator-id (t.ex. #123).",
"commands.computercraft.view.synopsis": "Titta på datorns terminal.",
"commands.computercraft.tp.not_there": "Kan inte hitta datorn i världen",
"commands.computercraft.tp.not_player": "Kan inte öppna terminalen för en ickespelare",
"commands.computercraft.tp.action": "Teleportera till den här datorn",
"commands.computercraft.tp.desc": "Teleportera till datorns position. Du kan ange en dators instans-id (t.ex. 123), dator-id (t.ex. #123) eller etikett (t.ex. \"@Min dator\").",
"commands.computercraft.tp.synopsis": "Teleportera till en specifik dator.",
"commands.computercraft.turn_on.done": "Startade %s/%s datorer",
"commands.computercraft.turn_on.desc": "Starta de listade datorerna eller alla om ingen anges. Du kan ange en dators instans-id (t.ex. 123), dator-id (t.ex. #123) eller etikett (t.ex. \"@Min dator\").",
"commands.computercraft.turn_on.synopsis": "Starta på datorer på distans.",
"commands.computercraft.shutdown.done": "Stängde av %s/%s datorer",
"commands.computercraft.dump.desc": "Visa status för alla datorer eller specifik information för en dator. Du kan ange en dators instans-id (t.ex. 123), dator-id (t.ex. #123) eller etikett (t.ex. \"@Min dator\").",
"commands.computercraft.shutdown.desc": "Stäng av de listade datorerna eller alla om ingen anges. Du kan ange en dators instans-id (t.ex. 123), dator-id (t.ex. #123) eller etikett (t.ex. \"@Min dator\").",
"commands.computercraft.shutdown.synopsis": "Stäng av datorer på distans.",
"commands.computercraft.dump.action": "Visa mer information om den här datorn",
"commands.computercraft.dump.synopsis": "Visa status för datorer.",
"commands.computercraft.help.no_command": "Inget sådant kommando '%s'",
"commands.computercraft.help.no_children": "%s har inget underkommando",
"commands.computercraft.help.desc": "Visa detta hjälpmeddelande",
"commands.computercraft.help.synopsis": "Tillhandahåll hjälp för ett specifikt kommando",
"commands.computercraft.desc": "/computercraft kommandot tillhandahåller olika debugging- och administrationsverktyg för att kontrollera och interagera med datorer.",
"commands.computercraft.synopsis": "Olika kommandon för att kontrollera datorer.",
"itemGroup.computercraft": "ComputerCraft"
}

View File

@@ -0,0 +1,48 @@
{
"gui.computercraft.tooltip.disk_id": "ID của đĩa: %s",
"upgrade.computercraft.speaker.adjective": "Ồn ào",
"upgrade.computercraft.wireless_modem_advanced.adjective": "Ender",
"upgrade.computercraft.wireless_modem_normal.adjective": "Không dây",
"upgrade.minecraft.crafting_table.adjective": "Chế tạo",
"upgrade.minecraft.diamond_hoe.adjective": "Trồng trọt",
"upgrade.minecraft.diamond_axe.adjective": "Đốn",
"upgrade.minecraft.diamond_pickaxe.adjective": "Khai thác",
"upgrade.minecraft.diamond_shovel.adjective": "Đào",
"item.computercraft.pocket_computer_advanced.upgraded": "Máy tính bỏ túi tiên tiến %s",
"item.computercraft.pocket_computer_advanced": "Máy tính bỏ túi tiên tiến",
"item.computercraft.pocket_computer_normal.upgraded": "Máy tính bỏ túi %s",
"item.computercraft.pocket_computer_normal": "Máy tính bỏ túi",
"item.computercraft.printed_book": "Sách in",
"item.computercraft.printed_page": "Trang in",
"item.computercraft.treasure_disk": "Đĩa mềm",
"item.computercraft.disk": "Đĩa mềm",
"block.computercraft.turtle_advanced.upgraded_twice": "Rùa tiên tiến %s %s",
"block.computercraft.turtle_advanced.upgraded": "Rùa tiên tiến %s",
"block.computercraft.turtle_advanced": "Rùa tiên tiến",
"block.computercraft.turtle_normal.upgraded_twice": "Rùa %s %s",
"block.computercraft.turtle_normal.upgraded": "Rùa %s",
"block.computercraft.turtle_normal": "Rùa",
"block.computercraft.wired_modem_full": "Modem có dây",
"block.computercraft.cable": "Dây cáp mạng",
"block.computercraft.wired_modem": "Modem có dây",
"block.computercraft.wireless_modem_advanced": "Modem Ender",
"block.computercraft.wireless_modem_normal": "Modem không dây",
"block.computercraft.monitor_advanced": "Màn hình tiên tiếng",
"block.computercraft.monitor_normal": "Màn hình",
"block.computercraft.speaker": "Loa",
"block.computercraft.printer": "Máy in",
"block.computercraft.disk_drive": "Ỗ đĩa",
"block.computercraft.computer_command": "Máy tính điều khiển",
"block.computercraft.computer_normal": "Máy tính",
"itemGroup.computercraft": "ComputerCraft",
"block.computercraft.computer_advanced": "Máy tính tiên tiến",
"tracking_field.computercraft.websocket_incoming.name": "Websocket đến",
"tracking_field.computercraft.websocket_outgoing.name": "Websocket đi",
"gui.computercraft.tooltip.computer_id": "ID của máy tính: %s",
"tracking_field.computercraft.coroutines_dead.name": "Coroutine bỏ đi",
"tracking_field.computercraft.coroutines_created.name": "Coroutine đã tạo",
"tracking_field.computercraft.http_download.name": "HTTP tải xuống",
"tracking_field.computercraft.http_upload.name": "HTTP tải lên",
"tracking_field.computercraft.http.name": "Yêu cầu HTTP",
"gui.computercraft.tooltip.copy": "Sao chép vào clipboard"
}

View File

@@ -6,7 +6,7 @@
uniform sampler2D u_font;
uniform int u_width;
uniform int u_height;
uniform samplerBuffer u_tbo;
uniform usamplerBuffer u_tbo;
uniform vec3 u_palette[16];
in vec2 f_pos;
@@ -30,9 +30,9 @@ void main() {
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);
int character = int(texelFetch(u_tbo, index).r);
int fg = int(texelFetch(u_tbo, index + 1).r);
int bg = int(texelFetch(u_tbo, index + 2).r);
vec2 pos = (term_pos - corner) * vec2(FONT_WIDTH, FONT_HEIGHT);
vec4 img = texture(u_font, (texture_corner(character) + pos) / 256.0);

View File

@@ -1,15 +1,137 @@
--- The Colors API allows you to manipulate sets of colors.
--
-- This is useful in conjunction with Bundled Cables from the RedPower mod,
-- RedNet Cables from the MineFactory Reloaded mod, and colors on Advanced
-- Computers and Advanced Monitors.
--
-- For the non-American English version just replace @{colors} with @{colours}
-- and it will use the other API, colours which is exactly the same, except in
-- British English (e.g. @{colors.gray} is spelt @{colours.grey}).
--
-- @see colours
-- @module colors
--[[- The Colors API allows you to manipulate sets of colors.
This is useful in conjunction with Bundled Cables from the RedPower mod, RedNet
Cables from the MineFactory Reloaded mod, and colors on Advanced Computers and
Advanced Monitors.
For the non-American English version just replace @{colors} with @{colours} and
it will use the other API, colours which is exactly the same, except in British
English (e.g. @{colors.gray} is spelt @{colours.grey}).
On basic terminals (such as the Computer and Monitor), all the colors are
converted to grayscale. This means you can still use all 16 colors on the
screen, but they will appear as the nearest tint of gray. You can check if a
terminal supports color by using the function @{term.isColor}.
Grayscale colors are calculated by taking the average of the three components,
i.e. `(red + green + blue) / 3`.
<table class="pretty-table">
<thead>
<tr><th colspan="8" align="center">Default Colors</th></tr>
<tr>
<th rowspan="2" align="center">Color</th>
<th colspan="3" align="center">Value</th>
<th colspan="4" align="center">Default Palette Color</th>
</tr>
<tr>
<th>Dec</th><th>Hex</th><th>Paint/Blit</th>
<th>Preview</th><th>Hex</th><th>RGB</th><th>Grayscale</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>colors.white</code></td>
<td align="right">1</td><td align="right">0x1</td><td align="right">0</td>
<td style="background:#F0F0F0"></td><td>#F0F0F0</td><td>240, 240, 240</td>
<td style="background:#F0F0F0"></td>
</tr>
<tr>
<td><code>colors.orange</code></td>
<td align="right">2</td><td align="right">0x2</td><td align="right">1</td>
<td style="background:#F2B233"></td><td>#F2B233</td><td>242, 178, 51</td>
<td style="background:#9D9D9D"></td>
</tr>
<tr>
<td><code>colors.magenta</code></td>
<td align="right">4</td><td align="right">0x4</td><td align="right">2</td>
<td style="background:#E57FD8"></td><td>#E57FD8</td><td>229, 127, 216</td>
<td style="background:#BEBEBE"></td>
</tr>
<tr>
<td><code>colors.lightBlue</code></td>
<td align="right">8</td><td align="right">0x8</td><td align="right">3</td>
<td style="background:#99B2F2"></td><td>#99B2F2</td><td>153, 178, 242</td>
<td style="background:#BFBFBF"></td>
</tr>
<tr>
<td><code>colors.yellow</code></td>
<td align="right">16</td><td align="right">0x10</td><td align="right">4</td>
<td style="background:#DEDE6C"></td><td>#DEDE6C</td><td>222, 222, 108</td>
<td style="background:#B8B8B8"></td>
</tr>
<tr>
<td><code>colors.lime</code></td>
<td align="right">32</td><td align="right">0x20</td><td align="right">5</td>
<td style="background:#7FCC19"></td><td>#7FCC19</td><td>127, 204, 25</td>
<td style="background:#767676"></td>
</tr>
<tr>
<td><code>colors.pink</code></td>
<td align="right">64</td><td align="right">0x40</td><td align="right">6</td>
<td style="background:#F2B2CC"></td><td>#F2B2CC</td><td>242, 178, 204</td>
<td style="background:#D0D0D0"></td>
</tr>
<tr>
<td><code>colors.gray</code></td>
<td align="right">128</td><td align="right">0x80</td><td align="right">7</td>
<td style="background:#4C4C4C"></td><td>#4C4C4C</td><td>76, 76, 76</td>
<td style="background:#4C4C4C"></td>
</tr>
<tr>
<td><code>colors.lightGray</code></td>
<td align="right">256</td><td align="right">0x100</td><td align="right">8</td>
<td style="background:#999999"></td><td>#999999</td><td>153, 153, 153</td>
<td style="background:#999999"></td>
</tr>
<tr>
<td><code>colors.cyan</code></td>
<td align="right">512</td><td align="right">0x200</td><td align="right">9</td>
<td style="background:#4C99B2"></td><td>#4C99B2</td><td>76, 153, 178</td>
<td style="background:#878787"></td>
</tr>
<tr>
<td><code>colors.purple</code></td>
<td align="right">1024</td><td align="right">0x400</td><td align="right">a</td>
<td style="background:#B266E5"></td><td>#B266E5</td><td>178, 102, 229</td>
<td style="background:#A9A9A9"></td>
</tr>
<tr>
<td><code>colors.blue</code></td>
<td align="right">2048</td><td align="right">0x800</td><td align="right">b</td>
<td style="background:#3366CC"></td><td>#3366CC</td><td>51, 102, 204</td>
<td style="background:#777777"></td>
</tr>
<tr>
<td><code>colors.brown</code></td>
<td align="right">4096</td><td align="right">0x1000</td><td align="right">c</td>
<td style="background:#7F664C"></td><td>#7F664C</td><td>127, 102, 76</td>
<td style="background:#656565"></td>
</tr>
<tr>
<td><code>colors.green</code></td>
<td align="right">8192</td><td align="right">0x2000</td><td align="right">d</td>
<td style="background:#57A64E"></td><td>#57A64E</td><td>87, 166, 78</td>
<td style="background:#6E6E6E"></td>
</tr>
<tr>
<td><code>colors.red</code></td>
<td align="right">16384</td><td align="right">0x4000</td><td align="right">e</td>
<td style="background:#CC4C4C"></td><td>#CC4C4C</td><td>204, 76, 76</td>
<td style="background:#767676"></td>
</tr>
<tr>
<td><code>colors.black</code></td>
<td align="right">32768</td><td align="right">0x8000</td><td align="right">f</td>
<td style="background:#111111"></td><td>#111111</td><td>17, 17, 17</td>
<td style="background:#111111"></td>
</tr>
</tbody>
</table>
@see colours
@module colors
]]
local expect = dofile("rom/modules/main/cc/expect.lua").expect
@@ -37,7 +159,7 @@ yellow = 0x10
-- terminal colour of #7FCC19.
lime = 0x20
--- Pink. Written as `6` in paint files and @{term.blit}, has a default
--- Pink: Written as `6` in paint files and @{term.blit}, has a default
-- terminal colour of #F2B2CC.
pink = 0x40
@@ -74,10 +196,11 @@ green = 0x2000
red = 0x4000
--- Black: Written as `f` in paint files and @{term.blit}, has a default
-- terminal colour of #191919.
-- terminal colour of #111111.
black = 0x8000
--- Combines a set of colors (or sets of colors) into a larger set.
--- Combines a set of colors (or sets of colors) into a larger set. Useful for
-- Bundled Cables.
--
-- @tparam number ... The colors to combine.
-- @treturn number The union of the color sets given in `...`
@@ -96,7 +219,8 @@ function combine(...)
return r
end
--- Removes one or more colors (or sets of colors) from an initial set.
--- Removes one or more colors (or sets of colors) from an initial set. Useful
-- for Bundled Cables.
--
-- Each parameter beyond the first may be a single color or may be a set of
-- colors (in the latter case, all colors in the set are removed from the
@@ -121,7 +245,8 @@ function subtract(colors, ...)
return r
end
--- Tests whether `color` is contained within `colors`.
--- Tests whether `color` is contained within `colors`. Useful for Bundled
-- Cables.
--
-- @tparam number colors A color, or color set
-- @tparam number color A color or set of colors that `colors` should contain.
@@ -207,3 +332,21 @@ function rgb8(r, g, b)
return packRGB(r, g, b)
end
end
-- Colour to hex lookup table for toBlit
local color_hex_lookup = {}
for i = 0, 15 do
color_hex_lookup[2 ^ i] = string.format("%x", i)
end
--- Converts the given color to a paint/blit hex character (0-9a-f).
--
-- This is equivalent to converting floor(log_2(color)) to hexadecimal.
--
-- @tparam number color The color to convert.
-- @treturn string The blit hex code of the color.
function toBlit(color)
expect(1, color, "number")
return color_hex_lookup[color] or
string.format("%x", math.floor(math.log(color) / math.log(2)))
end

View File

@@ -289,7 +289,7 @@ end
-- The `mode` string can be any of the following:
-- - **"r"**: Read mode
-- - **"w"**: Write mode
-- - **"w"**: Append mode
-- - **"a"**: Append mode
--
-- The mode may also have a `b` at the end, which opens the file in "binary
-- mode". This allows you to read binary files, as well as seek within a file.

View File

@@ -23,6 +23,25 @@ local function parseLine(tImageArg, sLine)
table.insert(tImageArg, tLine)
end
-- Sorts pairs of startX/startY/endX/endY such that the start is always the min
local function sortCoords(startX, startY, endX, endY)
local minX, maxX, minY, maxY
if startX <= endX then
minX, maxX = startX, endX
else
minX, maxX = endX, startX
end
if startY <= endY then
minY, maxY = startY, endY
else
minY, maxY = endY, startY
end
return minX, maxX, minY, maxY
end
--- Parses an image from a multi-line string
--
-- @tparam string image The string containing the raw-image data.
@@ -71,9 +90,6 @@ function drawPixel(xPos, yPos, colour)
expect(2, yPos, "number")
expect(3, colour, "number", "nil")
if type(xPos) ~= "number" then error("bad argument #1 (expected number, got " .. type(xPos) .. ")", 2) end
if type(yPos) ~= "number" then error("bad argument #2 (expected number, got " .. type(yPos) .. ")", 2) end
if colour ~= nil and type(colour) ~= "number" then error("bad argument #3 (expected number, got " .. type(colour) .. ")", 2) end
if colour then
term.setBackgroundColor(colour)
end
@@ -111,17 +127,7 @@ function drawLine(startX, startY, endX, endY, colour)
return
end
local minX = math.min(startX, endX)
local maxX, minY, maxY
if minX == startX then
minY = startY
maxX = endX
maxY = endY
else
minY = endY
maxX = startX
maxY = startY
end
local minX, maxX, minY, maxY = sortCoords(startX, startY, endX, endY)
-- TODO: clip to screen rectangle?
@@ -177,37 +183,33 @@ function drawBox(startX, startY, endX, endY, nColour)
endY = math.floor(endY)
if nColour then
term.setBackgroundColor(nColour)
term.setBackgroundColor(nColour) -- Maintain legacy behaviour
else
nColour = term.getBackgroundColour()
end
local colourHex = colours.toBlit(nColour)
if startX == endX and startY == endY then
drawPixelInternal(startX, startY)
return
end
local minX = math.min(startX, endX)
local maxX, minY, maxY
if minX == startX then
minY = startY
maxX = endX
maxY = endY
else
minY = endY
maxX = startX
maxY = startY
end
local minX, maxX, minY, maxY = sortCoords(startX, startY, endX, endY)
local width = maxX - minX + 1
for x = minX, maxX do
drawPixelInternal(x, minY)
drawPixelInternal(x, maxY)
end
if maxY - minY >= 2 then
for y = minY + 1, maxY - 1 do
drawPixelInternal(minX, y)
drawPixelInternal(maxX, y)
for y = minY, maxY do
if y == minY or y == maxY then
term.setCursorPos(minX, y)
term.blit((" "):rep(width), colourHex:rep(width), colourHex:rep(width))
else
term.setCursorPos(minX, y)
term.blit(" ", colourHex, colourHex)
term.setCursorPos(maxX, y)
term.blit(" ", colourHex, colourHex)
end
end
end
--- Draws a filled box on the current term from the specified start position to
-- the specified end position.
--
@@ -233,29 +235,23 @@ function drawFilledBox(startX, startY, endX, endY, nColour)
endY = math.floor(endY)
if nColour then
term.setBackgroundColor(nColour)
term.setBackgroundColor(nColour) -- Maintain legacy behaviour
else
nColour = term.getBackgroundColour()
end
local colourHex = colours.toBlit(nColour)
if startX == endX and startY == endY then
drawPixelInternal(startX, startY)
return
end
local minX = math.min(startX, endX)
local maxX, minY, maxY
if minX == startX then
minY = startY
maxX = endX
maxY = endY
else
minY = endY
maxX = startX
maxY = startY
end
local minX, maxX, minY, maxY = sortCoords(startX, startY, endX, endY)
local width = maxX - minX + 1
for x = minX, maxX do
for y = minY, maxY do
drawPixelInternal(x, y)
end
for y = minY, maxY do
term.setCursorPos(minX, y)
term.blit((" "):rep(width), colourHex:rep(width), colourHex:rep(width))
end
end

View File

@@ -432,7 +432,7 @@ do
--- Skip any whitespace
local function skip(str, pos)
local _, last = find(str, "^[ \n\r\v]+", pos)
local _, last = find(str, "^[ \n\r\t]+", pos)
if last then return last + 1 else return pos end
end
@@ -453,13 +453,13 @@ do
error_at(pos, "Unexpected %s, expected %s.", actual, exp)
end
local function parse_string(str, pos)
local function parse_string(str, pos, terminate)
local buf, n = {}, 1
while true do
local c = sub(str, pos, pos)
if c == "" then error_at(pos, "Unexpected end of input, expected '\"'.") end
if c == '"' then break end
if c == terminate then break end
if c == '\\' then
-- Handle the various escapes
@@ -472,7 +472,7 @@ do
buf[n], n, pos = utf8.char(tonumber(num_str, 16)), n + 1, pos + 6
else
local unesc = escapes[c]
if not unesc then error_at(pos + 1, "Unknown escape character %q.", unesc) end
if not unesc then error_at(pos + 1, "Unknown escape character %q.", c) end
buf[n], n, pos = unesc, n + 1, pos + 2
end
elseif c >= '\x20' then
@@ -485,13 +485,13 @@ do
return concat(buf, "", 1, n - 1), pos + 1
end
local valid = { b = true, B = true, s = true, S = true, l = true, L = true, f = true, F = true, d = true, D = true }
local num_types = { b = true, B = true, s = true, S = true, l = true, L = true, f = true, F = true, d = true, D = true }
local function parse_number(str, pos, opts)
local _, last, num_str = find(str, '^(-?%d+%.?%d*[eE]?[+-]?%d*)', pos)
local val = tonumber(num_str)
if not val then error_at(pos, "Malformed number %q.", num_str) end
if opts.nbt_style and valid[sub(str, pos + 1, pos + 1)] then return val, last + 2 end
if opts.nbt_style and num_types[sub(str, last + 1, last + 1)] then return val, last + 2 end
return val, last + 1
end
@@ -501,9 +501,11 @@ do
return val, last + 1
end
local arr_types = { I = true, L = true, B = true }
local function decode_impl(str, pos, opts)
local c = sub(str, pos, pos)
if c == '"' then return parse_string(str, pos + 1)
if c == '"' then return parse_string(str, pos + 1, '"')
elseif c == "'" and opts.nbt_style then return parse_string(str, pos + 1, "\'")
elseif c == "-" or c >= "0" and c <= "9" then return parse_number(str, pos, opts)
elseif c == "t" then
if sub(str, pos + 1, pos + 3) == "rue" then return true, pos + 4 end
@@ -528,7 +530,7 @@ do
while true do
local key, value
if c == "\"" then key, pos = parse_string(str, pos + 1)
if c == "\"" then key, pos = parse_string(str, pos + 1, "\"")
elseif opts.nbt_style then key, pos = parse_ident(str, pos)
else return expected(pos, c, "object key")
end
@@ -560,6 +562,11 @@ do
pos = skip(str, pos + 1)
c = sub(str, pos, pos)
if arr_types[c] and sub(str, pos + 1, pos + 1) == ";" and opts.nbt_style then
pos = skip(str, pos + 2)
c = sub(str, pos, pos)
end
if c == "" then return expected(pos, c, "']'") end
if c == "]" then return empty_json_array, pos + 1 end

View File

@@ -440,7 +440,7 @@ function create(parent, nX, nY, nWidth, nHeight, bStartVisible)
end
--- Get the buffered contents of a line in this window.
---
--
-- @tparam number y The y position of the line to get.
-- @treturn string The textual content of this line.
-- @treturn string The text colours of this line, suitable for use with @{term.blit}.
@@ -474,6 +474,14 @@ function create(parent, nX, nY, nWidth, nHeight, bStartVisible)
end
end
--- Get whether this window is visible. Invisible windows will not be
-- drawn to the screen until they are made visible again.
--
-- @treturn boolean Whether this window is visible.
-- @see Window:setVisible
function window.isVisible()
return bVisible
end
--- Draw this window. This does nothing if the window is not visible.
--
-- @see Window:setVisible

View File

@@ -1,3 +1,41 @@
# New features in CC: Tweaked 1.94.0
* Add getter for window visibility (devomaa)
* Generic peripherals are no longer experimental, and on by default.
* Use term.blit to draw boxes in paintutils (Lemmmy).
And several bug fixes:
* Fix turtles not getting advancements when turtles are on.
* Draw in-hand pocket computers with the correct transparent flags enabled.
* Several bug fixes to SNBT parsing.
* Fix several programs using their original name instead of aliases in usage hints (Lupus590).
# New features in CC: Tweaked 1.93.1
* Various documentation improvements (Lemmmy).
* Fix TBO monitor renderer on some older graphics cards (Lemmmy).
# New features in CC: Tweaked 1.93.0
* Update Swedish translations (Granddave).
* Printers use item tags to check dyes.
* HTTP rules may now be targetted for a specific port.
* Don't propagate adjacent redstone signals through computers.
And several bug fixes:
* Fix NPEs when turtles interact with containers.
# New features in CC: Tweaked 1.92.0
* Bump Cobalt version:
* Add support for the __pairs metamethod.
* string.format now uses the __tostring metamethod.
* Add date-specific MOTDs (MCJack123).
And several bug fixes:
* Correctly handle tabs within textutils.unserailizeJSON.
* Fix sheep not dropping items when sheared by turtles.
# New features in CC: Tweaked 1.91.1
* Fix crash when turtles interact with an entity.
@@ -48,8 +86,6 @@ And several bug fixes:
* Fix deadlock when mistakenly "watching" an unloaded chunk.
* Fix full path of files being leaked in some errors.
Type "help changelog" to see the full version history.
# New features in CC: Tweaked 1.89.1
* Fix crashes when rendering monitors of varying sizes.

View File

@@ -1,5 +1,13 @@
New features in CC: Tweaked 1.91.1
New features in CC: Tweaked 1.94.0
* Fix crash when turtles interact with an entity.
* Add getter for window visibility (devomaa)
* Generic peripherals are no longer experimental, and on by default.
* Use term.blit to draw boxes in paintutils (Lemmmy).
And several bug fixes:
* Fix turtles not getting advancements when turtles are on.
* Draw in-hand pocket computers with the correct transparent flags enabled.
* Several bug fixes to SNBT parsing.
* Fix several programs using their original name instead of aliases in usage hints (Lupus590).
Type "help changelog" to see the full version history.

View File

@@ -13,7 +13,7 @@
-- @module cc.pretty
-- @usage Print a table to the terminal
-- local pretty = require "cc.pretty"
-- pretty.write(pretty.dump({ 1, 2, 3 }))
-- pretty.write(pretty.pretty({ 1, 2, 3 }))
--
-- @usage Build a custom document and display it
-- local pretty = require "cc.pretty"

View File

@@ -1,6 +1,7 @@
local tArgs = { ... }
if #tArgs > 2 then
print("Usage: alias <alias> <program>")
local programName = arg[0] or fs.getName(shell.getRunningProgram())
print("Usage: " .. programName .. " <alias> <program>")
return
end

View File

@@ -1,6 +1,7 @@
local tArgs = { ... }
if #tArgs < 1 then
print("Usage: cd <path>")
local programName = arg[0] or fs.getName(shell.getRunningProgram())
print("Usage: " .. programName .. " <path>")
return
end

View File

@@ -4,7 +4,8 @@ if not commands then
return
end
if #tArgs == 0 then
printError("Usage: exec <command>")
local programName = arg[0] or fs.getName(shell.getRunningProgram())
printError("Usage: " .. programName .. " <command>")
return
end

View File

@@ -1,6 +1,7 @@
local tArgs = { ... }
if #tArgs < 2 then
print("Usage: cp <source> <destination>")
local programName = arg[0] or fs.getName(shell.getRunningProgram())
print("Usage: " .. programName .. " <source> <destination>")
return
end

View File

@@ -1,7 +1,8 @@
local args = table.pack(...)
if args.n < 1 then
print("Usage: rm <paths>")
local programName = arg[0] or fs.getName(shell.getRunningProgram())
print("Usage: " .. programName .. " <paths>")
return
end

View File

@@ -1,7 +1,8 @@
-- Get file to edit
local tArgs = { ... }
if #tArgs == 0 then
print("Usage: edit <path>")
local programName = arg[0] or fs.getName(shell.getRunningProgram())
print("Usage: " .. programName .. " <path>")
return
end

View File

@@ -1,7 +1,8 @@
-- Get arguments
local tArgs = { ... }
if #tArgs == 0 then
print("Usage: eject <drive>")
local programName = arg[0] or fs.getName(shell.getRunningProgram())
print("Usage: " .. programName .. " <drive>")
return
end

View File

@@ -34,7 +34,8 @@ end
-- Determines if the file exists, and can be edited on this computer
local tArgs = { ... }
if #tArgs == 0 then
print("Usage: paint <path>")
local programName = arg[0] or fs.getName(shell.getRunningProgram())
print("Usage: " .. programName .. " <path>")
return
end
local sPath = shell.resolve(tArgs[1])

View File

@@ -1,10 +1,11 @@
local tArgs = { ... }
local function printUsage()
local programName = arg[0] or fs.getName(shell.getRunningProgram())
print("Usages:")
print("dj play")
print("dj play <drive>")
print("dj stop")
print(programName .. " play")
print(programName .. " play <drive>")
print(programName .. " stop")
end
if #tArgs > 2 then

View File

@@ -1,8 +1,9 @@
local function printUsage()
local programName = arg[0] or fs.getName(shell.getRunningProgram())
print("Usages:")
print("gps host")
print("gps host <x> <y> <z>")
print("gps locate")
print(programName .. " host")
print(programName .. " host <x> <y> <z>")
print(programName .. " locate")
end
local tArgs = { ... }

View File

@@ -1,8 +1,9 @@
local function printUsage()
local programName = arg[0] or fs.getName(shell.getRunningProgram())
print("Usages:")
print("pastebin put <filename>")
print("pastebin get <code> <filename>")
print("pastebin run <code> <arguments>")
print(programName .. " put <filename>")
print(programName .. " get <code> <filename>")
print(programName .. " run <code> <arguments>")
end
local tArgs = { ... }

View File

@@ -1,7 +1,8 @@
local function printUsage()
local programName = arg[0] or fs.getName(shell.getRunningProgram())
print("Usage:")
print("wget <url> [filename]")
print("wget run <url>")
print(programName .. " <url> [filename]")
print(programName .. " run <url>")
end
local tArgs = { ... }

View File

@@ -1,11 +1,12 @@
local function printUsage()
local programName = arg[0] or fs.getName(shell.getRunningProgram())
print("Usages:")
print("label get")
print("label get <drive>")
print("label set <text>")
print("label set <drive> <text>")
print("label clear")
print("label clear <drive>")
print(programName .. " get")
print(programName .. " get <drive>")
print(programName .. " set <text>")
print(programName .. " set <drive> <text>")
print(programName .. " clear")
print(programName .. " clear <drive>")
end
local function checkDrive(sDrive)

View File

@@ -1,7 +1,8 @@
local tArgs = { ... }
if #tArgs < 1 then
print("Usage: mkdir <paths>")
local programName = arg[0] or fs.getName(shell.getRunningProgram())
print("Usage: " .. programName .. " <paths>")
return
end

View File

@@ -1,5 +1,6 @@
local function printUsage()
print("Usage: monitor <name> <program> <arguments>")
local programName = arg[0] or fs.getName(shell.getRunningProgram())
print("Usage: " .. programName .. " <name> <program> <arguments>")
return
end

View File

@@ -1,15 +1,24 @@
local tMotd = {}
local date = os.date("*t")
if date.month == 1 and date.day == 1 then
print("Happy new year!")
elseif date.month == 12 and date.day == 24 then
print("Merry X-mas!")
elseif date.month == 10 and date.day == 31 then
print("OOoooOOOoooo! Spooky!")
else
local tMotd = {}
for sPath in string.gmatch(settings.get("motd.path"), "[^:]+") do
if fs.exists(sPath) then
for sLine in io.lines(sPath) do
table.insert(tMotd, sLine)
for sPath in string.gmatch(settings.get("motd.path"), "[^:]+") do
if fs.exists(sPath) then
for sLine in io.lines(sPath) do
table.insert(tMotd, sLine)
end
end
end
end
if #tMotd == 0 then
print("missingno")
else
print(tMotd[math.random(1, #tMotd)])
if #tMotd == 0 then
print("missingno")
else
print(tMotd[math.random(1, #tMotd)])
end
end

View File

@@ -1,6 +1,7 @@
local tArgs = { ... }
if #tArgs < 2 then
print("Usage: mv <source> <destination>")
local programName = arg[0] or fs.getName(shell.getRunningProgram())
print("Usage: " .. programName .. " <source> <destination>")
return
end

View File

@@ -1,9 +1,10 @@
local tArgs = { ... }
local function printUsage()
local programName = arg[0] or fs.getName(shell.getRunningProgram())
print("Usages:")
print("chat host <hostname>")
print("chat join <hostname> <nickname>")
print(programName .. " host <hostname>")
print(programName .. " join <hostname> <nickname>")
end
local sOpenedModem = nil

View File

@@ -1,11 +1,12 @@
local tArgs = { ... }
local function printUsage()
local programName = arg[0] or fs.getName(shell.getRunningProgram())
print("Usages:")
print("redstone probe")
print("redstone set <side> <value>")
print("redstone set <side> <color> <value>")
print("redstone pulse <side> <count> <period>")
print(programName .. " probe")
print(programName .. " set <side> <value>")
print(programName .. " set <side> <color> <value>")
print(programName .. " pulse <side> <count> <period>")
end
local sCommand = tArgs[1]

View File

@@ -1,6 +1,7 @@
local tArgs = { ... }
if #tArgs < 2 then
print("Usage: rename <source> <destination>")
local programName = arg[0] or fs.getName(shell.getRunningProgram())
print("Usage: " .. programName .. " <source> <destination>")
return
end

View File

@@ -11,7 +11,8 @@ end
local tArgs = { ... }
local nLimit = nil
if #tArgs < 1 then
print("Usage: craft [number]")
local programName = arg[0] or fs.getName(shell.getRunningProgram())
print("Usage: " .. programName .. " [number]")
return
else
nLimit = tonumber(tArgs[1])

View File

@@ -5,7 +5,8 @@ end
local tArgs = { ... }
local function printUsage()
print("Usage: equip <slot> <side>")
local programName = arg[0] or fs.getName(shell.getRunningProgram())
print("Usage: " .. programName .. " <slot> <side>")
end
if #tArgs ~= 2 then

View File

@@ -5,7 +5,8 @@ end
local tArgs = { ... }
if #tArgs ~= 1 then
print("Usage: excavate <diameter>")
local programName = arg[0] or fs.getName(shell.getRunningProgram())
print("Usage: " .. programName .. " <diameter>")
return
end

View File

@@ -5,7 +5,8 @@ end
local tArgs = { ... }
if #tArgs < 1 then
print("Usage: go <direction> <distance>")
local programName = arg[0] or fs.getName(shell.getRunningProgram())
print("Usage: " .. programName .. " <direction> <distance>")
return
end

View File

@@ -6,7 +6,8 @@ end
local tArgs = { ... }
local nLimit = 1
if #tArgs > 1 then
print("Usage: refuel [number]")
local programName = arg[0] or fs.getName(shell.getRunningProgram())
print("Usage: " .. programName .. " [number]")
return
elseif #tArgs > 0 then
if tArgs[1] == "all" then

View File

@@ -5,7 +5,8 @@ end
local tArgs = { ... }
if #tArgs ~= 1 then
print("Usage: tunnel <length>")
local programName = arg[0] or fs.getName(shell.getRunningProgram())
print("Usage: " .. programName .. " <length>")
return
end

View File

@@ -5,7 +5,8 @@ end
local tArgs = { ... }
if #tArgs < 1 then
print("Usage: turn <direction> <turns>")
local programName = arg[0] or fs.getName(shell.getRunningProgram())
print("Usage: " .. programName .. " <direction> <turns>")
return
end

View File

@@ -5,7 +5,8 @@ end
local tArgs = { ... }
local function printUsage()
print("Usage: unequip <side>")
local programName = arg[0] or fs.getName(shell.getRunningProgram())
print("Usage: " .. programName .. " <side>")
end
if #tArgs ~= 1 then

View File

@@ -1,6 +1,7 @@
local tArgs = { ... }
if #tArgs < 1 then
print("Usage: type <path>")
local programName = arg[0] or fs.getName(shell.getRunningProgram())
print("Usage: " .. programName .. " <path>")
return
end

View File

@@ -0,0 +1,34 @@
/*
* 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.core.apis.http.options;
import org.junit.jupiter.api.Test;
import java.net.InetSocketAddress;
import java.util.Collections;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class AddressRuleTest
{
@Test
public void matchesPort()
{
Iterable<AddressRule> rules = Collections.singletonList( AddressRule.parse(
"127.0.0.1", 8080,
new PartialOptions( Action.ALLOW, null, null, null, null )
) );
assertEquals( apply( rules, "localhost", 8080 ).action, Action.ALLOW );
assertEquals( apply( rules, "localhost", 8081 ).action, Action.DENY );
}
private Options apply( Iterable<AddressRule> rules, String host, int port )
{
return AddressRule.apply( rules, host, new InetSocketAddress( host, port ) );
}
}

View File

@@ -0,0 +1 @@
[ ]

View File

@@ -73,4 +73,20 @@ describe("The colors library", function()
expect(colors.rgb8(0.3, 0.5, 0.6)):equals(0x4c7f99)
expect({ colors.rgb8(0x4c7f99) }):same { 0x4c / 0xFF, 0x7f / 0xFF, 0.6 }
end)
describe("colors.toBlit", function()
it("validates arguments", function()
expect.error(colors.toBlit, nil):eq("bad argument #1 (expected number, got nil)")
end)
it("converts all colors", function()
for i = 0, 15 do
expect(colors.toBlit(2 ^ i)):eq(string.format("%x", i))
end
end)
it("floors colors", function()
expect(colors.toBlit(16385)):eq("e")
end)
end)
end)

View File

@@ -1,4 +1,19 @@
local with_window = require "test_helpers".with_window
describe("The paintutils library", function()
-- Verifies that a window's lines are equal to the given table of blit
-- strings ({{"text", "fg", "bg"}, {"text", "fg", "bg"}...})
local function window_eq(w, state)
-- Verification of the size isn't really important in the tests, but
-- better safe than sorry.
local _, height = w.getSize()
expect(#state):eq(height)
for line = 1, height do
expect({ w.getLine(line) }):same(state[line])
end
end
describe("paintutils.parseImage", function()
it("validates arguments", function()
paintutils.parseImage("")
@@ -28,6 +43,30 @@ describe("The paintutils library", function()
expect.error(paintutils.drawLine, 1, 1, 1, nil):eq("bad argument #4 (expected number, got nil)")
expect.error(paintutils.drawLine, 1, 1, 1, 1, false):eq("bad argument #5 (expected number, got boolean)")
end)
it("draws a line going across with custom colour", function()
local w = with_window(3, 2, function()
paintutils.drawLine(1, 1, 3, 1, colours.red)
end)
window_eq(w, {
{ " ", "000", "eee" },
{ " ", "000", "fff" },
})
end)
it("draws a line going diagonally with term colour", function()
local w = with_window(3, 3, function()
term.setBackgroundColour(colours.red)
paintutils.drawLine(1, 1, 3, 3)
end)
window_eq(w, {
{ " ", "000", "eff" },
{ " ", "000", "fef" },
{ " ", "000", "ffe" },
})
end)
end)
describe("paintutils.drawBox", function()
@@ -38,6 +77,45 @@ describe("The paintutils library", function()
expect.error(paintutils.drawBox, 1, 1, 1, nil):eq("bad argument #4 (expected number, got nil)")
expect.error(paintutils.drawBox, 1, 1, 1, 1, false):eq("bad argument #5 (expected number, got boolean)")
end)
it("draws a box with term colour", function()
local w = with_window(3, 3, function()
term.setBackgroundColour(colours.red)
paintutils.drawBox(1, 1, 3, 3)
end)
window_eq(w, {
{ " ", "eee", "eee" },
{ " ", "e0e", "efe" },
{ " ", "eee", "eee" },
})
end)
it("draws a box with custom colour", function()
local w = with_window(3, 3, function()
paintutils.drawBox(1, 1, 3, 3, colours.red)
end)
window_eq(w, {
{ " ", "eee", "eee" },
{ " ", "e0e", "efe" },
{ " ", "eee", "eee" },
})
end)
it("draws a box without overwriting existing content", function()
local w = with_window(3, 3, function()
term.setCursorPos(2, 2)
term.write("a")
paintutils.drawBox(1, 1, 3, 3, colours.red)
end)
window_eq(w, {
{ " ", "eee", "eee" },
{ " a ", "e0e", "efe" },
{ " ", "eee", "eee" },
})
end)
end)
describe("paintutils.drawFilledBox", function()
@@ -48,6 +126,31 @@ describe("The paintutils library", function()
expect.error(paintutils.drawFilledBox, 1, 1, 1, nil):eq("bad argument #4 (expected number, got nil)")
expect.error(paintutils.drawFilledBox, 1, 1, 1, 1, false):eq("bad argument #5 (expected number, got boolean)")
end)
it("draws a filled box with term colour", function()
local w = with_window(3, 3, function()
term.setBackgroundColour(colours.red)
paintutils.drawFilledBox(1, 1, 3, 3)
end)
window_eq(w, {
{ " ", "eee", "eee" },
{ " ", "eee", "eee" },
{ " ", "eee", "eee" },
})
end)
it("draws a filled box with custom colour", function()
local w = with_window(3, 3, function()
paintutils.drawFilledBox(1, 1, 3, 3, colours.red)
end)
window_eq(w, {
{ " ", "eee", "eee" },
{ " ", "eee", "eee" },
{ " ", "eee", "eee" },
})
end)
end)
describe("paintutils.drawImage", function()

View File

@@ -126,12 +126,28 @@ describe("The textutils library", function()
end)
describe("parses using NBT-style syntax", function()
local function exp(x)
local res, err = textutils.unserializeJSON(x, { nbt_style = true })
if not res then error(err, 2) end
return expect(res)
end
it("basic objects", function()
expect(textutils.unserializeJSON([[{ a: 1, b:2 }]], { nbt_style = true })):same { a = 1, b = 2 }
exp([[{ a: 1, b:2 }]]):same { a = 1, b = 2 }
end)
it("suffixed numbers", function()
expect(textutils.unserializeJSON("1b", { nbt_style = true })):eq(1)
exp("1b"):eq(1)
exp("1.1d"):eq(1.1)
end)
it("strings", function()
exp("'123'"):eq("123")
exp("\"123\""):eq("123")
end)
it("typed arrays", function()
exp("[B; 1, 2, 3]"):same { 1, 2, 3 }
exp("[B;]"):same {}
end)
end)

View File

@@ -157,4 +157,17 @@ describe("The window library", function()
expect({ w.getLine(1) }):same { "test ", "aaaa0", "4444f" }
end)
end)
describe("Window.setVisible", function()
it("validates arguments", function()
local w = mk()
expect.error(w.setVisible, nil):eq("bad argument #1 (expected boolean, got nil)")
end)
end)
describe("Window.isVisible", function()
it("gets window visibility", function()
local w = mk()
w.setVisible(false)
expect(w.isVisible()):same(false)
end)
end)
end)

View File

@@ -10,7 +10,7 @@ describe("The exec program", function()
it("displays its usage when given no argument", function()
stub(_G, "commands", {})
expect(capture(stub, "/rom/programs/command/exec.lua"))
:matches { ok = true, output = "", error = "Usage: exec <command>\n" }
:matches { ok = true, output = "", error = "Usage: /rom/programs/command/exec.lua <command>\n" }
end)
it("runs a command", function()

Some files were not shown because too many files have changed in this diff Show More