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

Compare commits

..

93 Commits

Author SHA1 Message Date
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
SquidDev
26c12ac1a9 Bump version to 1.91.1 2020-09-04 17:29:35 +01:00
SquidDev
2c67849b35 Fix NPE when turtles interact with an entity
Closes #531
2020-08-27 17:17:03 +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
SquidDev
7809a2eddd Merge branch 'mc-1.15.x' into mc-1.16.x 2020-08-23 15:46:17 +01:00
SquidDev
183b342071 Bump for 1.91.0 2020-08-23 15:35:58 +01:00
SquidDev
0bb5515055 Fix checkstyle problems 2020-08-22 19:31:49 +01:00
SquidDev
e8e9294fdf Correctly check for success or consume
No, I don't really know what the difference is either :). Closes #518.
2020-08-22 19:28:02 +01:00
SquidDev
9acfc0316f Expose NBT hashes of items to users
This just uses the same approach as Plethora, so we should have aparity
for .list() now.
2020-08-22 16:09:35 +01:00
SquidDev
29fb0baa09 Use Forge's packet methods for sending SoundEvents
Doesn't fix #515 (arguably makes it worse in the sense that it's more
likely to throw). However it should provide better error reporting, and
make it more clear that it's not CC:T's fault.
2020-08-22 15:31:48 +01:00
R93950X
d5de39ebd4 Fix time formatting (#527)
Fixes #525.

Co-authored-by: R93950X <R93950X@users.noreply.github.com>
2020-08-22 15:17:12 +01:00
SquidDev
0faf76e4bd Fix if statement never being hit
Let's been honest, this bit's probably never been tested, because it
should never happen. Fixes #528.
2020-08-22 15:03:38 +01:00
SquidDev
99581e1f40 Initial update to 1.16.2
Seems to load fine, but not done any proper testing.
2020-08-14 22:00:03 +01:00
SquidDev
e8e2ed9fe5 Fix incorrect lower bound in mods.toml
It appears I had failed to update this when last bumping the Forge
version. Closes #521 - we're relying on a feature only added in Forge
31.1.16, and they're using 3.1.14.
2020-08-09 21:51:55 +01:00
SquidDev
9f72448ecd Properly deprecate colors.rgb8 2020-08-04 19:50:36 +01:00
SquidDev
3da3f16deb Fix link to logo 2020-08-04 18:30:22 +01:00
hydraz
0e2ce3c634 Make the key for mtime "modified" in fs.attributes (#512) 2020-07-31 18:39:09 +01:00
SquidDev
fe00e00537 Mention people should include logs 2020-07-31 18:31:47 +01:00
SquidDev
29646a7f61 Bump version to 1.90.3 2020-07-27 19:07:06 +01:00
SquidDev
50d2712581 Resolve CC's save location to the world dir
Fixes #509
2020-07-27 19:04:57 +01:00
SquidDev
3093f882d8 Fix selected slot now showing in the turtle GUI 2020-07-27 18:37:07 +01:00
SquidDev
e5cf0d1c61 Update mappings 2020-07-27 18:26:42 +01:00
Jonathan Coates
cd879b067f Merge pull request #508 from neumond/mc-1.15.x
Fix JSON serialization of strings
2020-07-25 17:51:46 +01:00
neumond
053cb1b53c Fix JSON serialization of strings
Control characters become escaped as JSON requires
Non-ASCII characters get escaped as well for better interoperability
We assume here that lua strings represent only first 256 code points of unicode
2020-07-25 19:40:06 +03:00
SquidDev
6b102a8142 Merge branch 'mc-1.15.x' into mc-1.16.x 2020-07-25 12:08:33 +01:00
SquidDev
ac7979fb46 Bump for 1.90.2 2020-07-25 11:53:46 +01:00
SquidDev
c8a6888a2f Fix styles not being saved
Styles have been changed to be immutable, meaning that we were never
updating them! Fixes #499.
2020-07-25 11:19:04 +01:00
SquidDev
9ce33f8a3f Add back missing override of getPositionVec
This was removed in the initial update (46595e73df)
because I got terribly confused over mappings and I forgot to add it
back.

Fixes #505
2020-07-25 10:56:50 +01:00
SquidDev
d51851e763 Use FML's scan data to gather annotations
We can just scrape them from the @AutoService annotation, which saves us
having to duplicate any work. Hopefully fixes #501, but I haven't tested
in a non-dev environment yet.
2020-07-23 22:41:20 +01:00
BlackDragon-B
fb70a1a998 Added Windows thing. (#500) 2020-07-18 18:59:52 +01:00
SquidDev
a1dcd59d95 Update to latest Forge
Fixes #498
2020-07-18 15:11:57 +01:00
SquidDev
2a17585702 Merge branch 'mc-1.15.x' into mc-1.16.x 2020-07-18 12:24:49 +01:00
SquidDev
2f323f23d7 Update changelog for release 2020-07-18 12:23:36 +01:00
SquidDev
087c305b0d Fix non-inventory GUIs rendering labels 2020-07-18 12:17:02 +01:00
SquidDev
31764f6d65 Register various gold items as piglin_loved 2020-07-18 11:14:55 +01:00
SquidDev
4efde2b294 Merge branch 'mc-1.15.x' into mc-1.16.x 2020-07-18 10:34:29 +01:00
SquidDev
95554a53d1 Move getResourceFile to CCAPIImpl
Just means we've got all the resource processing code in one place, and
keeps (most) MC code out of CC itself.
2020-07-18 10:31:28 +01:00
SquidDev
89c1b2771d Allow configuring max monitor render distance
64 blocks out to be enough for anyone. But just in case. Closes #494
2020-07-18 10:26:34 +01:00
SquidDev
8f069a9b72 Remove absolute file path from FS errors
When dealing with invalid paths (for instance, ones which are too long
or malformed), Java may throw a FileSystemException. This contains the
absolute path (i.e. C:/Users/Moi/.../.minecraft/...), which is printed
to the user within CC - obviously not ideal!

We simply catch this exception within the MountWrapper and map it back
to the local path. The disadvantage of doing it here is that we can't
map the path in the exception back to the computer - we'd need to catch
it in FileMount for that - so we just assume it referrs to the original
path instead.

Doing it in FileMount ends up being a little uglier, as we already do
all the exception wrangling in FileWrapper, so this'll do for now.

Fixes #495
2020-07-18 10:13:43 +01:00
SquidDev
2e9d6603e3 Correct IPeripheral documentation
It's no longer possible to implement this on the tile, due to the
conflict in getType. Given this is a really bad idea, it's not a big
issue, but we should mention it in the documentation.

Fixes #496.
2020-07-14 19:53:10 +01:00
SquidDev
46595e73df Initial update to Minecraft 1.16.1
A lot is broken, but at least we can get in game:
 - GUIs render a whole bunch of additional "inventory" text, which we
   really don't want.
 - Computers load from the wrong location.
 - There's some issues with using Forge's tags from outside of JSON
   recipes. We need to work out why.
2020-07-11 20:36:10 +01:00
SquidDev
a6a1b9b8e5 Add a whole tonne of documentation
There's a bit of duplication here, so we might try to clean this up, but
it's a good starting point.
2020-07-09 21:59:19 +01:00
SquidDev
3f277a7a7b Bump version to 1.90.0
Going to let this stew for a couple of days - there's probably something
else which'll break.
2020-07-06 15:38:09 +01:00
SquidDev
90c5d3f1e8 Don't load the chunk when watching monitors
Hopefully fixes #493
2020-07-06 15:21:14 +01:00
Naheulf
a5f7cf8334 Add enchantments and unbreakable to ItemData.java. (#488) 2020-07-06 14:18:07 +01:00
JackMacWindows
3075f89797 Added Javadoc for currently undocumented functions (#490)
This PR adds some documentation for APIs that did not have docs in the
source yet. This includes the:

* drive peripheral
* FS API
* OS PAI
* printer peripheral
* speaker peripheral
2020-07-05 08:26:37 +01:00
Weblate
45297665c6 Translations for Russian
Translations for French

Co-authored-by: neumond <alice.johnson@yandex.ru>
Co-authored-by: Naheulf <newheulf@gmail.com>
2020-07-05 03:41:59 +00:00
Jonathan Coates
ddbf3fc111 Merge pull request #491 from neumond/mc-1.15.x
Add port to Host http header if necessary
2020-07-04 21:48:20 +01:00
Weblate
da82b89676 Added translation for Russian
Co-authored-by: neumond <alice.johnson@yandex.ru>
2020-07-04 20:41:15 +00:00
neumond
d5f1a2c817 Add port to Host http header if necessary 2020-07-04 22:16:48 +03:00
SquidDev
6020adef6b Link to Weblate in CONTRIBUTING
Let's make it at least a little bit discoverable!
2020-07-04 10:17:40 +01:00
SquidDev
d2a52a8b5d Fix turtle.craft failing when missing an argument.
Stupid typo, stupid squid.
2020-07-03 21:37:14 +01:00
SquidDev
9f8774960f Generate documentation stubs from Javadocs
illuaminate does not handle Java files, for obvious reasons. In order to
get around that, we have a series of stub files within /doc/stub which
mirrored the Java ones. While this works, it has a few problems:

 - The link to source code does not work - it just links to the stub
   file.
 - There's no guarantee that documentation remains consistent with the
   Java code. This change found several methods which were incorrectly
   documented beforehand.

We now replace this with a custom Java doclet[1], which extracts doc
comments from @LuaFunction annotated methods and generates stub-files
from them. These also contain a @source annotation, which allows us to
correctly link them back to the original Java code.

There's some issues with this which have yet to be fixed. However, I
don't think any of them are major blockers right now:

 - The custom doclet relies on Java 9 - I think it's /technically/
   possible to do this on Java 8, but the API is significantly uglier.
   This means that we need to run javadoc on a separate JVM.

   This is possible, and it works locally and on CI, but is definitely
   not a nice approach.

 - illuaminate now requires the doc stubs to be generated in order for
   the linter to pass, which does make running the linter locally much
   harder (especially given the above bullet point).

   We could notionally include the generated stubs (or at least a cut
   down version of them) in the repo, but I'm not 100% sure about that.

[1]: https://docs.oracle.com/javase/9/docs/api/jdk/javadoc/doclet/package-summary.html
2020-07-03 13:31:26 +01:00
SquidDev
36bb8b67c9 Clean up data-gathering code
- Refer to this as "data" rather than "metadata". I'm still not sure
   where the meta came from - blame OpenPeripheral I guess.
 - Likewise, use getItemDetail within inventory methods, rather than
   getItemMeta.
 - Refactor common data-getting code into one class. This means that
   turtle.getItemDetail, turtle.inspect and commands.getBlockInfo all
   use the same code.
 - turtle.getItemDetail now accepts a second "detailed" parameter which
   will include the full metadata (#471, #452).
 - Tags are now only included in the detailed list. This is a breaking
   change, however should only affect one version (1.89.x) and I'm not
   convinced that the previous behaviour was safe.
2020-06-30 12:35:39 +01:00
SquidDev
8f3a56dd32 Merge branch 'mc-1.14.x' into mc-1.15.x 2020-06-30 11:31:41 +01:00
SquidDev
113d5d982f Merge branch 'master' into mc-1.14.x 2020-06-30 11:28:56 +01:00
SquidDev
37a447e745 Bump version to 1.89.2
Somewhat reluctant to do this, but it's a pretty major bug.
2020-06-30 11:10:26 +01:00
SquidDev
9e2232d240 Clean up entity drop code
We were incorrectly using captureDrops directly - it's more reasonable
to listen to the drop event. Fixes #486
2020-06-30 11:10:24 +01:00
Jonathan Coates
514db30fb1 Add configuration options to control terminal sizes (#475)
This allows for configuring the size of computers and pocket computers, 
as well as the max size of monitors.

There's several limitations with the current implementation, but it's
still "good enough" for an initial release:
 - Turtles cannot be resized.
 - GUIs do not scale themselves, so "large" sizes will not render within
   the default resolution.
2020-06-28 16:33:03 +01:00
Jonathan Coates
08181f72d4 Generic peripherals for any tile entities (#478)
This exposes a basic peripheral for any tile entity which does not have methods
already registered. We currently provide the following methods:

 - Inventories: size, list, getItemMeta, pushItems, pullItems.
 - Energy storage: getEnergy, getEnergyCapacity
 - Fluid tanks: tanks(), pushFluid, pullFluid.

These methods are currently experimental - it must be enabled through 
`experimental.generic_peripherals`. While this is an initial step towards
implementing #452, but is by no means complete.
2020-06-27 10:47:31 +01:00
SquidDev
613a28a5af Switch to Forge's DeferredRegister
Well, mostly. We currently don't do recipe serializers as I'm a little
too lazy. For items, blocks and TE types this does make registration
nicer - we've some helper functions which help reduce duplication.

Some types (containers, TEs, etc..) are a little less nice, as we now
must define the registry object (i.e. the WhateverType<?>) in a separate
class to the class it constructs. However, it's probably a worthwhile
price to pay.
2020-06-27 10:23:51 +01:00
Weblate
e4c422d6f9 Translations for German
Co-authored-by: Jummit <jummit@web.de>
2020-06-27 01:59:35 +00:00
Weblate
478f992dea Translations for German
Co-authored-by: Jummit <jummit@web.de>
2020-06-25 16:49:08 +00:00
JakobDev
b54519d0e6 Add functions for parsing and drawing nft (#458) 2020-06-25 09:08:35 +01:00
Jonathan Coates
9499654757 Add documentation for peripherals
No clue how we're going to do this for the dynamic peripheral system
if/when that ships, but this is a good first stage.

Like the Java APIs, this relies on stub files, so we can't link to the
implementation which is a bit of a shame. However, it's a good first
step.
2020-06-24 12:12:06 +01:00
SquidDev
c5138c535c Fix write method missing from printers
I'm really not very good at this modding lark am I? I've done a basic
search for other missing methods, and can't see anything, but goodness
knows.

Fixes #480
2020-06-23 10:01:44 +01:00
SquidDev
5bd8d84d14 Add missing config option for command computers
Fixes #479
2020-06-22 11:35:21 +01:00
Weblate
ab0310e27c Translations for Italian
Translations for French

Translations for French

Co-authored-by: hds <hds536jhmk@gmail.com>
Co-authored-by: Anavrins <xanavrins@gmail.com>
Co-authored-by: AxelFontarive <afontarive@gmail.com>
2020-06-21 16:42:35 +00:00
SquidDev
607751da40 Upload on all (active) mc-* branches 2020-06-21 13:24:47 +01:00
242 changed files with 5543 additions and 2369 deletions

View File

@@ -12,4 +12,5 @@ labels: bug
## Useful information to include:
- Minecraft version
- CC: Tweaked version
- Logs: These will be located in the `logs/` directory of your Minecraft instance. Please upload them as a gist or directly into this editor.
- Detailed reproduction steps: sometimes I can spot a bug pretty easily, but often it's much more obscure. The more information I have to help reproduce it, the quicker it'll get fixed.

View File

@@ -10,10 +10,10 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: Set up JDK 1.8
- name: Set up Java 8
uses: actions/setup-java@v1
with:
java-version: 1.8
java-version: 8
- name: Cache gradle dependencies
uses: actions/cache@v1
@@ -35,12 +35,8 @@ jobs:
- name: Upload Coverage
run: bash <(curl -s https://codecov.io/bash)
lint-lua:
name: Lint Lua
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Generate Java documentation stubs
run: ./gradlew luaJavadoc --no-daemon
- name: Lint Lua code
run: |

View File

@@ -2,7 +2,9 @@ name: Build documentation
on:
push:
branches: [ master ]
branches:
- master
- mc-1.15.x
tags:
release:
types: [ published ]
@@ -15,6 +17,25 @@ jobs:
steps:
- uses: actions/checkout@v1
- name: Set up Java 8
uses: actions/setup-java@v1
with:
java-version: 8
- name: Cache gradle dependencies
uses: actions/cache@v1
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('gradle.properties') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Build with Gradle
run: ./gradlew compileJava --no-daemon || ./gradlew compileJava --no-daemon
- name: Generate Java documentation stubs
run: ./gradlew luaJavadoc --no-daemon
- name: Build documentation
run: |
test -d bin || mkdir bin

1
.gitignore vendored
View File

@@ -4,6 +4,7 @@
/build
/out
/doc/**/*.html
/doc/javadoc/
/doc/index.json
# Runtime directories

View File

@@ -10,7 +10,7 @@ do use the issue templates - they provide a useful hint on what information to p
## Developing
In order to develop CC: Tweaked, you'll need to download the source code and then run it. This is a pretty simple
process.
process. When building on Windows, Use `gradlew.bat` instead of `./gradlew`.
- **Clone the repository:** `git clone https://github.com/SquidDev-CC/CC-Tweaked.git && cd CC-Tweaked`
- **Setup Forge:** `./gradlew build`
@@ -29,8 +29,13 @@ are run whenever you submit a PR, it's often useful to run this before committin
- **[illuaminate]:** Checks Lua code for semantic and styleistic issues. See [the usage section][illuaminate-usage] for
how to download and run it.
## Translations
Translations are managed through [Weblate], an online interface for managing language strings. This is synced
automatically with GitHub, so please don't submit PRs adding/changing translations!
[new-issue]: https://github.com/SquidDev-CC/CC-Tweaked/issues/new/choose "Create a new issue"
[community]: README.md#Community "Get in touch with the community."
[checkstyle]: https://checkstyle.org/
[illuaminate]: https://github.com/SquidDev/illuaminate/
[illuaminate-usage]: https://github.com/SquidDev/illuaminate/blob/master/README.md#usage
[weblate]: https://i18n.tweaked.cc/projects/cc-tweaked/minecraft/

View File

@@ -1,4 +1,4 @@
# ![CC: Tweaked](logo.png)
# ![CC: Tweaked](doc/logo.png)
[![Current build status](https://github.com/SquidDev-CC/CC-Tweaked/workflows/Build/badge.svg)](https://github.com/SquidDev-CC/CC-Tweaked/actions "Current build status") [![Download CC: Tweaked on CurseForge](http://cf.way2muchnoise.eu/title/cc-tweaked.svg)](https://minecraft.curseforge.com/projects/cc-tweaked "Download CC: Tweaked on CurseForge")
CC: Tweaked is a fork of [ComputerCraft](https://github.com/dan200/ComputerCraft), adding programmable computers,
@@ -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.169'
classpath 'net.minecraftforge.gradle:ForgeGradle:3.0.181'
classpath 'net.sf.proguard:proguard-gradle:6.1.0beta2'
classpath 'org.ajoberstar.grgit:grgit-gradle:3.0.0'
}
@@ -33,6 +33,8 @@ version = mod_version
group = "org.squiddev"
archivesBaseName = "cc-tweaked-${mc_version}"
sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.8'
minecraft {
runs {
client {
@@ -78,11 +80,14 @@ minecraft {
accessTransformer file('src/main/resources/META-INF/accesstransformer.cfg')
}
sourceSets.main.resources {
srcDir 'src/generated/resources'
sourceSets {
main.resources {
srcDir 'src/generated/resources'
}
}
repositories {
mavenCentral()
maven {
name "SquidDev"
url "https://squiddev.cc/maven"
@@ -93,6 +98,7 @@ configurations {
shade
compile.extendsFrom shade
deployerJars
cctJavadoc
}
dependencies {
@@ -103,7 +109,10 @@ dependencies {
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")
runtimeOnly fg.deobf("mezz.jei:jei-1.15.2:6.0.0.3")
// runtimeOnly fg.deobf("mezz.jei:jei-1.15.2:6.0.0.3")
compileOnly 'com.google.auto.service:auto-service:1.0-rc7'
annotationProcessor 'com.google.auto.service:auto-service:1.0-rc7'
shade 'org.squiddev:Cobalt:0.5.1-SNAPSHOT'
@@ -112,6 +121,8 @@ dependencies {
testImplementation 'org.hamcrest:hamcrest:2.2'
deployerJars "org.apache.maven.wagon:wagon-ssh:3.0.0"
cctJavadoc 'cc.tweaked:cct-javadoc:1.1.0'
}
// Compile tasks
@@ -120,6 +131,24 @@ javadoc {
include "dan200/computercraft/api/**/*.java"
}
task luaJavadoc(type: Javadoc) {
description "Generates documentation for Java-side Lua functions."
group "documentation"
source = sourceSets.main.allJava
destinationDir = file("doc/javadoc")
classpath = sourceSets.main.compileClasspath
options.docletpath = configurations.cctJavadoc.files as List
options.doclet = "cc.tweaked.javadoc.LuaDoclet"
// Attempt to run under Java 11 (any Java >= 9 will work though).
if(System.getProperty("java.version").startsWith("1.")
&& (System.getenv("JAVA_HOME_11_X64") != null || project.hasProperty("java11Home"))) {
executable = "${System.getenv("JAVA_HOME_11_X64") ?: project.property("java11Home")}/bin/javadoc"
}
}
jar {
dependsOn javadoc
@@ -146,8 +175,6 @@ jar {
}
}
import java.nio.charset.StandardCharsets
import java.nio.file.*
import java.util.zip.*

View File

@@ -9,4 +9,7 @@
<!-- Do not check for missing package Javadoc. -->
<suppress checks="JavadocStyle" files=".*[\\/]package-info.java" />
<!-- The commands API is documented in Lua. -->
<suppress checks="SummaryJavadocCheck" files=".*[\\/]CommandAPI.java" />
</suppressions>

View File

@@ -1,77 +0,0 @@
--- Execute a specific command.
--
-- @tparam string command The command to execute.
-- @treturn boolean Whether the command executed successfully.
-- @treturn { string... } The output of this command, as a list of lines.
-- @treturn number|nil The number of "affected" objects, or `nil` if the command
-- failed. The definition of this varies from command to command.
-- @usage Set the block above the command computer to stone.
--
-- commands.exec("setblock ~ ~1 ~ minecraft:stone")
function exec(command) end
--- Asynchronously execute a command.
--
-- Unlike @{exec}, this will immediately return, instead of waiting for the
-- command to execute. This allows you to run multiple commands at the same
-- time.
--
-- When this command has finished executing, it will queue a `task_complete`
-- event containing the result of executing this command (what @{exec} would
-- return).
--
-- @tparam string command The command to execute.
-- @treturn number The "task id". When this command has been executed, it will
-- queue a `task_complete` event with a matching id.
-- @usage Asynchronously sets the block above the computer to stone.
--
-- commands.execAsync("~ ~1 ~ minecraft:stone")
-- @see parallel One may also use the parallel API to run multiple commands at
-- once.
function execAsync(commad) end
--- List all available commands which the computer has permission to execute.
--
-- @treturn { string... } A list of all available commands
function list() end
--- Get the position of the current command computer.
--
-- @treturn number This computer's x position.
-- @treturn number This computer's y position.
-- @treturn number This computer's z position.
-- @see gps.locate To get the position of a non-command computer.
function getBlockPosition() end
--- Get some basic information about a block.
--
-- The returned table contains the current name, metadata and block state (as
-- with @{turtle.inspect}). If there is a tile entity for that block, its NBT
-- will also be returned.
--
-- @tparam number x The x position of the block to query.
-- @tparam number y The y position of the block to query.
-- @tparam number z The z position of the block to query.
-- @treturn table The given block's information.
-- @throws If the coordinates are not within the world, or are not currently
-- loaded.
function getBlockInfo(x, y, z) end
--- Get information about a range of blocks.
--
-- This returns the same information as @{getBlockInfo}, just for multiple
-- blocks at once.
--
-- Blocks are traversed by ascending y level, followed by z and x - the returned
-- table may be indexed using `x + z*width + y*depth*depth`.
--
-- @tparam number min_x The start x coordinate of the range to query.
-- @tparam number min_y The start y coordinate of the range to query.
-- @tparam number min_z The start z coordinate of the range to query.
-- @tparam number max_x The end x coordinate of the range to query.
-- @tparam number max_y The end y coordinate of the range to query.
-- @tparam number max_z The end z coordinate of the range to query.
-- @treturn { table... } A list of information about each block.
-- @throws If the coordinates are not within the world.
-- @throws If trying to get information about more than 4096 blocks.
function getBlockInfos(min_x, min_y, min_z, max_x, max_y, max_z) end

View File

@@ -2,23 +2,6 @@
--
-- @module fs
function list(path) end
function combine(base, child) end
function getName(path) end
function getSize(path) end
function exists(path) end
function isDir(path) end
function isReadOnly(path) end
function makeDir(path) end
function move(from, to) end
function copy(from, to) end
function delete(path) end
function open(path, mode) end
function getDrive(path) end
function getFreeSpace(path) end
function find(pattern) end
function getDir(path) end
--- Returns true if a path is mounted to the parent filesystem.
--
-- The root filesystem "/" is considered a mount, along with disk folders and
@@ -31,54 +14,21 @@ function getDir(path) end
-- @see getDrive
function isDriveRoot(path) end
--- Get the capacity of the drive at the given path.
--
-- This may be used in conjunction with @{getFreeSpace} to determine what
-- percentage of this drive has been used.
--
-- @tparam string path The path of the drive to get.
-- @treturn number This drive's capacity. This will be 0 for "read-only" drives,
-- such as the ROM or treasure disks.
function getCapacity(path) end
--[[- Provides completion for a file or directory name, suitable for use with
@{read}.
--- Get attributes about a specific file or folder.
--
-- The returned attributes table contains information about the size of the
-- file, whether it is a directory, and when it was created and last modified.
--
-- The creation and modification times are given as the number of milliseconds
-- since the UNIX epoch. This may be given to @{os.date} in order to convert it
-- to more usable form.
--
-- @tparam string path The path to get attributes for.
-- @treturn { size = number, isDir = boolean, created = number, modified = number }
-- The resulting attributes.
-- @throws If the path does not exist.
-- @see getSize If you only care about the file's size.
-- @see isDir If you only care whether a path is a directory or not.
function attributes(path) end
When a directory is a possible candidate for completion, two entries are
included - one with a trailing slash (indicating that entries within this
directory exist) and one without it (meaning this entry is an immediate
completion candidate). `include_dirs` can be set to @{false} to only include
those with a trailing slash.
-- Defined in bios.lua
function complete(sPath, sLocation, bIncludeFiles, bIncludeDirs) end
--- A file handle which can be read from.
--
-- @type ReadHandle
-- @see fs.open
local ReadHandle = {}
function ReadHandle.read(count) end
function ReadHandle.readAll() end
function ReadHandle.readLine(with_trailing) end
function ReadHandle.seek(whence, offset) end
function ReadHandle.close() end
--- A file handle which can be written to.
--
-- @type WriteHandle
-- @see fs.open
local WriteHandle = {}
function WriteHandle.write(text) end
function WriteHandle.writeLine(text) end
function WriteHandle.flush(text) end
function WriteHandle.seek(whence, offset) end
function WriteHandle.close() end
@tparam string path The path to complete.
@tparam string location The location where paths are resolved from.
@tparam[opt] boolean include_files When @{false}, only directories will be
included in the returned list.
@tparam[opt] boolean include_dirs When @{false}, "raw" directories will not be
included in the returned list.
@treturn { string... } A list of possible completion candidates.
]]
function complete(path, location, include_files, include_dirs) end

View File

@@ -93,47 +93,6 @@ function get(...) end
-- @treturn Response|nil The failing http response, if available.
function post(...) end
--- A http response. This acts very much like a @{fs.ReadHandle|file}, though
-- provides some http specific methods.
--
-- #### `http_success` event
-- #### `http_failure` event
--
-- @type Response
-- @see http.request On how to make a http request.
local Response = {}
--- Returns the response code and response message returned by the server
--
-- @treturn number The response code (i.e. 200)
-- @treturn string The response message (i.e. "OK")
function Response.getResponseCode() end
--- Get a table containing the response's headers, in a format similar to that
-- required by @{http.request}. If multiple headers are sent with the same
-- name, they will be combined with a comma.
--
-- @treturn { [string]=string } The response's headers.
-- Make a request to [example.computercraft.cc](https://example.computercraft.cc),
-- and print the returned headers.
-- ```lua
-- local request = http.get("https://example.computercraft.cc")
-- print(textutils.serialize(request.getResponseHeaders()))
-- -- => {
-- -- [ "Content-Type" ] = "text/plain; charset=utf8",
-- -- [ "content-length" ] = 17,
-- -- ...
-- -- }
-- request.close()
-- ```
function Response.getResponseHeaders() end
function Response.read(count) end
function Response.readAll() end
function Response.readLine(with_trailing) end
function Response.seek(whence, offset) end
function Response.close() end
--- Asynchronously determine whether a URL can be requested.
--
-- If this returns `true`, one should also listen for [`http_check`
@@ -198,32 +157,3 @@ function websocket(url, headers) end
-- @tparam[opt] { [string] = string } headers Additional headers to send as part
-- of the initial websocket connection.
function websocketAsync(url, headers) end
--- A websocket, which can be used to send an receive messages with a web
-- server.
--
-- @type Websocket
-- @see http.websocket On how to open a websocket.
local Websocket = {}
--- Send a websocket message to the connected server.
--
-- @tparam string message The message to send.
-- @tparam[opt] boolean binary Whether this message should be treated as a
-- binary string, rather than encoded text.
-- @throws If the websocket has been closed.
function Websocket.send(message, binary) end
--- Wait for a message from the server.
--
-- @tparam[opt] number timeout The number of seconds to wait if no message is
-- received.
-- @treturn[1] string The received message.
-- @treturn boolean If this was a binary message.
-- @treturn[2] nil If the websocket was closed while waiting, or if we timed out.
-- @throws If the websocket has been closed.
function Websocket.receive(timeout) end
--- Close this websocket. This will terminate the connection, meaning messages
-- can no longer be sent or received along it.
function Websocket.close() end

View File

@@ -1,21 +1,3 @@
function queueEvent(event, ...) end
function startTimer(delay) end
function setAlarm(time) end
function shutdown() end
function reboot() end
function getComputerID() end
computerID = getComputerID
function setComputerLabel(label) end
function getComputerLabel() end
computerLabel = getComputerLabel
function clock() end
function time(timezone) end
function day(timezone) end
function cancelTimer(id) end
function cancelAlarm(id) end
function epoch(timezone) end
function date(format, time) end
-- Defined in bios.lua
function loadAPI(path) end
function pullEvent(filter) end

View File

@@ -1,28 +0,0 @@
--[[-
Control the current pocket computer, adding or removing upgrades.
This API is only available on pocket computers. As such, you may use its
presence to determine what kind of computer you are using:
```lua
if pocket then
print("On a pocket computer")
else
print("On something else")
end
```
]]
--- Search the player's inventory for another upgrade, replacing the existing
-- one with that item if found.
--
-- This inventory search starts from the player's currently selected slot,
-- allowing you to prioritise upgrades.
--
-- @throws If an upgrade cannot be found.
function equipBack() end
--- Remove the pocket computer's current upgrade.
--
-- @throws If this pocket computer does not currently have an upgrade.
function unequipBack() end

View File

@@ -1,120 +0,0 @@
--[[- Interact with redstone attached to this computer.
The @{redstone} library exposes three "types" of redstone control:
- Binary input/output (@{setOutput}/@{getInput}): These simply check if a
redstone wire has any input or output. A signal strength of 1 and 15 are
treated the same.
- Analogue input/output (@{setAnalogueOutput}/@{getAnalogueInput}): These
work with the actual signal strength of the redstone wired, from 0 to 15.
- Bundled cables (@{setBundledOutput}/@{getBundledInput}): These interact with
"bundled" cables, such as those from Project:Red. These allow you to send
16 separate on/off signals. Each channel corresponds to a colour, with the
first being @{colors.white} and the last @{colors.black}.
Whenever a redstone input changes, a `redstone` event will be fired. This may
be used in or
This module may also be referred to as `rs`. For example, one may call
`rs.getSides()` instead of @{redstone.getSides}.
@module redstone
@usage Toggle the redstone signal above the computer every 0.5 seconds.
while true do
redstone.setOutput("top", not redstone.getOutput("top"))
sleep(0.5)
end
@usage Mimic a redstone comparator in [subtraction mode][comparator].
while true do
local rear = rs.getAnalogueInput("back")
local sides = math.max(rs.getAnalogueInput("left"), rs.getAnalogueInput("right"))
rs.setAnalogueOutput("front", math.max(rear - sides, 0))
os.pullEvent("redstone") -- Wait for a change to inputs.
end
[comparator]: https://minecraft.gamepedia.com/Redstone_Comparator#Subtract_signal_strength "Redstone Comparator on the Minecraft wiki."
]]
--- Returns a table containing the six sides of the computer. Namely, "top",
-- "bottom", "left", "right", "front" and "back".
--
-- @treturn { string... } A table of valid sides.
function getSides() end
--- Turn the redstone signal of a specific side on or off.
--
-- @tparam string side The side to set.
-- @tparam boolean on Whether the redstone signal should be on or off. When on,
-- a signal strength of 15 is emitted.
function setOutput(side, on) end
--- Get the current redstone output of a specific side.
--
-- @tparam string side The side to get.
-- @treturn boolean Whether the redstone output is on or off.
-- @see setOutput
function getOutput(side) end
--- Get the current redstone input of a specific side.
--
-- @tparam string side The side to get.
-- @treturn boolean Whether the redstone input is on or off.
function getInput(side) end
--- Set the redstone signal strength for a specific side.
--
-- @tparam string side The side to set.
-- @tparam number value The signal strength, between 0 and 15.
-- @throws If `value` is not between 0 and 15.
function setAnalogOutput(side, value) end
setAnalogueOutput = setAnalogOutput
--- Get the redstone output signal strength for a specific side.
--
-- @tparam string side The side to get.
-- @treturn number The output signal strength, between 0 and 15.
-- @see setAnalogueOutput
function getAnalogOutput(sid) end
getAnalogueOutput = getAnalogOutput
--- Get the redstone input signal strength for a specific side.
--
-- @tparam string side The side to get.
-- @treturn number The input signal strength, between 0 and 15.
function getAnalogInput(side) end
getAnalogueInput = getAnalogInput
--- Set the bundled cable output for a specific side.
--
-- @tparam string side The side to set.
-- @tparam number The colour bitmask to set.
-- @see colors.subtract For removing a colour from the bitmask.
-- @see colors.combine For adding a colour to the bitmask.
function setBundledOutput(side, output) end
--- Get the bundled cable output for a specific side.
--
-- @tparam string side The side to get.
-- @treturn number The bundled cable's output.
function getBundledOutput(side) end
--- Get the bundled cable input for a specific side.
--
-- @tparam string side The side to get.
-- @treturn number The bundled cable's input.
-- @see testBundledInput To determine if a specific colour is set.
function getBundledInput(side) end
--- Determine if a specific combination of colours are on for the given side.
--
-- @tparam string side The side to test.
-- @tparam number mask The mask to test.
-- @see getBundledInput
-- @see colors.combine For adding a colour to the bitmask.
-- @usage Check if @{colors.white} and @{colors.black} are on for above the
-- computer.
--
-- print(redstone.testBundledInput("top", colors.combine(colors.white, colors.black)))
function testBundledInput(side, mask) end

View File

@@ -1,52 +0,0 @@
function write(text) end
function scroll(lines) end
function setCursorPos(x, y) end
function setCursorBlink(blink) end
function getCursorPos() end
function getSize() end
function clear() end
function clearLine() end
function setTextColour(colour) end
setTextColor = setTextColour
function setBackgroundColour(colour) end
setBackgroundColor = setBackgroundColour
function isColour() end
isColor = isColour
function getTextColour() end
getTextColor = getTextColor
function getBackgroundColour() end
getBackgroundColor = getBackgroundColour
function blit(text, text_colours, background_colours) end
function setPaletteColour(colour, ...) end
setPaletteColor = setPaletteColour
function getPaletteColour(colour, ...) end
getPaletteColor = getPaletteColour
function nativePaletteColour(colour) end
nativePaletteColor = nativePaletteColour
--- @type Redirect
local Redirect = {}
Redirect.write = write
Redirect.scroll = scroll
Redirect.setCursorPos = setCursorPos
Redirect.setCursorBlink = setCursorBlink
Redirect.getCursorPos = getCursorPos
Redirect.getSize = getSize
Redirect.clear = clear
Redirect.clearLine = clearLine
Redirect.setTextColour = setTextColour
Redirect.setTextColor = setTextColor
Redirect.setBackgroundColour = setBackgroundColour
Redirect.setBackgroundColor = setBackgroundColor
Redirect.isColour = isColour
Redirect.isColor = isColor
Redirect.getTextColour = getTextColour
Redirect.getTextColor = getTextColor
Redirect.getBackgroundColour = getBackgroundColour
Redirect.getBackgroundColor = getBackgroundColor
Redirect.blit = blit
Redirect.setPaletteColour = setPaletteColour
Redirect.setPaletteColor = setPaletteColor
Redirect.getPaletteColour = getPaletteColour
Redirect.getPaletteColor = getPaletteColor

View File

@@ -1,230 +1 @@
--- Move the turtle forward one block.
-- @treturn boolean Whether the turtle could successfully move.
-- @treturn string|nil The reason the turtle could not move.
function forward() end
--- Move the turtle backwards one block.
-- @treturn boolean Whether the turtle could successfully move.
-- @treturn string|nil The reason the turtle could not move.
function back() end
--- Move the turtle up one block.
-- @treturn boolean Whether the turtle could successfully move.
-- @treturn string|nil The reason the turtle could not move.
function up() end
--- Move the turtle down one block.
-- @treturn boolean Whether the turtle could successfully move.
-- @treturn string|nil The reason the turtle could not move.
function down() end
--- Rotate the turtle 90 degress to the left.
function turnLeft() end
--- Rotate the turtle 90 degress to the right.
function turnRight() end
--- Attempt to break the block in front of the turtle.
--
-- This requires a turtle tool capable of breaking the block. Diamond pickaxes
-- (mining turtles) can break any vanilla block, but other tools (such as axes)
-- are more limited.
--
-- @tparam[opt] "left"|"right" side The specific tool to use.
-- @treturn boolean Whether a block was broken.
-- @treturn string|nil The reason no block was broken.
function dig(side) end
--- Attempt to break the block above the turtle. See @{dig} for full details.
--
-- @tparam[opt] "left"|"right" side The specific tool to use.
-- @treturn boolean Whether a block was broken.
-- @treturn string|nil The reason no block was broken.
function digUp(side) end
--- Attempt to break the block below the turtle. See @{dig} for full details.
--
-- @tparam[opt] "left"|"right" side The specific tool to use.
-- @treturn boolean Whether a block was broken.
-- @treturn string|nil The reason no block was broken.
function digDown(side) end
--- Attack the entity in front of the turtle.
--
-- @tparam[opt] "left"|"right" side The specific tool to use.
-- @treturn boolean Whether an entity was attacked.
-- @treturn string|nil The reason nothing was attacked.
function attack(side) end
--- Attack the entity above the turtle.
--
-- @tparam[opt] "left"|"right" side The specific tool to use.
-- @treturn boolean Whether an entity was attacked.
-- @treturn string|nil The reason nothing was attacked.
function attackUp(side) end
--- Attack the entity below the turtle.
--
-- @tparam[opt] "left"|"right" side The specific tool to use.
-- @treturn boolean Whether an entity was attacked.
-- @treturn string|nil The reason nothing was attacked.
function attackDown(side) end
--- Place a block or item into the world in front of the turtle.
--
-- @treturn boolean Whether the block could be placed.
-- @treturn string|nil The reason the block was not placed.
function place() end
--- Place a block or item into the world above the turtle.
--
-- @treturn boolean Whether the block could be placed.
-- @treturn string|nil The reason the block was not placed.
function placeUp() end
--- Place a block or item into the world below the turtle.
--
-- @treturn boolean Whether the block could be placed.
-- @treturn string|nil The reason the block was not placed.
function placeDown() end
--- Drop the currently selected stack into the inventory in front of the turtle,
-- or as an item into the world if there is no inventory.
--
-- @tparam[opt] number count The number of items to drop. If not given, the
-- entire stack will be dropped.
-- @treturn boolean Whether items were dropped.
-- @treturn string|nil The reason the no items were dropped.
-- @see select
function drop(count) end
--- Drop the currently selected stack into the inventory above the turtle, or as
-- an item into the world if there is no inventory.
--
-- @tparam[opt] number count The number of items to drop. If not given, the
-- entire stack will be dropped.
-- @treturn boolean Whether items were dropped.
-- @treturn string|nil The reason the no items were dropped.
-- @see select
function dropUp(count) end
--- Drop the currently selected stack into the inventory below the turtle, or as
-- an item into the world if there is no inventory.
--
-- @tparam[opt] number count The number of items to drop. If not given, the
-- entire stack will be dropped.
-- @treturn boolean Whether items were dropped.
-- @treturn string|nil The reason the no items were dropped.
-- @see select
function dropDown(count) end
--- Suck an item from the inventory in front of the turtle, or from an item
-- floating in the world.
--
-- This will pull items into the first acceptable slot, starting at the
-- @{select|currently selected} one.
--
-- @tparam[opt] number count The number of items to suck. If not given, up to a
-- stack of items will be picked up.
-- @treturn boolean Whether items were picked up.
-- @treturn string|nil The reason the no items were picked up.
function suck(count) end
--- Suck an item from the inventory above the turtle, or from an item floating
-- in the world.
--
-- @tparam[opt] number count The number of items to suck. If not given, up to a
-- stack of items will be picked up.
-- @treturn boolean Whether items were picked up.
-- @treturn string|nil The reason the no items were picked up.
function suckUp(count) end
--- Suck an item from the inventory below the turtle, or from an item floating
-- in the world.
--
-- @tparam[opt] number count The number of items to suck. If not given, up to a
-- stack of items will be picked up.
-- @treturn boolean Whether items were picked up.
-- @treturn string|nil The reason the no items were picked up.
function suckDown(count) end
--- Check if there is a solid block in front of the turtle. In this case, solid
-- refers to any non-air or liquid block.
--
-- @treturn boolean If there is a solid block in front.
function detect() end
--- Check if there is a solid block above the turtle.
--
-- @treturn boolean If there is a solid block above.
function detectUp() end
--- Check if there is a solid block below the turtle.
--
-- @treturn boolean If there is a solid block below.
function detectDown() end
function compare() end
function compareUp() end
function compareDown() end
function inspect() end
function inspectUp() end
function inspectDown() end
--- Change the currently selected slot.
--
-- The selected slot is determines what slot actions like @{drop} or
-- @{getItemCount} act on.
--
-- @tparam number slot The slot to select.
-- @see getSelectedSlot
function select(slot) end
--- Get the currently selected slot.
--
-- @treturn number The current slot.
-- @see select
function getSelectedSlot() end
--- Get the number of items in the given slot.
--
-- @tparam[opt] number slot The slot we wish to check. Defaults to the @{turtle.select|selected slot}.
-- @treturn number The number of items in this slot.
function getItemCount(slot) end
--- Get the remaining number of items which may be stored in this stack.
--
-- For instance, if a slot contains 13 blocks of dirt, it has room for another 51.
--
-- @tparam[opt] number slot The slot we wish to check. Defaults to the @{turtle.select|selected slot}.
-- @treturn number The space left in this slot.
function getItemSpace(slot) end
--- Get detailed information about the items in the given slot.
--
-- @tparam[opt] number slot The slot to get information about. Defaults to the @{turtle.select|selected slot}.
-- @treturn nil|table Information about the given slot, or @{nil} if it is empty.
-- @usage Print the current slot, assuming it contains 13 dirt.
--
-- print(textutils.serialize(turtle.getItemDetail()))
-- -- => {
-- -- name = "minecraft:dirt",
-- -- damage = 0,
-- -- count = 13,
-- -- }
function getItemDetail(slot) end
function getFuelLevel() end
function refuel(count) end
function compareTo(slot) end
function transferTo(slot, count) end
function getFuelLimit() end
function equipLeft() end
function equipRight() end
function craft(limit) end

View File

@@ -51,7 +51,12 @@ h4 { font-size: 1.06em; }
a, a:visited, a:active { font-weight: bold; color: #004080; text-decoration: none; }
a:hover { text-decoration: underline; }
blockquote { margin-left: 3em; }
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; }

View File

@@ -1,7 +1,7 @@
# Mod properties
mod_version=1.89.1
mod_version=1.93.0
# Minecraft properties (update mods.toml when changing)
mc_version=1.15.2
forge_version=31.1.41
mappings_version=20200429-1.15.1
mc_version=1.16.3
forge_version=34.0.1
mappings_version=20200723-1.16.1

View File

@@ -2,6 +2,7 @@
(sources
/doc/stub/
/doc/javadoc/
/src/main/resources/*/computercraft/lua/bios.lua
/src/main/resources/*/computercraft/lua/rom/
/src/test/resources/test-rom)
@@ -12,8 +13,12 @@
(index doc/index.md)
(source-link https://github.com/SquidDev-CC/CC-Tweaked/blob/${commit}/${path}#L${line})
(module-kinds
(peripheral Peripherals))
(library-path
/doc/stub/
/doc/javadoc/
/src/main/resources/*/computercraft/lua/rom/apis
/src/main/resources/*/computercraft/lua/rom/apis/command
@@ -64,31 +69,41 @@
(lint (allow-toplevel-global true)))
;; Silence some variable warnings in documentation stubs.
(at /doc/stub
(at (/doc/stub/ /doc/javadoc/)
(linters -var:unused-global)
(lint (allow-toplevel-global true)))
;; Suppress warnings for currently undocumented modules.
(at
(/doc/stub/fs.lua
(; Java APIs
/doc/stub/http.lua
/doc/stub/os.lua
/doc/stub/term.lua
/doc/stub/turtle.lua
; Java generated APIs
/doc/javadoc/turtle.lua
; Peripherals
/doc/javadoc/drive.lua
/doc/javadoc/speaker.lua
/doc/javadoc/printer.lua
; Lua APIs
/src/main/resources/*/computercraft/lua/rom/apis/io.lua
/src/main/resources/*/computercraft/lua/rom/apis/window.lua)
(linters -doc:undocumented -doc:undocumented-arg))
(linters -doc:undocumented -doc:undocumented-arg -doc:undocumented-return))
;; These currently rely on unknown references.
(at
(/src/main/resources/*/computercraft/lua/rom/apis/textutils.lua
/src/main/resources/*/computercraft/lua/rom/modules/main/cc/completion.lua
/src/main/resources/*/computercraft/lua/rom/modules/main/cc/shell/completion.lua
/src/main/resources/*/computercraft/lua/rom/programs/shell.lua)
/src/main/resources/*/computercraft/lua/rom/programs/shell.lua
/doc/stub/fs.lua)
(linters -doc:unresolved-reference))
(at /src/test/resources/test-rom
; We should still be able to test deprecated members.
(linters -var:deprecated)
(lint
(globals
:max sleep write

View File

@@ -0,0 +1,10 @@
{
"replace": false,
"values": [
"computercraft:computer_advanced",
"computercraft:turtle_advanced",
"computercraft:wireless_modem_advanced",
"computercraft:pocket_computer_advanced",
"computercraft:monitor_advanced"
]
}

View File

@@ -8,38 +8,20 @@ package dan200.computercraft;
import dan200.computercraft.api.turtle.event.TurtleAction;
import dan200.computercraft.core.apis.http.options.Action;
import dan200.computercraft.core.apis.http.options.AddressRule;
import dan200.computercraft.core.asm.GenericSource;
import dan200.computercraft.shared.Config;
import dan200.computercraft.shared.computer.blocks.BlockComputer;
import dan200.computercraft.shared.Registry;
import dan200.computercraft.shared.computer.core.ClientComputerRegistry;
import dan200.computercraft.shared.computer.core.ServerComputerRegistry;
import dan200.computercraft.shared.computer.items.ItemComputer;
import dan200.computercraft.shared.media.items.ItemDisk;
import dan200.computercraft.shared.media.items.ItemPrintout;
import dan200.computercraft.shared.media.items.ItemTreasureDisk;
import dan200.computercraft.shared.peripheral.diskdrive.BlockDiskDrive;
import dan200.computercraft.shared.peripheral.modem.wired.BlockCable;
import dan200.computercraft.shared.peripheral.modem.wired.BlockWiredModemFull;
import dan200.computercraft.shared.peripheral.modem.wired.ItemBlockCable;
import dan200.computercraft.shared.peripheral.modem.wireless.BlockWirelessModem;
import dan200.computercraft.shared.peripheral.monitor.BlockMonitor;
import dan200.computercraft.shared.peripheral.monitor.MonitorRenderer;
import dan200.computercraft.shared.peripheral.printer.BlockPrinter;
import dan200.computercraft.shared.peripheral.speaker.BlockSpeaker;
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
import dan200.computercraft.shared.pocket.peripherals.PocketModem;
import dan200.computercraft.shared.pocket.peripherals.PocketSpeaker;
import dan200.computercraft.shared.turtle.blocks.BlockTurtle;
import dan200.computercraft.shared.turtle.items.ItemTurtle;
import dan200.computercraft.shared.turtle.upgrades.*;
import net.minecraft.resources.IReloadableResourceManager;
import net.minecraft.util.ResourceLocation;
import dan200.computercraft.shared.util.ServiceUtil;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.server.ServerLifecycleHooks;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
@@ -53,12 +35,11 @@ public final class ComputerCraft
{
public static final String MOD_ID = "computercraft";
public static final int DATAFIXER_VERSION = 0;
// Configuration options
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",
@@ -82,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() ) );
@@ -99,6 +80,7 @@ public final class ComputerCraft
public static int modemHighAltitudeRangeDuringStorm = 384;
public static int maxNotesPerTick = 8;
public static MonitorRenderer monitorRenderer = MonitorRenderer.BEST;
public static double monitorDistanceSq = 4096;
public static long monitorBandwidth = 1_000_000;
public static boolean turtlesNeedFuel = true;
@@ -108,61 +90,19 @@ public final class ComputerCraft
public static boolean turtlesCanPush = true;
public static EnumSet<TurtleAction> turtleDisabledActions = EnumSet.noneOf( TurtleAction.class );
public static final int terminalWidth_computer = 51;
public static final int terminalHeight_computer = 19;
public static boolean genericPeripheral = false;
public static final int terminalWidth_turtle = 39;
public static final int terminalHeight_turtle = 13;
public static int computerTermWidth = 51;
public static int computerTermHeight = 19;
public static final int terminalWidth_pocketComputer = 26;
public static final int terminalHeight_pocketComputer = 20;
public static final int turtleTermWidth = 39;
public static final int turtleTermHeight = 13;
// Blocks and Items
public static final class Blocks
{
public static BlockComputer computerNormal;
public static BlockComputer computerAdvanced;
public static BlockComputer computerCommand;
public static int pocketTermWidth = 26;
public static int pocketTermHeight = 20;
public static BlockTurtle turtleNormal;
public static BlockTurtle turtleAdvanced;
public static BlockSpeaker speaker;
public static BlockDiskDrive diskDrive;
public static BlockPrinter printer;
public static BlockMonitor monitorNormal;
public static BlockMonitor monitorAdvanced;
public static BlockWirelessModem wirelessModemNormal;
public static BlockWirelessModem wirelessModemAdvanced;
public static BlockWiredModemFull wiredModemFull;
public static BlockCable cable;
}
public static final class Items
{
public static ItemComputer computerNormal;
public static ItemComputer computerAdvanced;
public static ItemComputer computerCommand;
public static ItemPocketComputer pocketComputerNormal;
public static ItemPocketComputer pocketComputerAdvanced;
public static ItemTurtle turtleNormal;
public static ItemTurtle turtleAdvanced;
public static ItemDisk disk;
public static ItemTreasureDisk treasureDisk;
public static ItemPrintout printedPage;
public static ItemPrintout printedPages;
public static ItemPrintout printedBook;
public static ItemBlockCable.Cable cable;
public static ItemBlockCable.WiredModem wiredModem;
}
public static int monitorWidth = 8;
public static int monitorHeight = 6;
public static final class TurtleUpgrades
{
@@ -194,19 +134,8 @@ public final class ComputerCraft
public ComputerCraft()
{
Config.load();
}
public static InputStream getResourceFile( String domain, String subPath )
{
IReloadableResourceManager manager = ServerLifecycleHooks.getCurrentServer().getResourceManager();
try
{
return manager.getResource( new ResourceLocation( domain, subPath ) ).getInputStream();
}
catch( IOException ignored )
{
return null;
}
Config.setup();
Registry.setup();
GenericSource.setup( () -> ServiceUtil.loadServicesForge( GenericSource.class ) );
}
}

View File

@@ -27,6 +27,7 @@ import dan200.computercraft.shared.wired.WiredNode;
import net.minecraft.resources.IReloadableResourceManager;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.World;
@@ -36,6 +37,8 @@ import net.minecraftforge.fml.server.ServerLifecycleHooks;
import javax.annotation.Nonnull;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import static dan200.computercraft.shared.Capabilities.CAPABILITY_WIRED_ELEMENT;
@@ -49,6 +52,19 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
{
}
public static InputStream getResourceFile( String domain, String subPath )
{
IReloadableResourceManager manager = (IReloadableResourceManager) ServerLifecycleHooks.getCurrentServer().getDataPackRegistries().getResourceManager();
try
{
return manager.getResource( new ResourceLocation( domain, subPath ) ).getInputStream();
}
catch( IOException ignored )
{
return null;
}
}
@Nonnull
@Override
public String getInstalledVersion()
@@ -81,7 +97,7 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
@Override
public IMount createResourceMount( @Nonnull String domain, @Nonnull String subPath )
{
IReloadableResourceManager manager = ServerLifecycleHooks.getCurrentServer().getResourceManager();
IReloadableResourceManager manager = (IReloadableResourceManager) ServerLifecycleHooks.getCurrentServer().getDataPackRegistries().getResourceManager();
ResourceMount mount = ResourceMount.get( domain, subPath, manager );
return mount.exists( "" ) ? mount : null;
}

View File

@@ -6,11 +6,11 @@
package dan200.computercraft.api.client;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.TransformationMatrix;
import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.client.renderer.model.ModelManager;
import net.minecraft.client.renderer.model.ModelResourceLocation;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.vector.TransformationMatrix;
import javax.annotation.Nonnull;
import java.util.Objects;

View File

@@ -5,7 +5,7 @@
*/
package dan200.computercraft.api.network;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
@@ -29,7 +29,7 @@ public interface IPacketReceiver
* @return The receiver's position.
*/
@Nonnull
Vec3d getPosition();
Vector3d getPosition();
/**
* Get the maximum distance this receiver can send and receive messages.

View File

@@ -5,7 +5,7 @@
*/
package dan200.computercraft.api.network;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
@@ -29,7 +29,7 @@ public interface IPacketSender
* @return The sender's position.
*/
@Nonnull
Vec3d getPosition();
Vector3d getPosition();
/**
* Get some sort of identification string for this sender. This does not strictly need to be unique, but you

View File

@@ -15,8 +15,7 @@ import javax.annotation.Nullable;
* The interface that defines a peripheral.
*
* In order to expose a peripheral for your block or tile entity, you may either attach a {@link Capability}, or
* register a {@link IPeripheralProvider}. It is <em>not</em> recommended to implement {@link IPeripheral} directly on
* the tile.
* register a {@link IPeripheralProvider}. This <em>cannot</em> be implemented {@link IPeripheral} directly on the tile.
*
* Peripherals should provide a series of methods to the user, either using {@link LuaFunction} or by implementing
* {@link IDynamicPeripheral}.

View File

@@ -5,12 +5,15 @@
*/
package dan200.computercraft.api.pocket;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.IItemProvider;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.Util;
import net.minecraftforge.common.util.NonNullSupplier;
import javax.annotation.Nonnull;
import java.util.function.Supplier;
/**
* A base class for {@link IPocketUpgrade}s.
@@ -21,23 +24,48 @@ public abstract class AbstractPocketUpgrade implements IPocketUpgrade
{
private final ResourceLocation id;
private final String adjective;
private final ItemStack stack;
private final NonNullSupplier<ItemStack> stack;
protected AbstractPocketUpgrade( ResourceLocation id, String adjective, ItemStack stack )
protected AbstractPocketUpgrade( ResourceLocation id, String adjective, NonNullSupplier<ItemStack> stack )
{
this.id = id;
this.adjective = adjective;
this.stack = stack;
}
protected AbstractPocketUpgrade( ResourceLocation id, NonNullSupplier<ItemStack> item )
{
this( id, Util.makeTranslationKey( "upgrade", id ) + ".adjective", item );
}
protected AbstractPocketUpgrade( ResourceLocation id, String adjective, ItemStack stack )
{
this( id, adjective, () -> stack );
}
protected AbstractPocketUpgrade( ResourceLocation id, ItemStack stack )
{
this( id, () -> stack );
}
protected AbstractPocketUpgrade( ResourceLocation id, String adjective, IItemProvider item )
{
this( id, adjective, new ItemStack( item ) );
this( id, adjective, new CachedStack( () -> item ) );
}
protected AbstractPocketUpgrade( ResourceLocation id, IItemProvider item )
{
this( id, Util.makeTranslationKey( "upgrade", id ) + ".adjective", new ItemStack( item ) );
this( id, new CachedStack( () -> item ) );
}
protected AbstractPocketUpgrade( ResourceLocation id, String adjective, Supplier<? extends IItemProvider> item )
{
this( id, adjective, new CachedStack( item ) );
}
protected AbstractPocketUpgrade( ResourceLocation id, Supplier<? extends IItemProvider> item )
{
this( id, new CachedStack( item ) );
}
@Nonnull
@@ -58,6 +86,32 @@ public abstract class AbstractPocketUpgrade implements IPocketUpgrade
@Override
public final ItemStack getCraftingItem()
{
return stack;
return stack.get();
}
/**
* Caches the construction of an item stack.
*
* @see dan200.computercraft.api.turtle.AbstractTurtleUpgrade For explanation of this class.
*/
private static final class CachedStack implements NonNullSupplier<ItemStack>
{
private final Supplier<? extends IItemProvider> provider;
private Item item;
private ItemStack stack;
CachedStack( Supplier<? extends IItemProvider> provider )
{
this.provider = provider;
}
@Nonnull
@Override
public ItemStack get()
{
Item item = provider.get().asItem();
if( item == this.item && stack != null ) return stack;
return stack = new ItemStack( this.item = item );
}
}
}

View File

@@ -5,12 +5,15 @@
*/
package dan200.computercraft.api.turtle;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.IItemProvider;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.Util;
import net.minecraftforge.common.util.NonNullSupplier;
import javax.annotation.Nonnull;
import java.util.function.Supplier;
/**
* A base class for {@link ITurtleUpgrade}s.
@@ -22,9 +25,9 @@ public abstract class AbstractTurtleUpgrade implements ITurtleUpgrade
private final ResourceLocation id;
private final TurtleUpgradeType type;
private final String adjective;
private final ItemStack stack;
private final NonNullSupplier<ItemStack> stack;
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, String adjective, ItemStack stack )
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, String adjective, NonNullSupplier<ItemStack> stack )
{
this.id = id;
this.type = type;
@@ -32,19 +35,39 @@ public abstract class AbstractTurtleUpgrade implements ITurtleUpgrade
this.stack = stack;
}
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, String adjective, IItemProvider item )
{
this( id, type, adjective, new ItemStack( item ) );
}
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, ItemStack stack )
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, NonNullSupplier<ItemStack> stack )
{
this( id, type, Util.makeTranslationKey( "upgrade", id ) + ".adjective", stack );
}
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, String adjective, ItemStack stack )
{
this( id, type, adjective, () -> stack );
}
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, ItemStack stack )
{
this( id, type, () -> stack );
}
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, String adjective, IItemProvider item )
{
this( id, type, adjective, new CachedStack( () -> item ) );
}
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, IItemProvider item )
{
this( id, type, new ItemStack( item ) );
this( id, type, new CachedStack( () -> item ) );
}
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, String adjective, Supplier<? extends IItemProvider> item )
{
this( id, type, adjective, new CachedStack( item ) );
}
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, Supplier<? extends IItemProvider> item )
{
this( id, type, new CachedStack( item ) );
}
@Nonnull
@@ -72,6 +95,32 @@ public abstract class AbstractTurtleUpgrade implements ITurtleUpgrade
@Override
public final ItemStack getCraftingItem()
{
return stack;
return stack.get();
}
/**
* A supplier which converts an item into an item stack.
*
* Constructing item stacks is somewhat expensive due to attaching capabilities. We cache it if given a consistent item.
*/
private static final class CachedStack implements NonNullSupplier<ItemStack>
{
private final Supplier<? extends IItemProvider> provider;
private Item item;
private ItemStack stack;
CachedStack( Supplier<? extends IItemProvider> provider )
{
this.provider = provider;
}
@Nonnull
@Override
public ItemStack get()
{
Item item = provider.get().asItem();
if( item == this.item && stack != null ) return stack;
return stack = new ItemStack( this.item = item );
}
}
}

View File

@@ -13,7 +13,7 @@ import net.minecraft.inventory.IInventory;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.world.World;
import net.minecraftforge.items.IItemHandlerModifiable;
@@ -67,7 +67,7 @@ public interface ITurtleAccess
* @see #getVisualYaw(float)
*/
@Nonnull
Vec3d getVisualPosition( float f );
Vector3d getVisualPosition( float f );
/**
* Returns the yaw the turtle is facing when it is rendered.

View File

@@ -16,8 +16,8 @@ import java.util.Objects;
/**
* Fired when a turtle gathers data on an item in its inventory.
*
* You may prevent items being inspected, or add additional information to the result. Be aware that this is fired on
* the computer thread, and so any operations on it must be thread safe.
* You may prevent items being inspected, or add additional information to the result. Be aware that this may be fired
* on the computer thread, and so any operations on it must be thread safe.
*
* @see TurtleAction#INSPECT_ITEM
*/
@@ -25,8 +25,15 @@ public class TurtleInspectItemEvent extends TurtleActionEvent
{
private final ItemStack stack;
private final Map<String, Object> data;
private final boolean mainThread;
@Deprecated
public TurtleInspectItemEvent( @Nonnull ITurtleAccess turtle, @Nonnull ItemStack stack, @Nonnull Map<String, Object> data )
{
this( turtle, stack, data, false );
}
public TurtleInspectItemEvent( @Nonnull ITurtleAccess turtle, @Nonnull ItemStack stack, @Nonnull Map<String, Object> data, boolean mainThread )
{
super( turtle, TurtleAction.INSPECT_ITEM );
@@ -34,6 +41,7 @@ public class TurtleInspectItemEvent extends TurtleActionEvent
Objects.requireNonNull( data, "data cannot be null" );
this.stack = stack;
this.data = data;
this.mainThread = mainThread;
}
/**
@@ -58,6 +66,17 @@ public class TurtleInspectItemEvent extends TurtleActionEvent
return data;
}
/**
* If this event is being fired on the server thread. When true, information which relies on server state may be
* exposed.
*
* @return If this is run on the main thread.
*/
public boolean onMainThread()
{
return mainThread;
}
/**
* Add new information to the inspection result. Note this will override fields with the same name.
*

View File

@@ -7,6 +7,7 @@ package dan200.computercraft.client;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.client.render.TurtleModelLoader;
import dan200.computercraft.shared.Registry;
import dan200.computercraft.shared.common.IColouredItem;
import dan200.computercraft.shared.media.items.ItemDisk;
import dan200.computercraft.shared.media.items.ItemTreasureDisk;
@@ -109,7 +110,7 @@ public final class ClientRegistry
@SubscribeEvent
public static void onItemColours( ColorHandlerEvent.Item event )
{
if( ComputerCraft.Items.disk == null || ComputerCraft.Blocks.turtleNormal == null )
if( Registry.ModItems.DISK == null || Registry.ModBlocks.TURTLE_NORMAL == null )
{
ComputerCraft.log.warn( "Block/item registration has failed. Skipping registration of item colours." );
return;
@@ -117,12 +118,12 @@ public final class ClientRegistry
event.getItemColors().register(
( stack, layer ) -> layer == 1 ? ((ItemDisk) stack.getItem()).getColour( stack ) : 0xFFFFFF,
ComputerCraft.Items.disk
Registry.ModItems.DISK.get()
);
event.getItemColors().register(
( stack, layer ) -> layer == 1 ? ItemTreasureDisk.getColour( stack ) : 0xFFFFFF,
ComputerCraft.Items.treasureDisk
Registry.ModItems.TREASURE_DISK.get()
);
event.getItemColors().register( ( stack, layer ) -> {
@@ -139,12 +140,12 @@ public final class ClientRegistry
return light == -1 ? Colour.BLACK.getHex() : light;
}
}
}, ComputerCraft.Items.pocketComputerNormal, ComputerCraft.Items.pocketComputerAdvanced );
}, Registry.ModItems.POCKET_COMPUTER_NORMAL.get(), Registry.ModItems.POCKET_COMPUTER_ADVANCED.get() );
// Setup turtle colours
event.getItemColors().register(
( stack, tintIndex ) -> tintIndex == 0 ? ((IColouredItem) stack.getItem()).getColour( stack ) : 0xFFFFFF,
ComputerCraft.Blocks.turtleNormal, ComputerCraft.Blocks.turtleAdvanced
Registry.ModBlocks.TURTLE_NORMAL.get(), Registry.ModBlocks.TURTLE_ADVANCED.get()
);
}
}

View File

@@ -12,14 +12,12 @@ import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.NewChatGui;
import net.minecraft.client.gui.RenderComponentsUtil;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextFormatting;
import org.apache.commons.lang3.StringUtils;
import javax.annotation.Nullable;
import java.util.List;
public class ClientTableFormatter implements TableFormatter
{
@@ -57,7 +55,7 @@ public class ClientTableFormatter implements TableFormatter
@Override
public int getWidth( ITextComponent component )
{
return renderer().getStringWidth( component.getFormattedText() );
return renderer().func_238414_a_( component );
}
@Override
@@ -66,10 +64,11 @@ public class ClientTableFormatter implements TableFormatter
Minecraft mc = Minecraft.getInstance();
NewChatGui chat = mc.ingameGUI.getChatGUI();
// Trim the text if it goes over the allowed length
int maxWidth = MathHelper.floor( chat.getChatWidth() / chat.getScale() );
List<ITextComponent> list = RenderComponentsUtil.splitText( component, maxWidth, mc.fontRenderer, false, false );
if( !list.isEmpty() ) chat.printChatMessageWithOptionalDeletion( list.get( 0 ), id );
// TODO: Trim the text if it goes over the allowed length
// int maxWidth = MathHelper.floor( chat.getChatWidth() / chat.getScale() );
// List<ITextProperties> list = RenderComponentsUtil.func_238505_a_( component, maxWidth, mc.fontRenderer );
// if( !list.isEmpty() ) chat.printChatMessageWithOptionalDeletion( list.get( 0 ), id );
chat.printChatMessageWithOptionalDeletion( component, id );
}
@Override

View File

@@ -13,10 +13,14 @@ import dan200.computercraft.core.terminal.TextBuffer;
import dan200.computercraft.shared.util.Colour;
import dan200.computercraft.shared.util.Palette;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.*;
import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.RenderState;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.vector.Matrix4f;
import net.minecraft.util.math.vector.TransformationMatrix;
import org.lwjgl.opengl.GL11;
import javax.annotation.Nonnull;

View File

@@ -5,10 +5,12 @@
*/
package dan200.computercraft.client.gui;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.client.gui.widgets.WidgetTerminal;
import dan200.computercraft.client.gui.widgets.WidgetWrapper;
import dan200.computercraft.client.render.ComputerBorderRenderer;
import dan200.computercraft.shared.computer.core.ClientComputer;
import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.computer.inventory.ContainerComputer;
@@ -17,21 +19,20 @@ import dan200.computercraft.shared.computer.inventory.ContainerViewComputer;
import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer;
import net.minecraft.client.gui.screen.inventory.ContainerScreen;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.ITextComponent;
import org.lwjgl.glfw.GLFW;
import javax.annotation.Nonnull;
import static dan200.computercraft.client.render.ComputerBorderRenderer.BORDER;
import static dan200.computercraft.client.render.ComputerBorderRenderer.MARGIN;
public final class GuiComputer<T extends ContainerComputerBase> extends ContainerScreen<T>
{
public static final ResourceLocation BACKGROUND_NORMAL = new ResourceLocation( ComputerCraft.MOD_ID, "textures/gui/corners_normal.png" );
public static final ResourceLocation BACKGROUND_ADVANCED = new ResourceLocation( ComputerCraft.MOD_ID, "textures/gui/corners_advanced.png" );
public static final ResourceLocation BACKGROUND_COMMAND = new ResourceLocation( ComputerCraft.MOD_ID, "textures/gui/corners_command.png" );
public static final ResourceLocation BACKGROUND_COLOUR = new ResourceLocation( ComputerCraft.MOD_ID, "textures/gui/corners_colour.png" );
private final ComputerFamily m_family;
private final ClientComputer m_computer;
private final int m_termWidth;
private final int m_termHeight;
private final ComputerFamily family;
private final ClientComputer computer;
private final int termWidth;
private final int termHeight;
private WidgetTerminal terminal;
private WidgetWrapper terminalWrapper;
@@ -41,10 +42,10 @@ public final class GuiComputer<T extends ContainerComputerBase> extends Containe
)
{
super( container, player, title );
m_family = container.getFamily();
m_computer = (ClientComputer) container.getComputer();
m_termWidth = termWidth;
m_termHeight = termHeight;
family = container.getFamily();
computer = (ClientComputer) container.getComputer();
this.termWidth = termWidth;
this.termHeight = termHeight;
terminal = null;
}
@@ -52,7 +53,7 @@ public final class GuiComputer<T extends ContainerComputerBase> extends Containe
{
return new GuiComputer<>(
container, inventory, component,
ComputerCraft.terminalWidth_computer, ComputerCraft.terminalHeight_computer
ComputerCraft.computerTermWidth, ComputerCraft.computerTermHeight
);
}
@@ -60,7 +61,7 @@ public final class GuiComputer<T extends ContainerComputerBase> extends Containe
{
return new GuiComputer<>(
container, inventory, component,
ComputerCraft.terminalWidth_pocketComputer, ComputerCraft.terminalHeight_pocketComputer
ComputerCraft.pocketTermWidth, ComputerCraft.pocketTermHeight
);
}
@@ -78,25 +79,25 @@ public final class GuiComputer<T extends ContainerComputerBase> extends Containe
{
minecraft.keyboardListener.enableRepeatEvents( true );
int termPxWidth = m_termWidth * FixedWidthFontRenderer.FONT_WIDTH;
int termPxHeight = m_termHeight * FixedWidthFontRenderer.FONT_HEIGHT;
int termPxWidth = termWidth * FixedWidthFontRenderer.FONT_WIDTH;
int termPxHeight = termHeight * FixedWidthFontRenderer.FONT_HEIGHT;
xSize = termPxWidth + 4 + 24;
ySize = termPxHeight + 4 + 24;
xSize = termPxWidth + MARGIN * 2 + BORDER * 2;
ySize = termPxHeight + MARGIN * 2 + BORDER * 2;
super.init();
terminal = new WidgetTerminal( minecraft, () -> m_computer, m_termWidth, m_termHeight, 2, 2, 2, 2 );
terminalWrapper = new WidgetWrapper( terminal, 2 + 12 + guiLeft, 2 + 12 + guiTop, termPxWidth, termPxHeight );
terminal = new WidgetTerminal( minecraft, () -> computer, termWidth, termHeight, MARGIN, MARGIN, MARGIN, MARGIN );
terminalWrapper = new WidgetWrapper( terminal, MARGIN + BORDER + guiLeft, MARGIN + BORDER + guiTop, termPxWidth, termPxHeight );
children.add( terminalWrapper );
setFocused( terminalWrapper );
setListener( terminalWrapper );
}
@Override
public void removed()
public void onClose()
{
super.removed();
super.onClose();
children.remove( terminal );
terminal = null;
minecraft.keyboardListener.enableRepeatEvents( false );
@@ -113,66 +114,46 @@ public final class GuiComputer<T extends ContainerComputerBase> extends Containe
public boolean keyPressed( int key, int scancode, int modifiers )
{
// Forward the tab key to the terminal, rather than moving between controls.
if( key == GLFW.GLFW_KEY_TAB && getFocused() != null && getFocused() == terminalWrapper )
if( key == GLFW.GLFW_KEY_TAB && getListener() != null && getListener() == terminalWrapper )
{
return getFocused().keyPressed( key, scancode, modifiers );
return getListener().keyPressed( key, scancode, modifiers );
}
return super.keyPressed( key, scancode, modifiers );
}
@Override
public void drawGuiContainerBackgroundLayer( float partialTicks, int mouseX, int mouseY )
public void drawGuiContainerBackgroundLayer( @Nonnull MatrixStack stack, float partialTicks, int mouseX, int mouseY )
{
// Work out where to draw
int startX = terminalWrapper.getX() - 2;
int startY = terminalWrapper.getY() - 2;
int endX = startX + terminalWrapper.getWidth() + 4;
int endY = startY + terminalWrapper.getHeight() + 4;
// Draw terminal
terminal.draw( terminalWrapper.getX(), terminalWrapper.getY() );
// Draw a border around the terminal
RenderSystem.color4f( 1.0f, 1.0f, 1.0f, 1.0f );
switch( m_family )
{
case NORMAL:
default:
minecraft.getTextureManager().bindTexture( BACKGROUND_NORMAL );
break;
case ADVANCED:
minecraft.getTextureManager().bindTexture( BACKGROUND_ADVANCED );
break;
case COMMAND:
minecraft.getTextureManager().bindTexture( BACKGROUND_COMMAND );
break;
}
blit( startX - 12, startY - 12, 12, 28, 12, 12 );
blit( startX - 12, endY, 12, 40, 12, 12 );
blit( endX, startY - 12, 24, 28, 12, 12 );
blit( endX, endY, 24, 40, 12, 12 );
blit( startX, startY - 12, 0, 0, endX - startX, 12 );
blit( startX, endY, 0, 12, endX - startX, 12 );
blit( startX - 12, startY, 0, 28, 12, endY - startY );
blit( endX, startY, 36, 28, 12, endY - startY );
RenderSystem.color4f( 1, 1, 1, 1 );
minecraft.getTextureManager().bindTexture( ComputerBorderRenderer.getTexture( family ) );
ComputerBorderRenderer.render(
terminalWrapper.getX() - MARGIN, terminalWrapper.getY() - MARGIN, getBlitOffset(),
terminalWrapper.getWidth() + MARGIN * 2, terminalWrapper.getHeight() + MARGIN * 2
);
}
@Override
public void render( int mouseX, int mouseY, float partialTicks )
public void render( @Nonnull MatrixStack stack, int mouseX, int mouseY, float partialTicks )
{
renderBackground();
super.render( mouseX, mouseY, partialTicks );
renderHoveredToolTip( mouseX, mouseY );
super.render( stack, mouseX, mouseY, partialTicks );
func_230459_a_( stack, mouseX, mouseY );
}
@Override
public boolean mouseDragged( double x, double y, int button, double deltaX, double deltaY )
{
return (getFocused() != null && getFocused().mouseDragged( x, y, button, deltaX, deltaY ))
return (getListener() != null && getListener().mouseDragged( x, y, button, deltaX, deltaY ))
|| super.mouseDragged( x, y, button, deltaX, deltaY );
}
@Override
protected void drawGuiContainerForegroundLayer( @Nonnull MatrixStack transform, int mouseX, int mouseY )
{
// Skip rendering labels.
}
}

View File

@@ -5,6 +5,7 @@
*/
package dan200.computercraft.client.gui;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem;
import dan200.computercraft.shared.peripheral.diskdrive.ContainerDiskDrive;
import net.minecraft.client.gui.screen.inventory.ContainerScreen;
@@ -12,6 +13,8 @@ import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.ITextComponent;
import javax.annotation.Nonnull;
public class GuiDiskDrive extends ContainerScreen<ContainerDiskDrive>
{
private static final ResourceLocation BACKGROUND = new ResourceLocation( "computercraft", "textures/gui/disk_drive.png" );
@@ -22,26 +25,18 @@ public class GuiDiskDrive extends ContainerScreen<ContainerDiskDrive>
}
@Override
protected void drawGuiContainerForegroundLayer( int mouseX, int mouseY )
{
String title = this.title.getFormattedText();
font.drawString( title, (xSize - font.getStringWidth( title )) / 2.0f, 6, 0x404040 );
font.drawString( title, 8, ySize - 96 + 2, 0x404040 );
}
@Override
protected void drawGuiContainerBackgroundLayer( float partialTicks, int mouseX, int mouseY )
protected void drawGuiContainerBackgroundLayer( @Nonnull MatrixStack transform, float partialTicks, int mouseX, int mouseY )
{
RenderSystem.color4f( 1.0F, 1.0F, 1.0F, 1.0F );
minecraft.getTextureManager().bindTexture( BACKGROUND );
blit( guiLeft, guiTop, 0, 0, xSize, ySize );
blit( transform, guiLeft, guiTop, 0, 0, xSize, ySize );
}
@Override
public void render( int mouseX, int mouseY, float partialTicks )
public void render( @Nonnull MatrixStack transform, int mouseX, int mouseY, float partialTicks )
{
renderBackground();
super.render( mouseX, mouseY, partialTicks );
renderHoveredToolTip( mouseX, mouseY );
renderBackground( transform );
super.render( transform, mouseX, mouseY, partialTicks );
func_230459_a_( transform, mouseX, mouseY );
}
}

View File

@@ -5,14 +5,16 @@
*/
package dan200.computercraft.client.gui;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem;
import dan200.computercraft.shared.peripheral.printer.ContainerPrinter;
import net.minecraft.client.gui.screen.inventory.ContainerScreen;
import net.minecraft.client.resources.I18n;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.ITextComponent;
import javax.annotation.Nonnull;
public class GuiPrinter extends ContainerScreen<ContainerPrinter>
{
private static final ResourceLocation BACKGROUND = new ResourceLocation( "computercraft", "textures/gui/printer.png" );
@@ -22,29 +24,29 @@ public class GuiPrinter extends ContainerScreen<ContainerPrinter>
super( container, player, title );
}
@Override
/*@Override
protected void drawGuiContainerForegroundLayer( int mouseX, int mouseY )
{
String title = getTitle().getFormattedText();
font.drawString( title, (xSize - font.getStringWidth( title )) / 2.0f, 6, 0x404040 );
font.drawString( I18n.format( "container.inventory" ), 8, ySize - 96 + 2, 0x404040 );
}
}*/
@Override
protected void drawGuiContainerBackgroundLayer( float partialTicks, int mouseX, int mouseY )
protected void drawGuiContainerBackgroundLayer( @Nonnull MatrixStack transform, float partialTicks, int mouseX, int mouseY )
{
RenderSystem.color4f( 1.0F, 1.0F, 1.0F, 1.0F );
minecraft.getTextureManager().bindTexture( BACKGROUND );
blit( guiLeft, guiTop, 0, 0, xSize, ySize );
blit( transform, guiLeft, guiTop, 0, 0, xSize, ySize );
if( getContainer().isPrinting() ) blit( guiLeft + 34, guiTop + 21, 176, 0, 25, 45 );
if( getContainer().isPrinting() ) blit( transform, guiLeft + 34, guiTop + 21, 176, 0, 25, 45 );
}
@Override
public void render( int mouseX, int mouseY, float partialTicks )
public void render( @Nonnull MatrixStack stack, int mouseX, int mouseY, float partialTicks )
{
renderBackground();
super.render( mouseX, mouseY, partialTicks );
renderHoveredToolTip( mouseX, mouseY );
renderBackground( stack );
super.render( stack, mouseX, mouseY, partialTicks );
func_230459_a_( stack, mouseX, mouseY );
}
}

View File

@@ -5,6 +5,7 @@
*/
package dan200.computercraft.client.gui;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem;
import dan200.computercraft.core.terminal.TextBuffer;
import dan200.computercraft.shared.common.ContainerHeldItem;
@@ -12,18 +13,17 @@ import dan200.computercraft.shared.media.items.ItemPrintout;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screen.inventory.ContainerScreen;
import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.Matrix4f;
import net.minecraft.client.renderer.TransformationMatrix;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.util.math.vector.Matrix4f;
import net.minecraft.util.text.ITextComponent;
import org.lwjgl.glfw.GLFW;
import javax.annotation.Nonnull;
import static dan200.computercraft.client.render.PrintoutRenderer.*;
public class GuiPrintout extends ContainerScreen<ContainerHeldItem>
{
private static final Matrix4f IDENTITY = TransformationMatrix.identity().getMatrix();
private final boolean m_book;
private final int m_pages;
private final TextBuffer[] m_text;
@@ -91,27 +91,33 @@ public class GuiPrintout extends ContainerScreen<ContainerHeldItem>
}
@Override
public void drawGuiContainerBackgroundLayer( float partialTicks, int mouseX, int mouseY )
protected void drawGuiContainerBackgroundLayer( @Nonnull MatrixStack transform, float partialTicks, int mouseX, int mouseY )
{
// Draw the printout
RenderSystem.color4f( 1.0f, 1.0f, 1.0f, 1.0f );
RenderSystem.enableDepthTest();
IRenderTypeBuffer.Impl renderer = Minecraft.getInstance().getRenderTypeBuffers().getBufferSource();
drawBorder( IDENTITY, renderer, guiLeft, guiTop, getBlitOffset(), m_page, m_pages, m_book );
drawText( IDENTITY, renderer, guiLeft + X_TEXT_MARGIN, guiTop + Y_TEXT_MARGIN, ItemPrintout.LINES_PER_PAGE * m_page, m_text, m_colours );
Matrix4f matrix = transform.getLast().getMatrix();
drawBorder( matrix, renderer, guiLeft, guiTop, getBlitOffset(), m_page, m_pages, m_book );
drawText( matrix, renderer, guiLeft + X_TEXT_MARGIN, guiTop + Y_TEXT_MARGIN, ItemPrintout.LINES_PER_PAGE * m_page, m_text, m_colours );
renderer.finish();
}
@Override
public void render( int mouseX, int mouseY, float partialTicks )
public void render( @Nonnull MatrixStack stack, int mouseX, int mouseY, float partialTicks )
{
// We must take the background further back in order to not overlap with our printed pages.
setBlitOffset( getBlitOffset() - 1 );
renderBackground();
renderBackground( stack );
setBlitOffset( getBlitOffset() + 1 );
super.render( mouseX, mouseY, partialTicks );
renderHoveredToolTip( mouseX, mouseY );
super.render( stack, mouseX, mouseY, partialTicks );
}
@Override
protected void drawGuiContainerForegroundLayer( @Nonnull MatrixStack transform, int mouseX, int mouseY )
{
// Skip rendering labels.
}
}

View File

@@ -5,6 +5,7 @@
*/
package dan200.computercraft.client.gui;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.client.gui.widgets.WidgetTerminal;
@@ -18,6 +19,8 @@ import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.ITextComponent;
import org.lwjgl.glfw.GLFW;
import javax.annotation.Nonnull;
public class GuiTurtle extends ContainerScreen<ContainerTurtle>
{
private static final ResourceLocation BACKGROUND_NORMAL = new ResourceLocation( "computercraft", "textures/gui/turtle_normal.png" );
@@ -49,25 +52,25 @@ public class GuiTurtle extends ContainerScreen<ContainerTurtle>
super.init();
minecraft.keyboardListener.enableRepeatEvents( true );
int termPxWidth = ComputerCraft.terminalWidth_turtle * FixedWidthFontRenderer.FONT_WIDTH;
int termPxHeight = ComputerCraft.terminalHeight_turtle * FixedWidthFontRenderer.FONT_HEIGHT;
int termPxWidth = ComputerCraft.turtleTermWidth * FixedWidthFontRenderer.FONT_WIDTH;
int termPxHeight = ComputerCraft.turtleTermHeight * FixedWidthFontRenderer.FONT_HEIGHT;
terminal = new WidgetTerminal(
minecraft, () -> m_computer,
ComputerCraft.terminalWidth_turtle,
ComputerCraft.terminalHeight_turtle,
ComputerCraft.turtleTermWidth,
ComputerCraft.turtleTermHeight,
2, 2, 2, 2
);
terminalWrapper = new WidgetWrapper( terminal, 2 + 8 + guiLeft, 2 + 8 + guiTop, termPxWidth, termPxHeight );
children.add( terminalWrapper );
setFocused( terminalWrapper );
setListener( terminalWrapper );
}
@Override
public void removed()
public void onClose()
{
super.removed();
super.onClose();
children.remove( terminal );
terminal = null;
minecraft.keyboardListener.enableRepeatEvents( false );
@@ -84,55 +87,58 @@ public class GuiTurtle extends ContainerScreen<ContainerTurtle>
public boolean keyPressed( int key, int scancode, int modifiers )
{
// Forward the tab key to the terminal, rather than moving between controls.
if( key == GLFW.GLFW_KEY_TAB && getFocused() != null && getFocused() == terminalWrapper )
if( key == GLFW.GLFW_KEY_TAB && getListener() != null && getListener() == terminalWrapper )
{
return getFocused().keyPressed( key, scancode, modifiers );
return getListener().keyPressed( key, scancode, modifiers );
}
return super.keyPressed( key, scancode, modifiers );
}
private void drawSelectionSlot( boolean advanced )
{
// Draw selection slot
int slot = m_container.getSelectedSlot();
if( slot >= 0 )
{
RenderSystem.color4f( 1.0F, 1.0F, 1.0F, 1.0F );
int slotX = slot % 4;
int slotY = slot / 4;
minecraft.getTextureManager().bindTexture( advanced ? BACKGROUND_ADVANCED : BACKGROUND_NORMAL );
blit( guiLeft + ContainerTurtle.TURTLE_START_X - 2 + slotX * 18, guiTop + ContainerTurtle.PLAYER_START_Y - 2 + slotY * 18, 0, 217, 24, 24 );
}
}
@Override
protected void drawGuiContainerBackgroundLayer( float partialTicks, int mouseX, int mouseY )
protected void drawGuiContainerBackgroundLayer( @Nonnull MatrixStack transform, float partialTicks, int mouseX, int mouseY )
{
// Draw term
boolean advanced = m_family == ComputerFamily.ADVANCED;
ResourceLocation texture = m_family == ComputerFamily.ADVANCED ? BACKGROUND_ADVANCED : BACKGROUND_NORMAL;
terminal.draw( terminalWrapper.getX(), terminalWrapper.getY() );
// Draw border/inventory
RenderSystem.color4f( 1.0F, 1.0F, 1.0F, 1.0F );
minecraft.getTextureManager().bindTexture( advanced ? BACKGROUND_ADVANCED : BACKGROUND_NORMAL );
blit( guiLeft, guiTop, 0, 0, xSize, ySize );
minecraft.getTextureManager().bindTexture( texture );
blit( transform, guiLeft, guiTop, 0, 0, xSize, ySize );
drawSelectionSlot( advanced );
// Draw selection slot
int slot = m_container.getSelectedSlot();
if( slot >= 0 )
{
int slotX = slot % 4;
int slotY = slot / 4;
blit( transform,
guiLeft + ContainerTurtle.TURTLE_START_X - 2 + slotX * 18,
guiTop + ContainerTurtle.PLAYER_START_Y - 2 + slotY * 18,
0, 217, 24, 24
);
}
}
@Override
public void render( int mouseX, int mouseY, float partialTicks )
public void render( @Nonnull MatrixStack stack, int mouseX, int mouseY, float partialTicks )
{
renderBackground();
super.render( mouseX, mouseY, partialTicks );
renderHoveredToolTip( mouseX, mouseY );
renderBackground( stack );
super.render( stack, mouseX, mouseY, partialTicks );
func_230459_a_( stack, mouseX, mouseY );
}
@Override
public boolean mouseDragged( double x, double y, int button, double deltaX, double deltaY )
{
return (getFocused() != null && getFocused().mouseDragged( x, y, button, deltaX, deltaY ))
return (getListener() != null && getListener().mouseDragged( x, y, button, deltaX, deltaY ))
|| super.mouseDragged( x, y, button, deltaX, deltaY );
}
@Override
protected void drawGuiContainerForegroundLayer( @Nonnull MatrixStack transform, int mouseX, int mouseY )
{
// Skip rendering labels.
}
}

View File

@@ -10,20 +10,20 @@ import dan200.computercraft.client.gui.*;
import dan200.computercraft.client.render.TileEntityMonitorRenderer;
import dan200.computercraft.client.render.TileEntityTurtleRenderer;
import dan200.computercraft.client.render.TurtlePlayerRenderer;
import dan200.computercraft.shared.common.ContainerHeldItem;
import dan200.computercraft.shared.Registry;
import dan200.computercraft.shared.common.IColouredItem;
import dan200.computercraft.shared.computer.inventory.ContainerComputer;
import dan200.computercraft.shared.computer.inventory.ContainerViewComputer;
import dan200.computercraft.shared.peripheral.diskdrive.ContainerDiskDrive;
import dan200.computercraft.shared.peripheral.monitor.ClientMonitor;
import dan200.computercraft.shared.peripheral.monitor.TileMonitor;
import dan200.computercraft.shared.peripheral.printer.ContainerPrinter;
import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer;
import dan200.computercraft.shared.turtle.blocks.TileTurtle;
import dan200.computercraft.shared.turtle.core.TurtlePlayer;
import dan200.computercraft.shared.turtle.inventory.ContainerTurtle;
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
import net.minecraft.client.gui.ScreenManager;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.RenderTypeLookup;
import net.minecraft.item.IItemPropertyGetter;
import net.minecraft.item.Item;
import net.minecraft.item.ItemModelsProperties;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
@@ -32,6 +32,8 @@ import net.minecraftforge.fml.client.registry.RenderingRegistry;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import java.util.function.Supplier;
@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, value = Dist.CLIENT, bus = Mod.EventBusSubscriber.Bus.MOD )
public final class ComputerCraftProxyClient
{
@@ -41,36 +43,55 @@ public final class ComputerCraftProxyClient
registerContainers();
// While turtles themselves are not transparent, their upgrades may be.
RenderTypeLookup.setRenderLayer( ComputerCraft.Blocks.turtleNormal, RenderType.getTranslucent() );
RenderTypeLookup.setRenderLayer( ComputerCraft.Blocks.turtleAdvanced, RenderType.getTranslucent() );
RenderTypeLookup.setRenderLayer( Registry.ModBlocks.TURTLE_NORMAL.get(), RenderType.getTranslucent() );
RenderTypeLookup.setRenderLayer( Registry.ModBlocks.TURTLE_ADVANCED.get(), RenderType.getTranslucent() );
// Monitors' textures have transparent fronts and so count as cutouts.
RenderTypeLookup.setRenderLayer( ComputerCraft.Blocks.monitorNormal, RenderType.getCutout() );
RenderTypeLookup.setRenderLayer( ComputerCraft.Blocks.monitorAdvanced, RenderType.getCutout() );
RenderTypeLookup.setRenderLayer( Registry.ModBlocks.MONITOR_NORMAL.get(), RenderType.getCutout() );
RenderTypeLookup.setRenderLayer( Registry.ModBlocks.MONITOR_ADVANCED.get(), RenderType.getCutout() );
// Setup TESRs
ClientRegistry.bindTileEntityRenderer( TileMonitor.FACTORY_NORMAL, TileEntityMonitorRenderer::new );
ClientRegistry.bindTileEntityRenderer( TileMonitor.FACTORY_ADVANCED, TileEntityMonitorRenderer::new );
ClientRegistry.bindTileEntityRenderer( TileTurtle.FACTORY_NORMAL, TileEntityTurtleRenderer::new );
ClientRegistry.bindTileEntityRenderer( TileTurtle.FACTORY_ADVANCED, TileEntityTurtleRenderer::new );
ClientRegistry.bindTileEntityRenderer( Registry.ModTiles.MONITOR_NORMAL.get(), TileEntityMonitorRenderer::new );
ClientRegistry.bindTileEntityRenderer( Registry.ModTiles.MONITOR_ADVANCED.get(), TileEntityMonitorRenderer::new );
ClientRegistry.bindTileEntityRenderer( Registry.ModTiles.TURTLE_NORMAL.get(), TileEntityTurtleRenderer::new );
ClientRegistry.bindTileEntityRenderer( Registry.ModTiles.TURTLE_ADVANCED.get(), TileEntityTurtleRenderer::new );
// TODO: ClientRegistry.bindTileEntityRenderer( TileCable.FACTORY, x -> new TileEntityCableRenderer() );
RenderingRegistry.registerEntityRenderingHandler( TurtlePlayer.TYPE, TurtlePlayerRenderer::new );
RenderingRegistry.registerEntityRenderingHandler( Registry.ModEntities.TURTLE_PLAYER.get(), TurtlePlayerRenderer::new );
registerItemProperty( "state",
( stack, world, player ) -> ItemPocketComputer.getState( stack ).ordinal(),
Registry.ModItems.POCKET_COMPUTER_NORMAL, Registry.ModItems.POCKET_COMPUTER_ADVANCED
);
registerItemProperty( "state",
( stack, world, player ) -> IColouredItem.getColourBasic( stack ) != -1 ? 1 : 0,
Registry.ModItems.POCKET_COMPUTER_NORMAL, Registry.ModItems.POCKET_COMPUTER_ADVANCED
);
}
@SafeVarargs
private static void registerItemProperty( String name, IItemPropertyGetter getter, Supplier<? extends Item>... items )
{
ResourceLocation id = new ResourceLocation( ComputerCraft.MOD_ID, name );
for( Supplier<? extends Item> item : items )
{
ItemModelsProperties.func_239418_a_( item.get(), id, getter );
}
}
private static void registerContainers()
{
// My IDE doesn't think so, but we do actually need these generics.
ScreenManager.<ContainerComputer, GuiComputer<ContainerComputer>>registerFactory( ContainerComputer.TYPE, GuiComputer::create );
ScreenManager.<ContainerPocketComputer, GuiComputer<ContainerPocketComputer>>registerFactory( ContainerPocketComputer.TYPE, GuiComputer::createPocket );
ScreenManager.registerFactory( ContainerTurtle.TYPE, GuiTurtle::new );
ScreenManager.<ContainerComputer, GuiComputer<ContainerComputer>>registerFactory( Registry.ModContainers.COMPUTER.get(), GuiComputer::create );
ScreenManager.<ContainerPocketComputer, GuiComputer<ContainerPocketComputer>>registerFactory( Registry.ModContainers.POCKET_COMPUTER.get(), GuiComputer::createPocket );
ScreenManager.registerFactory( Registry.ModContainers.TURTLE.get(), GuiTurtle::new );
ScreenManager.registerFactory( ContainerPrinter.TYPE, GuiPrinter::new );
ScreenManager.registerFactory( ContainerDiskDrive.TYPE, GuiDiskDrive::new );
ScreenManager.registerFactory( ContainerHeldItem.PRINTOUT_TYPE, GuiPrintout::new );
ScreenManager.registerFactory( Registry.ModContainers.PRINTER.get(), GuiPrinter::new );
ScreenManager.registerFactory( Registry.ModContainers.DISK_DRIVE.get(), GuiDiskDrive::new );
ScreenManager.registerFactory( Registry.ModContainers.PRINTOUT.get(), GuiPrintout::new );
ScreenManager.<ContainerViewComputer, GuiComputer<ContainerViewComputer>>registerFactory( ContainerViewComputer.TYPE, GuiComputer::createView );
ScreenManager.<ContainerViewComputer, GuiComputer<ContainerViewComputer>>registerFactory( Registry.ModContainers.VIEW_COMPUTER.get(), GuiComputer::createView );
}
@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, value = Dist.CLIENT )

View File

@@ -8,19 +8,20 @@ package dan200.computercraft.client.render;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.vertex.IVertexBuilder;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.Registry;
import dan200.computercraft.shared.peripheral.modem.wired.BlockCable;
import dan200.computercraft.shared.peripheral.modem.wired.CableShapes;
import dan200.computercraft.shared.util.WorldUtil;
import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.ActiveRenderInfo;
import net.minecraft.client.renderer.Matrix4f;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.entity.Entity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.util.math.vector.Matrix4f;
import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.DrawHighlightEvent;
@@ -51,7 +52,7 @@ public final class CableHighlightRenderer
BlockState state = world.getBlockState( pos );
// We only care about instances with both cable and modem.
if( state.getBlock() != ComputerCraft.Blocks.cable || state.get( BlockCable.MODEM ).getFacing() == null || !state.get( BlockCable.CABLE ) )
if( state.getBlock() != Registry.ModBlocks.CABLE.get() || state.get( BlockCable.MODEM ).getFacing() == null || !state.get( BlockCable.CABLE ) )
{
return;
}
@@ -62,7 +63,7 @@ public final class CableHighlightRenderer
? CableShapes.getModemShape( state )
: CableShapes.getCableShape( state );
Vec3d cameraPos = info.getProjectedView();
Vector3d cameraPos = info.getProjectedView();
double xOffset = pos.getX() - cameraPos.getX();
double yOffset = pos.getY() - cameraPos.getY();
double zOffset = pos.getZ() - cameraPos.getZ();

View File

@@ -0,0 +1,175 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.client.render;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.IVertexBuilder;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.computer.core.ComputerFamily;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.vector.Matrix4f;
import org.lwjgl.opengl.GL11;
import javax.annotation.Nonnull;
public class ComputerBorderRenderer
{
public static final ResourceLocation BACKGROUND_NORMAL = new ResourceLocation( ComputerCraft.MOD_ID, "textures/gui/corners_normal.png" );
public static final ResourceLocation BACKGROUND_ADVANCED = new ResourceLocation( ComputerCraft.MOD_ID, "textures/gui/corners_advanced.png" );
public static final ResourceLocation BACKGROUND_COMMAND = new ResourceLocation( ComputerCraft.MOD_ID, "textures/gui/corners_command.png" );
public static final ResourceLocation BACKGROUND_COLOUR = new ResourceLocation( ComputerCraft.MOD_ID, "textures/gui/corners_colour.png" );
private static final Matrix4f IDENTITY = new Matrix4f();
static
{
IDENTITY.setIdentity();
}
/**
* The margin between the terminal and its border.
*/
public static final int MARGIN = 2;
/**
* The width of the terminal border.
*/
public static final int BORDER = 12;
private static final int CORNER_TOP_Y = 28;
private static final int CORNER_BOTTOM_Y = CORNER_TOP_Y + BORDER;
private static final int CORNER_LEFT_X = BORDER;
private static final int CORNER_RIGHT_X = CORNER_LEFT_X + BORDER;
private static final int BORDER_RIGHT_X = 36;
private static final int GAP = 4;
private static final float TEX_SCALE = 1 / 256.0f;
private final Matrix4f transform;
private final IVertexBuilder builder;
private final int z;
private final float r, g, b;
public ComputerBorderRenderer( Matrix4f transform, IVertexBuilder builder, int z, float r, float g, float b )
{
this.transform = transform;
this.builder = builder;
this.z = z;
this.r = r;
this.g = g;
this.b = b;
}
@Nonnull
public static ResourceLocation getTexture( @Nonnull ComputerFamily family )
{
switch( family )
{
case NORMAL:
default:
return BACKGROUND_NORMAL;
case ADVANCED:
return BACKGROUND_ADVANCED;
case COMMAND:
return BACKGROUND_COMMAND;
}
}
public static void render( int x, int y, int z, int width, int height )
{
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder buffer = tessellator.getBuffer();
buffer.begin( GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR_TEX );
render( IDENTITY, buffer, x, y, z, width, height );
RenderSystem.enableAlphaTest();
tessellator.draw();
}
public static void render( Matrix4f transform, IVertexBuilder buffer, int x, int y, int z, int width, int height )
{
render( transform, buffer, x, y, z, width, height, 1, 1, 1 );
}
public static void render( Matrix4f transform, IVertexBuilder buffer, int x, int y, int z, int width, int height, float r, float g, float b )
{
render( transform, buffer, x, y, z, width, height, 0, r, g, b );
}
public static void render( Matrix4f transform, IVertexBuilder buffer, int x, int y, int z, int width, int height, int borderHeight, float r, float g, float b )
{
new ComputerBorderRenderer( transform, buffer, z, r, g, b ).doRender( x, y, width, height, borderHeight );
}
public void doRender( int x, int y, int width, int height, int bottomHeight )
{
int endX = x + width;
int endY = y + height;
// Vertical bars
renderLine( x - BORDER, y, 0, CORNER_TOP_Y, BORDER, endY - y );
renderLine( endX, y, BORDER_RIGHT_X, CORNER_TOP_Y, BORDER, endY - y );
// Top bar
renderLine( x, y - BORDER, 0, 0, endX - x, BORDER );
renderCorner( x - BORDER, y - BORDER, CORNER_LEFT_X, CORNER_TOP_Y );
renderCorner( endX, y - BORDER, CORNER_RIGHT_X, CORNER_TOP_Y );
// Bottom bar. We allow for drawing a stretched version, which allows for additional elements (such as the
// pocket computer's lights).
if( bottomHeight <= 0 )
{
renderLine( x, endY, 0, BORDER, endX - x, BORDER );
renderCorner( x - BORDER, endY, CORNER_LEFT_X, CORNER_BOTTOM_Y );
renderCorner( endX, endY, CORNER_RIGHT_X, CORNER_BOTTOM_Y );
}
else
{
// Bottom left, middle, right. We do this in three portions: the top inner corners, an extended region for
// lights, and then the bottom outer corners.
renderTexture( x - BORDER, endY, CORNER_LEFT_X, CORNER_BOTTOM_Y, BORDER, BORDER / 2 );
renderTexture( x, endY, 0, BORDER, width, BORDER / 2, BORDER, BORDER / 2 );
renderTexture( endX, endY, CORNER_RIGHT_X, CORNER_BOTTOM_Y, BORDER, BORDER / 2 );
renderTexture( x - BORDER, endY + BORDER / 2, CORNER_LEFT_X, CORNER_BOTTOM_Y + GAP, BORDER, bottomHeight, BORDER, GAP );
renderTexture( x, endY + BORDER / 2, 0, BORDER + GAP, width, bottomHeight, BORDER, GAP );
renderTexture( endX, endY + BORDER / 2, CORNER_RIGHT_X, CORNER_BOTTOM_Y + GAP, BORDER, bottomHeight, BORDER, GAP );
renderTexture( x - BORDER, endY + bottomHeight + BORDER / 2, CORNER_LEFT_X, CORNER_BOTTOM_Y + BORDER / 2, BORDER, BORDER / 2 );
renderTexture( x, endY + bottomHeight + BORDER / 2, 0, BORDER + BORDER / 2, width, BORDER / 2 );
renderTexture( endX, endY + bottomHeight + BORDER / 2, CORNER_RIGHT_X, CORNER_BOTTOM_Y + BORDER / 2, BORDER, BORDER / 2 );
}
}
private void renderCorner( int x, int y, int u, int v )
{
renderTexture( x, y, u, v, BORDER, BORDER, BORDER, BORDER );
}
private void renderLine( int x, int y, int u, int v, int width, int height )
{
renderTexture( x, y, u, v, width, height, BORDER, BORDER );
}
private void renderTexture( int x, int y, int u, int v, int width, int height )
{
renderTexture( x, y, u, v, width, height, width, height );
}
private void renderTexture( int x, int y, int u, int v, int width, int height, int textureWidth, int textureHeight )
{
builder.pos( transform, x, y + height, z ).color( r, g, b, 1.0f ).tex( u * TEX_SCALE, (v + textureHeight) * TEX_SCALE ).endVertex();
builder.pos( transform, x + width, y + height, z ).color( r, g, b, 1.0f ).tex( (u + textureWidth) * TEX_SCALE, (v + textureHeight) * TEX_SCALE ).endVertex();
builder.pos( transform, x + width, y, z ).color( r, g, b, 1.0f ).tex( (u + textureWidth) * TEX_SCALE, v * TEX_SCALE ).endVertex();
builder.pos( transform, x, y, z ).color( r, g, b, 1.0f ).tex( u * TEX_SCALE, v * TEX_SCALE ).endVertex();
}
}

View File

@@ -10,12 +10,12 @@ import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.player.AbstractClientPlayerEntity;
import net.minecraft.client.renderer.FirstPersonRenderer;
import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.Vector3f;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Hand;
import net.minecraft.util.HandSide;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.vector.Vector3f;
public abstract class ItemMapLikeRenderer
{

View File

@@ -7,7 +7,6 @@ package dan200.computercraft.client.render;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.IVertexBuilder;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.client.gui.FixedWidthFontRenderer;
import dan200.computercraft.core.terminal.Terminal;
@@ -16,9 +15,13 @@ import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
import dan200.computercraft.shared.util.Colour;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.*;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.vector.Matrix4f;
import net.minecraft.util.math.vector.Vector3f;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.RenderHandEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
@@ -27,7 +30,8 @@ import org.lwjgl.opengl.GL11;
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_HEIGHT;
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_WIDTH;
import static dan200.computercraft.client.gui.GuiComputer.*;
import static dan200.computercraft.client.render.ComputerBorderRenderer.BORDER;
import static dan200.computercraft.client.render.ComputerBorderRenderer.MARGIN;
/**
* Emulates map rendering for pocket computers.
@@ -35,8 +39,6 @@ import static dan200.computercraft.client.gui.GuiComputer.*;
@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, value = Dist.CLIENT )
public final class ItemPocketRenderer extends ItemMapLikeRenderer
{
private static final int MARGIN = 2;
private static final int FRAME = 12;
private static final int LIGHT_HEIGHT = 8;
private static final ItemPocketRenderer INSTANCE = new ItemPocketRenderer();
@@ -67,8 +69,8 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
int termWidth, termHeight;
if( terminal == null )
{
termWidth = ComputerCraft.terminalWidth_pocketComputer;
termHeight = ComputerCraft.terminalHeight_pocketComputer;
termWidth = ComputerCraft.pocketTermWidth;
termHeight = ComputerCraft.pocketTermHeight;
}
else
{
@@ -86,7 +88,7 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
transform.rotate( Vector3f.ZP.rotationDegrees( 180f ) );
transform.scale( 0.5f, 0.5f, 0.5f );
float scale = 0.75f / Math.max( width + FRAME * 2, height + FRAME * 2 + LIGHT_HEIGHT );
float scale = 0.75f / Math.max( width + BORDER * 2, height + BORDER * 2 + LIGHT_HEIGHT );
transform.scale( scale, scale, 0 );
transform.translate( -0.5 * width, -0.5 * height, 0 );
@@ -117,10 +119,8 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
private static void renderFrame( Matrix4f transform, ComputerFamily family, int colour, int width, int height )
{
Minecraft.getInstance().getTextureManager().bindTexture( colour != -1
? BACKGROUND_COLOUR
: family == ComputerFamily.NORMAL ? BACKGROUND_NORMAL : BACKGROUND_ADVANCED
);
Minecraft.getInstance().getTextureManager()
.bindTexture( colour != -1 ? ComputerBorderRenderer.BACKGROUND_COLOUR : ComputerBorderRenderer.getTexture( family ) );
float r = ((colour >>> 16) & 0xFF) / 255.0f;
float g = ((colour >>> 8) & 0xFF) / 255.0f;
@@ -130,28 +130,7 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
BufferBuilder buffer = tessellator.getBuffer();
buffer.begin( GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR_TEX );
// Top left, middle, right
renderTexture( transform, buffer, -FRAME, -FRAME, 12, 28, FRAME, FRAME, r, g, b );
renderTexture( transform, buffer, 0, -FRAME, 0, 0, width, FRAME, r, g, b );
renderTexture( transform, buffer, width, -FRAME, 24, 28, FRAME, FRAME, r, g, b );
// Left and bright border
renderTexture( transform, buffer, -FRAME, 0, 0, 28, FRAME, height, r, g, b );
renderTexture( transform, buffer, width, 0, 36, 28, FRAME, height, r, g, b );
// Bottom left, middle, right. We do this in three portions: the top inner corners, an extended region for
// lights, and then the bottom outer corners.
renderTexture( transform, buffer, -FRAME, height, 12, 40, FRAME, FRAME / 2, r, g, b );
renderTexture( transform, buffer, 0, height, 0, 12, width, FRAME / 2, r, g, b );
renderTexture( transform, buffer, width, height, 24, 40, FRAME, FRAME / 2, r, g, b );
renderTexture( transform, buffer, -FRAME, height + FRAME / 2, 12, 44, FRAME, LIGHT_HEIGHT, FRAME, 4, r, g, b );
renderTexture( transform, buffer, 0, height + FRAME / 2, 0, 16, width, LIGHT_HEIGHT, FRAME, 4, r, g, b );
renderTexture( transform, buffer, width, height + FRAME / 2, 24, 44, FRAME, LIGHT_HEIGHT, FRAME, 4, r, g, b );
renderTexture( transform, buffer, -FRAME, height + LIGHT_HEIGHT + FRAME / 2, 12, 40 + FRAME / 2, FRAME, FRAME / 2, r, g, b );
renderTexture( transform, buffer, 0, height + LIGHT_HEIGHT + FRAME / 2, 0, 12 + FRAME / 2, width, FRAME / 2, r, g, b );
renderTexture( transform, buffer, width, height + LIGHT_HEIGHT + FRAME / 2, 24, 40 + FRAME / 2, FRAME, FRAME / 2, r, g, b );
ComputerBorderRenderer.render( transform, buffer, 0, 0, 0, width, height, LIGHT_HEIGHT, r, g, b );
tessellator.draw();
}
@@ -168,26 +147,12 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder buffer = tessellator.getBuffer();
buffer.begin( GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR );
buffer.pos( transform, width - LIGHT_HEIGHT * 2, height + LIGHT_HEIGHT + FRAME / 2.0f, 0 ).color( r, g, b, 1.0f ).endVertex();
buffer.pos( transform, width, height + LIGHT_HEIGHT + FRAME / 2.0f, 0 ).color( r, g, b, 1.0f ).endVertex();
buffer.pos( transform, width, height + FRAME / 2.0f, 0 ).color( r, g, b, 1.0f ).endVertex();
buffer.pos( transform, width - LIGHT_HEIGHT * 2, height + FRAME / 2.0f, 0 ).color( r, g, b, 1.0f ).endVertex();
buffer.pos( transform, width - LIGHT_HEIGHT * 2, height + LIGHT_HEIGHT + BORDER / 2.0f, 0 ).color( r, g, b, 1.0f ).endVertex();
buffer.pos( transform, width, height + LIGHT_HEIGHT + BORDER / 2.0f, 0 ).color( r, g, b, 1.0f ).endVertex();
buffer.pos( transform, width, height + BORDER / 2.0f, 0 ).color( r, g, b, 1.0f ).endVertex();
buffer.pos( transform, width - LIGHT_HEIGHT * 2, height + BORDER / 2.0f, 0 ).color( r, g, b, 1.0f ).endVertex();
tessellator.draw();
RenderSystem.enableTexture();
}
private static void renderTexture( Matrix4f transform, IVertexBuilder builder, int x, int y, int textureX, int textureY, int width, int height, float r, float g, float b )
{
renderTexture( transform, builder, x, y, textureX, textureY, width, height, width, height, r, g, b );
}
private static void renderTexture( Matrix4f transform, IVertexBuilder builder, int x, int y, int textureX, int textureY, int width, int height, int textureWidth, int textureHeight, float r, float g, float b )
{
float scale = 1 / 255.0f;
builder.pos( transform, x, y + height, 0 ).color( r, g, b, 1.0f ).tex( textureX * scale, (textureY + textureHeight) * scale ).endVertex();
builder.pos( transform, x + width, y + height, 0 ).color( r, g, b, 1.0f ).tex( (textureX + textureWidth) * scale, (textureY + textureHeight) * scale ).endVertex();
builder.pos( transform, x + width, y, 0 ).color( r, g, b, 1.0f ).tex( (textureX + textureWidth) * scale, textureY * scale ).endVertex();
builder.pos( transform, x, y, 0 ).color( r, g, b, 1.0f ).tex( textureX * scale, textureY * scale ).endVertex();
}
}

View File

@@ -9,9 +9,9 @@ import com.mojang.blaze3d.matrix.MatrixStack;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.media.items.ItemPrintout;
import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.Matrix4f;
import net.minecraft.client.renderer.Vector3f;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.vector.Matrix4f;
import net.minecraft.util.math.vector.Vector3f;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.RenderHandEvent;
import net.minecraftforge.client.event.RenderItemInFrameEvent;

View File

@@ -9,12 +9,12 @@ import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.vertex.IVertexBuilder;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.peripheral.monitor.TileMonitor;
import net.minecraft.client.renderer.Matrix4f;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.vector.Matrix4f;
import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.DrawHighlightEvent;
@@ -61,7 +61,7 @@ public final class MonitorHighlightRenderer
if( monitor.getYIndex() != monitor.getHeight() - 1 ) faces.remove( monitor.getDown() );
MatrixStack transformStack = event.getMatrix();
Vec3d cameraPos = event.getInfo().getProjectedView();
Vector3d cameraPos = event.getInfo().getProjectedView();
transformStack.push();
transformStack.translate( pos.getX() - cameraPos.getX(), pos.getY() - cameraPos.getY(), pos.getZ() - cameraPos.getZ() );

View File

@@ -12,8 +12,8 @@ import com.mojang.blaze3d.systems.RenderSystem;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.client.gui.FixedWidthFontRenderer;
import dan200.computercraft.shared.util.Palette;
import net.minecraft.client.renderer.Matrix4f;
import net.minecraft.client.renderer.texture.TextureUtil;
import net.minecraft.util.math.vector.Matrix4f;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL13;
import org.lwjgl.opengl.GL20;

View File

@@ -10,11 +10,11 @@ import dan200.computercraft.client.gui.FixedWidthFontRenderer;
import dan200.computercraft.core.terminal.TextBuffer;
import dan200.computercraft.shared.util.Palette;
import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.Matrix4f;
import net.minecraft.client.renderer.RenderState;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.vector.Matrix4f;
import org.lwjgl.opengl.GL11;
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_HEIGHT;

View File

@@ -17,13 +17,19 @@ import dan200.computercraft.shared.peripheral.monitor.MonitorRenderer;
import dan200.computercraft.shared.peripheral.monitor.TileMonitor;
import dan200.computercraft.shared.util.Colour;
import dan200.computercraft.shared.util.DirectionUtil;
import net.minecraft.client.renderer.*;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.GLAllocation;
import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.renderer.vertex.VertexBuffer;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.vector.Matrix4f;
import net.minecraft.util.math.vector.TransformationMatrix;
import net.minecraft.util.math.vector.Vector3f;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL13;
import org.lwjgl.opengl.GL20;

View File

@@ -19,8 +19,6 @@ import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.renderer.Atlases;
import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.Matrix4f;
import net.minecraft.client.renderer.Vector3f;
import net.minecraft.client.renderer.model.BakedQuad;
import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.client.renderer.model.ModelManager;
@@ -31,7 +29,9 @@ import net.minecraft.util.Direction;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.vector.Matrix4f;
import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.util.math.vector.Vector3f;
import net.minecraftforge.client.model.data.EmptyModelData;
import javax.annotation.Nonnull;
@@ -99,7 +99,7 @@ public class TileEntityTurtleRenderer extends TileEntityRenderer<TileTurtle>
transform.push();
// Setup the transform.
Vec3d offset = turtle.getRenderOffset( partialTicks );
Vector3d offset = turtle.getRenderOffset( partialTicks );
float yaw = turtle.getRenderYaw( partialTicks );
transform.translate( offset.x, offset.y, offset.z );

View File

@@ -57,16 +57,16 @@ public final class TurtleModelLoader implements IModelLoader<TurtleModelLoader.T
}
@Override
public Collection<Material> getTextures( IModelConfiguration owner, Function<ResourceLocation, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors )
public Collection<RenderMaterial> getTextures( IModelConfiguration owner, Function<ResourceLocation, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors )
{
Set<Material> materials = new HashSet<>();
Set<RenderMaterial> materials = new HashSet<>();
materials.addAll( modelGetter.apply( family ).getTextures( modelGetter, missingTextureErrors ) );
materials.addAll( modelGetter.apply( COLOUR_TURTLE_MODEL ).getTextures( modelGetter, missingTextureErrors ) );
return materials;
}
@Override
public IBakedModel bake( IModelConfiguration owner, ModelBakery bakery, Function<Material, TextureAtlasSprite> spriteGetter, IModelTransform transform, ItemOverrideList overrides, ResourceLocation modelLocation )
public IBakedModel bake( IModelConfiguration owner, ModelBakery bakery, Function<RenderMaterial, TextureAtlasSprite> spriteGetter, IModelTransform transform, ItemOverrideList overrides, ResourceLocation modelLocation )
{
return new TurtleSmartItemModel(
bakery.getBakedModel( family, transform, spriteGetter ),

View File

@@ -7,12 +7,12 @@ package dan200.computercraft.client.render;
import dan200.computercraft.api.client.TransformedModel;
import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.TransformationMatrix;
import net.minecraft.client.renderer.model.BakedQuad;
import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.client.renderer.model.ItemOverrideList;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.util.Direction;
import net.minecraft.util.math.vector.TransformationMatrix;
import net.minecraftforge.client.model.data.EmptyModelData;
import net.minecraftforge.client.model.data.IModelData;
import net.minecraftforge.client.model.pipeline.BakedQuadBuilder;

View File

@@ -7,7 +7,6 @@
package dan200.computercraft.client.render;
import com.mojang.blaze3d.matrix.MatrixStack;
import dan200.computercraft.client.gui.GuiComputer;
import dan200.computercraft.shared.turtle.core.TurtlePlayer;
import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.entity.EntityRenderer;
@@ -27,7 +26,7 @@ public class TurtlePlayerRenderer extends EntityRenderer<TurtlePlayer>
@Override
public ResourceLocation getEntityTexture( @Nonnull TurtlePlayer entity )
{
return GuiComputer.BACKGROUND_NORMAL;
return ComputerBorderRenderer.BACKGROUND_NORMAL;
}
@Override

View File

@@ -15,14 +15,14 @@ import dan200.computercraft.shared.util.Holiday;
import dan200.computercraft.shared.util.HolidayUtil;
import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.TransformationMatrix;
import net.minecraft.client.renderer.model.*;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.LivingEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Direction;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;
import net.minecraft.util.math.vector.TransformationMatrix;
import net.minecraftforge.client.model.data.IModelData;
import javax.annotation.Nonnull;
@@ -109,7 +109,7 @@ public class TurtleSmartItemModel implements IBakedModel
{
@Nonnull
@Override
public IBakedModel getModelWithOverrides( @Nonnull IBakedModel originalModel, @Nonnull ItemStack stack, @Nullable World world, @Nullable LivingEntity entity )
public IBakedModel func_239290_a_( @Nonnull IBakedModel originalModel, @Nonnull ItemStack stack, @Nullable ClientWorld world, @Nullable LivingEntity entity )
{
ItemTurtle turtle = (ItemTurtle) stack.getItem();
int colour = turtle.getColour( stack );

View File

@@ -28,6 +28,11 @@ import java.util.Map;
import java.util.OptionalLong;
import java.util.function.Function;
/**
* The FS API allows you to manipulate files and the filesystem.
*
* @cc.module fs
*/
public class FSAPI implements ILuaAPI
{
private final IAPIEnvironment environment;
@@ -56,6 +61,13 @@ public class FSAPI implements ILuaAPI
fileSystem = null;
}
/**
* Returns a list of files in a directory.
*
* @param path The path to list.
* @return A table with a list of files in the directory.
* @throws LuaException If the path doesn't exist.
*/
@LuaFunction
public final String[] list( String path ) throws LuaException
{
@@ -70,24 +82,51 @@ public class FSAPI implements ILuaAPI
}
}
/**
* Combines two parts of a path into one full path, adding separators as
* needed.
*
* @param pathA The first part of the path. For example, a parent directory path.
* @param pathB The second part of the path. For example, a file name.
* @return The new path, with separators added between parts as needed.
*/
@LuaFunction
public final String combine( String pathA, String pathB )
{
return fileSystem.combine( pathA, pathB );
}
/**
* Returns the file name portion of a path.
*
* @param path The path to get the name from.
* @return The final part of the path (the file name).
*/
@LuaFunction
public final String getName( String path )
{
return FileSystem.getName( path );
}
/**
* Returns the parent directory portion of a path.
*
* @param path The path to get the directory from.
* @return The path with the final part removed (the parent directory).
*/
@LuaFunction
public final String getDir( String path )
{
return FileSystem.getDirectory( path );
}
/**
* Returns the size of the specified file.
*
* @param path The file to get the file size of.
* @return The size of the file, in bytes.
* @throws LuaException If the path doesn't exist.
*/
@LuaFunction
public final long getSize( String path ) throws LuaException
{
@@ -101,6 +140,12 @@ public class FSAPI implements ILuaAPI
}
}
/**
* Returns whether the specified path exists.
*
* @param path The path to check the existence of.
* @return Whether the path exists.
*/
@LuaFunction
public final boolean exists( String path )
{
@@ -114,6 +159,12 @@ public class FSAPI implements ILuaAPI
}
}
/**
* Returns whether the specified path is a directory.
*
* @param path The path to check.
* @return Whether the path is a directory.
*/
@LuaFunction
public final boolean isDir( String path )
{
@@ -127,6 +178,12 @@ public class FSAPI implements ILuaAPI
}
}
/**
* Returns whether a path is read-only.
*
* @param path The path to check.
* @return Whether the path cannot be written to.
*/
@LuaFunction
public final boolean isReadOnly( String path )
{
@@ -140,6 +197,12 @@ public class FSAPI implements ILuaAPI
}
}
/**
* Creates a directory, and any missing parents, at the specified path.
*
* @param path The path to the directory to create.
* @throws LuaException If the directory couldn't be created.
*/
@LuaFunction
public final void makeDir( String path ) throws LuaException
{
@@ -154,6 +217,15 @@ public class FSAPI implements ILuaAPI
}
}
/**
* Moves a file or directory from one path to another.
*
* Any parent directories are created as needed.
*
* @param path The current file or directory to move from.
* @param dest The destination path for the file or directory.
* @throws LuaException If the file or directory couldn't be moved.
*/
@LuaFunction
public final void move( String path, String dest ) throws LuaException
{
@@ -168,6 +240,15 @@ public class FSAPI implements ILuaAPI
}
}
/**
* Copies a file or directory to a new path.
*
* Any parent directories are created as needed.
*
* @param path The file or directory to copy.
* @param dest The path to the destination file or directory.
* @throws LuaException If the file or directory couldn't be copied.
*/
@LuaFunction
public final void copy( String path, String dest ) throws LuaException
{
@@ -182,6 +263,15 @@ public class FSAPI implements ILuaAPI
}
}
/**
* Deletes a file or directory.
*
* If the path points to a directory, all of the enclosed files and
* subdirectories are also deleted.
*
* @param path The path to the file or directory to delete.
* @throws LuaException If the file or directory couldn't be deleted.
*/
@LuaFunction
public final void delete( String path ) throws LuaException
{
@@ -196,6 +286,24 @@ public class FSAPI implements ILuaAPI
}
}
// FIXME: Add individual handle type documentation
/**
* Opens a file for reading or writing at a path.
*
* The mode parameter can be {@code r} to read, {@code w} to write (deleting
* all contents), or {@code a} to append (keeping contents). If {@code b} is
* added to the end, the file will be opened in binary mode; otherwise, it's
* opened in text mode.
*
* @param path The path to the file to open.
* @param mode The mode to open the file with.
* @return A file handle object for the file, or {@code nil} + an error message on error.
* @throws LuaException If an invalid mode was specified.
* @cc.treturn [1] table A file handle object for the file.
* @cc.treturn [2] nil If the file does not exist, or cannot be opened.
* @cc.treturn string|nil A message explaining why the file cannot be opened.
*/
@LuaFunction
public final Object[] open( String path, String mode ) throws LuaException
{
@@ -250,6 +358,14 @@ public class FSAPI implements ILuaAPI
}
}
/**
* Returns the name of the mount that the specified path is located on.
*
* @param path The path to get the drive of.
* @return The name of the drive that the file is on; e.g. {@code hdd} for local files, or {@code rom} for ROM files.
* @throws LuaException If the path doesn't exist.
* @cc.treturn string The name of the drive that the file is on; e.g. {@code hdd} for local files, or {@code rom} for ROM files.
*/
@LuaFunction
public final Object[] getDrive( String path ) throws LuaException
{
@@ -263,6 +379,15 @@ public class FSAPI implements ILuaAPI
}
}
/**
* Returns the amount of free space available on the drive the path is
* located on.
*
* @param path The path to check the free space for.
* @return The amount of free space available, in bytes.
* @throws LuaException If the path doesn't exist.
* @cc.treturn number|"unlimited" The amount of free space available, in bytes, or "unlimited".
*/
@LuaFunction
public final Object getFreeSpace( String path ) throws LuaException
{
@@ -277,6 +402,18 @@ public class FSAPI implements ILuaAPI
}
}
/**
* Searches for files matching a string with wildcards.
*
* This string is formatted like a normal path string, but can include any
* number of wildcards ({@code *}) to look for files matching anything.
* For example, {@code rom/* /command*} will look for any path starting with
* {@code command} inside any subdirectory of {@code /rom}.
*
* @param path The wildcard-qualified path to search for.
* @return A list of paths that match the search string.
* @throws LuaException If the path doesn't exist.
*/
@LuaFunction
public final String[] find( String path ) throws LuaException
{
@@ -291,6 +428,19 @@ public class FSAPI implements ILuaAPI
}
}
/**
* Returns true if a path is mounted to the parent filesystem.
*
* The root filesystem "/" is considered a mount, along with disk folders and the rom folder. Other programs
* (such as network shares) can extend this to make other mount types by correctly assigning their return value for
* getDrive.
*
* @param path The path of the drive to get.
* @return The drive's capacity.
* @throws LuaException If the capacity cannot be determined.
* @cc.treturn number|nil This drive's capacity. This will be nil for "read-only" drives, such as the ROM or
* treasure disks.
*/
@LuaFunction
public final Object getCapacity( String path ) throws LuaException
{
@@ -305,6 +455,22 @@ public class FSAPI implements ILuaAPI
}
}
/**
* Get attributes about a specific file or folder.
*
* The returned attributes table contains information about the size of the file, whether it is a directory, and
* when it was created and last modified.
*
* The creation and modification times are given as the number of milliseconds since the UNIX epoch. This may be
* given to {@link OSAPI#date} in order to convert it to more usable form.
*
* @param path The path to get attributes for.
* @return The resulting attributes.
* @throws LuaException If the path does not exist.
* @cc.treturn { size = number, isDir = boolean, created = number, modified = number } The resulting attributes.
* @see #getSize If you only care about the file's size.
* @see #isDir If you only care whether a path is a directory or not.
*/
@LuaFunction
public final Map<String, Object> attributes( String path ) throws LuaException
{
@@ -313,6 +479,7 @@ public class FSAPI implements ILuaAPI
BasicFileAttributes attributes = fileSystem.getAttributes( path );
Map<String, Object> result = new HashMap<>();
result.put( "modification", getFileTime( attributes.lastModifiedTime() ) );
result.put( "modified", getFileTime( attributes.lastModifiedTime() ) );
result.put( "created", getFileTime( attributes.creationTime() ) );
result.put( "size", attributes.isDirectory() ? 0 : attributes.size() );
result.put( "isDir", attributes.isDirectory() );

View File

@@ -26,6 +26,12 @@ import java.util.Optional;
import static dan200.computercraft.core.apis.TableHelper.*;
/**
* The http library allows communicating with web servers, sending and receiving data from them.
*
* @cc.module http
* @hidden
*/
public class HTTPAPI implements ILuaAPI
{
private final IAPIEnvironment m_apiEnvironment;

View File

@@ -23,6 +23,11 @@ import java.util.*;
import static dan200.computercraft.api.lua.LuaValues.checkFinite;
/**
* The {@link OSAPI} API allows interacting with the current computer.
*
* @cc.module os
*/
public class OSAPI implements ILuaAPI
{
private final IAPIEnvironment apiEnvironment;
@@ -148,24 +153,58 @@ public class OSAPI implements ILuaAPI
return c.getTime().getTime();
}
/**
* Adds an event to the event queue. This event can later be pulled with
* os.pullEvent.
*
* @param name The name of the event to queue.
* @param args The parameters of the event.
* @cc.tparam string name The name of the event to queue.
* @cc.param ... The parameters of the event.
* @cc.see os.pullEvent To pull the event queued
*/
@LuaFunction
public final void queueEvent( String name, IArguments args )
{
apiEnvironment.queueEvent( name, args.drop( 1 ).getAll() );
}
/**
* 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.
*
* @param timer The number of seconds until the timer fires.
* @return The ID of the new timer.
* @throws LuaException If the time is below zero.
*/
@LuaFunction
public final int startTimer( double timer ) throws LuaException
{
return apiEnvironment.startTimer( Math.round( checkFinite( 0, timer ) / 0.05 ) );
}
/**
* Cancels a timer previously started with startTimer. This will stop the
* timer from firing.
*
* @param token The ID of the timer to cancel.
* @see #startTimer To start a timer.
*/
@LuaFunction
public final void cancelTimer( int token )
{
apiEnvironment.cancelTimer( token );
}
/**
* Sets an alarm that will fire at the specified world time. When it fires,
* an alarm event will be added to the event queue.
*
* @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.
* @throws LuaException If the time is out of range.
*/
@LuaFunction
public final int setAlarm( double time ) throws LuaException
{
@@ -179,6 +218,13 @@ public class OSAPI implements ILuaAPI
}
}
/**
* Cancels an alarm previously started with setAlarm. This will stop the
* alarm from firing.
*
* @param token The ID of the alarm to cancel.
* @see #setAlarm To set an alarm.
*/
@LuaFunction
public final void cancelAlarm( int token )
{
@@ -188,24 +234,41 @@ public class OSAPI implements ILuaAPI
}
}
/**
* Shuts down the computer immediately.
*/
@LuaFunction( "shutdown" )
public final void doShutdown()
{
apiEnvironment.shutdown();
}
/**
* Reboots the computer immediately.
*/
@LuaFunction( "reboot" )
public final void doReboot()
{
apiEnvironment.reboot();
}
/**
* Returns the ID of the computer.
*
* @return The ID of the computer.
*/
@LuaFunction( { "getComputerID", "computerID" } )
public final int getComputerID()
{
return apiEnvironment.getComputerID();
}
/**
* Returns the label of the computer, or {@code nil} if none is set.
*
* @return The label of the computer.
* @cc.treturn string The label of the computer.
*/
@LuaFunction( { "getComputerLabel", "computerLabel" } )
public final Object[] getComputerLabel()
{
@@ -213,18 +276,48 @@ public class OSAPI implements ILuaAPI
return label == null ? null : new Object[] { label };
}
/**
* Set the label of this computer.
*
* @param label The new label. May be {@code nil} in order to clear it.
*/
@LuaFunction
public final void setComputerLabel( Optional<String> label )
{
apiEnvironment.setLabel( StringUtil.normaliseLabel( label.orElse( null ) ) );
}
/**
* Returns the number of seconds that the computer has been running.
*
* @return The computer's uptime.
*/
@LuaFunction
public final double clock()
{
return m_clock * 0.05;
}
/**
* Returns the current time depending on the string passed in. This will
* always be in the range [0.0, 24.0).
*
* * If called with {@code ingame}, the current world time will be returned.
* This is the default if nothing is passed.
* * If called with {@code utc}, returns the hour of the day in UTC time.
* * If called with {@code local}, returns the hour of the day in the
* timezone the server is located in.
*
* This function can also be called with a table returned from {@link #date},
* which will convert the date fields into a UNIX timestamp (number of
* seconds since 1 January 1970).
*
* @param args The locale of the time, or a table filled by {@code os.date("*t")} to decode. Defaults to {@code ingame} locale if not specified.
* @return The hour of the selected locale, or a UNIX timestamp from the table, depending on the argument passed in.
* @throws LuaException If an invalid locale is passed.
* @cc.tparam [opt] string|table locale The locale of the time, or a table filled by {@code os.date("*t")} to decode. Defaults to {@code ingame} locale if not specified.
* @see #date To get a date table that can be converted with this function.
*/
@LuaFunction
public final Object time( IArguments args ) throws LuaException
{
@@ -245,6 +338,20 @@ public class OSAPI implements ILuaAPI
}
}
/**
* Returns the day depending on the locale specified.
*
* * If called with {@code ingame}, returns the number of days since the
* world was created. This is the default.
* * If called with {@code utc}, returns the number of days since 1 January
* 1970 in the UTC timezone.
* * If called with {@code local}, returns the number of days since 1
* January 1970 in the server's local timezone.
*
* @param args The locale to get the day for. Defaults to {@code ingame} if not set.
* @return The day depending on the selected locale.
* @throws LuaException If an invalid locale is passed.
*/
@LuaFunction
public final int day( Optional<String> args ) throws LuaException
{
@@ -261,6 +368,20 @@ public class OSAPI implements ILuaAPI
}
}
/**
* Returns the number of seconds since an epoch depending on the locale.
*
* * If called with {@code ingame}, returns the number of seconds since the
* world was created. This is the default.
* * If called with {@code utc}, returns the number of seconds since 1
* January 1970 in the UTC timezone.
* * If called with {@code local}, returns the number of seconds since 1
* January 1970 in the server's local timezone.
*
* @param args The locale to get the seconds for. Defaults to {@code ingame} if not set.
* @return The seconds since the epoch depending on the selected locale.
* @throws LuaException If an invalid locale is passed.
*/
@LuaFunction
public final long epoch( Optional<String> args ) throws LuaException
{
@@ -289,6 +410,26 @@ public class OSAPI implements ILuaAPI
}
}
/**
* Returns a date string (or table) using a specified format string and
* optional time to format.
*
* The format string takes the same formats as C's {@code strftime} function
* (http://www.cplusplus.com/reference/ctime/strftime/). In extension, it
* can be prefixed with an exclamation mark ({@code !}) to use UTC time
* instead of the server's local timezone.
*
* If the format is exactly {@code *t} (optionally prefixed with {@code !}), a
* table will be returned instead. This table has fields for the year, month,
* day, hour, minute, second, day of the week, day of the year, and whether
* Daylight Savings Time is in effect. This table can be converted to a UNIX
* timestamp (days since 1 January 1970) with {@link #date}.
*
* @param formatA The format of the string to return. This defaults to {@code %c}, which expands to a string similar to "Sat Dec 24 16:58:00 2011".
* @param timeA The time to convert to a string. This defaults to the current time.
* @return The resulting format string.
* @throws LuaException If an invalid format is passed.
*/
@LuaFunction
public final Object date( Optional<String> formatA, Optional<Long> timeA ) throws LuaException
{

View File

@@ -22,6 +22,12 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.*;
/**
* CC's "native" peripheral API. This is wrapped within CraftOS to provide a version which works with modems.
*
* @cc.module peripheral
* @hidden
*/
public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChangeListener
{
private class PeripheralWrapper extends ComputerAccess

View File

@@ -10,6 +10,48 @@ import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.api.lua.LuaFunction;
import dan200.computercraft.core.computer.ComputerSide;
/**
* Interact with redstone attached to this computer.
*
* The {@link RedstoneAPI} library exposes three "types" of redstone control:
* - Binary input/output ({@link #setOutput}/{@link #getInput}): These simply check if a redstone wire has any input or
* output. A signal strength of 1 and 15 are treated the same.
* - Analogue input/output ({@link #setAnalogOutput}/{@link #getAnalogInput}): These work with the actual signal
* strength of the redstone wired, from 0 to 15.
* - Bundled cables ({@link #setBundledOutput}/{@link #getBundledInput}): These interact with "bundled" cables, such
* as those from Project:Red. These allow you to send 16 separate on/off signals. Each channel corresponds to a
* colour, with the first being @{colors.white} and the last @{colors.black}.
*
* Whenever a redstone input changes, a {@code redstone} event will be fired. This may be used instead of repeativly
* polling.
*
* This module may also be referred to as {@code rs}. For example, one may call {@code rs.getSides()} instead of
* {@link #getSides}.
*
* @cc.usage Toggle the redstone signal above the computer every 0.5 seconds.
*
* <pre>
* while true do
* redstone.setOutput("top", not redstone.getOutput("top"))
* sleep(0.5)
* end
* </pre>
* @cc.usage Mimic a redstone comparator in [subtraction mode][comparator].
*
* <pre>
* while true do
* local rear = rs.getAnalogueInput("back")
* local sides = math.max(rs.getAnalogueInput("left"), rs.getAnalogueInput("right"))
* rs.setAnalogueOutput("front", math.max(rear - sides, 0))
*
* os.pullEvent("redstone") -- Wait for a change to inputs.
* end
* </pre>
*
* [comparator]: https://minecraft.gamepedia.com/Redstone_Comparator#Subtract_signal_strength "Redstone Comparator on
* the Minecraft wiki."
* @cc.module redstone
*/
public class RedstoneAPI implements ILuaAPI
{
private final IAPIEnvironment environment;
@@ -25,67 +67,145 @@ public class RedstoneAPI implements ILuaAPI
return new String[] { "rs", "redstone" };
}
/**
* Returns a table containing the six sides of the computer. Namely, "top", "bottom", "left", "right", "front" and
* "back".
*
* @return A table of valid sides.
*/
@LuaFunction
public final String[] getSides()
{
return ComputerSide.NAMES;
}
/**
* Turn the redstone signal of a specific side on or off.
*
* @param side The side to set.
* @param on Whether the redstone signal should be on or off. When on, a signal strength of 15 is emitted.
*/
@LuaFunction
public final void setOutput( ComputerSide side, boolean output )
public final void setOutput( ComputerSide side, boolean on )
{
environment.setOutput( side, output ? 15 : 0 );
environment.setOutput( side, on ? 15 : 0 );
}
/**
* Get the current redstone output of a specific side.
*
* @param side The side to get.
* @return Whether the redstone output is on or off.
* @see #setOutput
*/
@LuaFunction
public final boolean getOutput( ComputerSide side )
{
return environment.getOutput( side ) > 0;
}
/**
* Get the current redstone input of a specific side.
*
* @param side The side to get.
* @return Whether the redstone input is on or off.
*/
@LuaFunction
public final boolean getInput( ComputerSide side )
{
return environment.getInput( side ) > 0;
}
/**
* Set the redstone signal strength for a specific side.
*
* @param side The side to set.
* @param value The signal strength between 0 and 15.
* @throws LuaException If {@code value} is not betwene 0 and 15.
*/
@LuaFunction( { "setAnalogOutput", "setAnalogueOutput" } )
public final void setAnalogOutput( ComputerSide side, int output ) throws LuaException
public final void setAnalogOutput( ComputerSide side, int value ) throws LuaException
{
if( output < 0 || output > 15 ) throw new LuaException( "Expected number in range 0-15" );
environment.setOutput( side, output );
if( value < 0 || value > 15 ) throw new LuaException( "Expected number in range 0-15" );
environment.setOutput( side, value );
}
/**
* Get the redstone output signal strength for a specific side.
*
* @param side The side to get.
* @return The output signal strength, between 0 and 15.
* @see #setAnalogOutput
*/
@LuaFunction( { "getAnalogOutput", "getAnalogueOutput" } )
public final int getAnalogOutput( ComputerSide side )
{
return environment.getOutput( side );
}
/**
* Get the redstone input signal strength for a specific side.
*
* @param side The side to get.
* @return The input signal strength, between 0 and 15.
*/
@LuaFunction( { "getAnalogInput", "getAnalogueInput" } )
public final int getAnalogInput( ComputerSide side )
{
return environment.getInput( side );
}
/**
* Set the bundled cable output for a specific side.
*
* @param side The side to set.
* @param output The colour bitmask to set.
* @cc.see colors.subtract For removing a colour from the bitmask.
* @cc.see colors.combine For adding a color to the bitmask.
*/
@LuaFunction
public final void setBundledOutput( ComputerSide side, int output )
{
environment.setBundledOutput( side, output );
}
/**
* Get the bundled cable output for a specific side.
*
* @param side The side to get.
* @return The bundle cable's output.
*/
@LuaFunction
public final int getBundledOutput( ComputerSide side )
{
return environment.getBundledOutput( side );
}
/**
* Get the bundled cable input for a specific side.
*
* @param side The side to get.
* @return The bundle cable's input.
* @see #testBundledInput To determine if a specific colour is set.
*/
@LuaFunction
public final int getBundledInput( ComputerSide side )
{
return environment.getBundledOutput( side );
}
/**
* Determine if a specific combination of colours are on for the given side.
*
* @param side The side to test.
* @param mask The mask to test.
* @return If the colours are on.
* @cc.usage Check if @{colors.white} and @{colors.black} are on above the computer.
* <pre>
* print(redstone.testBundledInput("top", colors.combine(colors.white, colors.black)))
* </pre>
* @see #getBundledInput
*/
@LuaFunction
public final boolean testBundledInput( ComputerSide side, int mask )
{

View File

@@ -5,6 +5,7 @@
*/
package dan200.computercraft.core.apis;
import dan200.computercraft.api.lua.IArguments;
import dan200.computercraft.api.lua.ILuaAPI;
import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.api.lua.LuaFunction;
@@ -14,6 +15,11 @@ import dan200.computercraft.shared.util.Colour;
import javax.annotation.Nonnull;
/**
* The Terminal API provides functions for writing text to the terminal and monitors, and drawing ASCII graphics.
*
* @cc.module term
*/
public class TermAPI extends TermMethods implements ILuaAPI
{
private final Terminal terminal;
@@ -31,11 +37,22 @@ public class TermAPI extends TermMethods implements ILuaAPI
return new String[] { "term" };
}
/**
* Get the default palette value for a colour.
*
* @param colour The colour whose palette should be fetched.
* @return The RGB values.
* @throws LuaException When given an invalid colour.
* @cc.treturn number The red channel, will be between 0 and 1.
* @cc.treturn number The green channel, will be between 0 and 1.
* @cc.treturn number The blue channel, will be between 0 and 1.
* @see TermMethods#setPaletteColour(IArguments) To change the palette colour.
*/
@LuaFunction( { "nativePaletteColour", "nativePaletteColor" } )
public final Object[] nativePaletteColour( int colourArg ) throws LuaException
public final Object[] nativePaletteColour( int colour ) throws LuaException
{
int colour = 15 - parseColour( colourArg );
Colour c = Colour.fromInt( colour );
int actualColour = 15 - parseColour( colour );
Colour c = Colour.fromInt( actualColour );
float[] rgb = c.getRGB();

View File

@@ -18,6 +18,8 @@ import javax.annotation.Nonnull;
/**
* A base class for all objects which interact with a terminal. Namely the {@link TermAPI} and monitors.
*
* @cc.module term.Redirect
*/
public abstract class TermMethods
{
@@ -37,6 +39,16 @@ public abstract class TermMethods
public abstract boolean isColour() throws LuaException;
/**
* Write {@code text} at the current cursor position, moving the cursor to the end of the text.
*
* Unlike functions like {@code write} and {@code print}, this does not wrap the text - it simply copies the
* text to the current terminal line.
*
* @param arguments The text to write.
* @throws LuaException (hidden) If the terminal cannot be found.
* @cc.param text The text to write.
*/
@LuaFunction
public final void write( IArguments arguments ) throws LuaException
{
@@ -49,12 +61,29 @@ public abstract class TermMethods
}
}
/**
* Move all positions up (or down) by {@code y} pixels.
*
* Every pixel in the terminal will be replaced by the line {@code y} pixels below it. If {@code y} is negative, it
* will copy pixels from above instead.
*
* @param y The number of lines to move up by. This may be a negative number.
* @throws LuaException (hidden) If the terminal cannot be found.
*/
@LuaFunction
public final void scroll( int y ) throws LuaException
{
getTerminal().scroll( y );
}
/**
* Get the position of the cursor.
*
* @return The cursor's position.
* @throws LuaException (hidden) If the terminal cannot be found.
* @cc.treturn number The x position of the cursor.
* @cc.treturn number The y position of the cursor.
*/
@LuaFunction
public final Object[] getCursorPos() throws LuaException
{
@@ -62,6 +91,13 @@ public abstract class TermMethods
return new Object[] { terminal.getCursorX() + 1, terminal.getCursorY() + 1 };
}
/**
* Set the position of the cursor. {@link #write(IArguments) terminal writes} will begin from this position.
*
* @param x The new x position of the cursor.
* @param y The new y position of the cursor.
* @throws LuaException (hidden) If the terminal cannot be found.
*/
@LuaFunction
public final void setCursorPos( int x, int y ) throws LuaException
{
@@ -72,12 +108,24 @@ public abstract class TermMethods
}
}
/**
* Checks if the cursor is currently blinking.
*
* @return If the cursor is blinking.
* @throws LuaException (hidden) If the terminal cannot be found.
*/
@LuaFunction
public final boolean getCursorBlink() throws LuaException
{
return getTerminal().getCursorBlink();
}
/**
* Sets whether the cursor should be visible (and blinking) at the current {@link #getCursorPos() cursor position}.
*
* @param blink Whether the cursor should blink.
* @throws LuaException (hidden) If the terminal cannot be found.
*/
@LuaFunction
public final void setCursorBlink( boolean blink ) throws LuaException
{
@@ -88,6 +136,14 @@ public abstract class TermMethods
}
}
/**
* Get the size of the terminal.
*
* @return The terminal's size.
* @throws LuaException (hidden) If the terminal cannot be found.
* @cc.treturn number The terminal's width.
* @cc.treturn number The terminal's height.
*/
@LuaFunction
public final Object[] getSize() throws LuaException
{
@@ -95,24 +151,49 @@ public abstract class TermMethods
return new Object[] { terminal.getWidth(), terminal.getHeight() };
}
/**
* Clears the terminal, filling it with the {@link #getBackgroundColour() current background colour}.
*
* @throws LuaException (hidden) If the terminal cannot be found.
*/
@LuaFunction
public final void clear() throws LuaException
{
getTerminal().clear();
}
/**
* Clears the line the cursor is currently on, filling it with the {@link #getBackgroundColour() current background
* colour}.
*
* @throws LuaException (hidden) If the terminal cannot be found.
*/
@LuaFunction
public final void clearLine() throws LuaException
{
getTerminal().clearLine();
}
/**
* Return the colour that new text will be written as.
*
* @return The current text colour.
* @throws LuaException (hidden) If the terminal cannot be found.
* @cc.see colors For a list of colour constants, returned by this function.
*/
@LuaFunction( { "getTextColour", "getTextColor" } )
public final int getTextColour() throws LuaException
{
return encodeColour( getTerminal().getTextColour() );
}
/**
* Set the colour that new text will be written as.
*
* @param colourArg The new text colour.
* @throws LuaException (hidden) If the terminal cannot be found.
* @cc.see colors For a list of colour constants.
*/
@LuaFunction( { "setTextColour", "setTextColor" } )
public final void setTextColour( int colourArg ) throws LuaException
{
@@ -124,12 +205,28 @@ public abstract class TermMethods
}
}
/**
* Return the current background colour. This is used when {@link #write writing text} and {@link #clear clearing}
* the terminal.
*
* @return The current background colour.
* @throws LuaException (hidden) If the terminal cannot be found.
* @cc.see colors For a list of colour constants, returned by this function.
*/
@LuaFunction( { "getBackgroundColour", "getBackgroundColor" } )
public final int getBackgroundColour() throws LuaException
{
return encodeColour( getTerminal().getBackgroundColour() );
}
/**
* Set the current background colour. This is used when {@link #write writing text} and {@link #clear clearing} the
* terminal.
*
* @param colourArg The new background colour.
* @throws LuaException (hidden) If the terminal cannot be found.
* @cc.see colors For a list of colour constants.
*/
@LuaFunction( { "setBackgroundColour", "setBackgroundColor" } )
public final void setBackgroundColour( int colourArg ) throws LuaException
{
@@ -141,12 +238,41 @@ public abstract class TermMethods
}
}
/**
* Determine if this terminal supports colour.
*
* Terminals which do not support colour will still allow writing coloured text/backgrounds, but it will be
* displayed in greyscale.
*
* @return Whether this terminal supports colour.
* @throws LuaException (hidden) If the terminal cannot be found.
*/
@LuaFunction( { "isColour", "isColor" } )
public final boolean getIsColour() throws LuaException
{
return isColour();
}
/**
* Writes {@code text} to the terminal with the specific foreground and background characters.
*
* As with {@link #write(IArguments)}, the text will be written at the current cursor location, with the cursor
* moving to the end of the text.
*
* {@code textColour} and {@code backgroundColour} must both be strings the same length as {@code text}. All
* characters represent a single hexadecimal digit, which is converted to one of CC's colours. For instance,
* {@code "a"} corresponds to purple.
*
* @param text The text to write.
* @param textColour The corresponding text colours.
* @param backgroundColour The corresponding background colours.
* @throws LuaException If the three inputs are not the same length.
* @cc.see colors For a list of colour constants, and their hexadecimal values.
* @cc.usage Prints "Hello, world!" in rainbow text.
* <pre>{@code
* term.blit("Hello, world!","01234456789ab","0000000000000")
* }</pre>
*/
@LuaFunction
public final void blit( String text, String textColour, String backgroundColour ) throws LuaException
{
@@ -163,6 +289,38 @@ public abstract class TermMethods
}
}
/**
* Set the palette for a specific colour.
*
* ComputerCraft's palette system allows you to change how a specific colour should be displayed. For instance, you
* can make @{colors.red} <em>more red</em> by setting its palette to #FF0000. This does now allow you to draw more
* colours - you are still limited to 16 on the screen at one time - but you can change <em>which</em> colours are
* used.
*
* @param args The new palette values.
* @throws LuaException (hidden) If the terminal cannot be found.
* @cc.tparam [1] number index The colour whose palette should be changed.
* @cc.tparam number colour A 24-bit integer representing the RGB value of the colour. For instance the integer
* `0xFF0000` corresponds to the colour #FF0000.
* @cc.tparam [2] number index The colour whose palette should be changed.
* @cc.tparam number r The intensity of the red channel, between 0 and 1.
* @cc.tparam number g The intensity of the green channel, between 0 and 1.
* @cc.tparam number b The intensity of the blue channel, between 0 and 1.
* @cc.usage Change the @{colors.red|red colour} from the default #CC4C4C to #FF0000.
* <pre>{@code
* term.setPaletteColour(colors.red, 0xFF0000)
* term.setTextColour(colors.red)
* print("Hello, world!")
* }</pre>
* @cc.usage As above, but specifying each colour channel separately.
* <pre>{@code
* term.setPaletteColour(colors.red, 1, 0, 0)
* term.setTextColour(colors.red)
* print("Hello, world!")
* }</pre>
* @cc.see colors.unpackRGB To convert from the 24-bit format to three separate channels.
* @cc.see colors.packRGB To convert from three separate channels to the 24-bit format.
*/
@LuaFunction( { "setPaletteColour", "setPaletteColor" } )
public final void setPaletteColour( IArguments args ) throws LuaException
{
@@ -182,6 +340,16 @@ public abstract class TermMethods
}
}
/**
* Get the current palette for a specific colour.
*
* @param colourArg The colour whose palette should be fetched.
* @return The resulting colour.
* @throws LuaException (hidden) If the terminal cannot be found.
* @cc.treturn number The red channel, will be between 0 and 1.
* @cc.treturn number The green channel, will be between 0 and 1.
* @cc.treturn number The blue channel, will be between 0 and 1.
*/
@LuaFunction( { "getPaletteColour", "getPaletteColor" } )
public final Object[] getPaletteColour( int colourArg ) throws LuaException
{
@@ -189,12 +357,8 @@ public abstract class TermMethods
Terminal terminal = getTerminal();
synchronized( terminal )
{
if( terminal.getPalette() != null )
{
return ArrayUtils.toObject( terminal.getPalette().getColour( colour ) );
}
return ArrayUtils.toObject( terminal.getPalette().getColour( colour ) );
}
return null;
}
public static int parseColour( int colour ) throws LuaException
@@ -213,10 +377,7 @@ public abstract class TermMethods
public static void setColour( Terminal terminal, int colour, double r, double g, double b )
{
if( terminal.getPalette() != null )
{
terminal.getPalette().setColour( colour, r, g, b );
terminal.setChanged();
}
terminal.getPalette().setColour( colour, r, g, b );
terminal.setChanged();
}
}

View File

@@ -5,7 +5,6 @@
*/
package dan200.computercraft.core.apis.handles;
import dan200.computercraft.api.lua.IArguments;
import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.api.lua.LuaFunction;
@@ -19,6 +18,12 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
/**
* A file handle opened with {@link dan200.computercraft.core.apis.FSAPI#open(String, String)} with the {@code "rb"}
* mode.
*
* @cc.module fs.BinaryReadHandle
*/
public class BinaryReadableHandle extends HandleGeneric
{
private static final int BUFFER_SIZE = 8192;
@@ -27,7 +32,7 @@ public class BinaryReadableHandle extends HandleGeneric
final SeekableByteChannel seekable;
private final ByteBuffer single = ByteBuffer.allocate( 1 );
protected BinaryReadableHandle( ReadableByteChannel reader, SeekableByteChannel seekable, Closeable closeable )
BinaryReadableHandle( ReadableByteChannel reader, SeekableByteChannel seekable, Closeable closeable )
{
super( closeable );
this.reader = reader;
@@ -45,6 +50,18 @@ public class BinaryReadableHandle extends HandleGeneric
return of( channel, channel );
}
/**
* Read a number of bytes from this file.
*
* @param countArg The number of bytes to read. When absent, a single byte will be read <em>as a number</em>. This
* may be 0 to determine we are at the end of the file.
* @return The read bytes.
* @throws LuaException When trying to read a negative number of bytes.
* @throws LuaException If the file has been closed.
* @cc.treturn [1] nil If we are at the end of the file.
* @cc.treturn [2] number The value of the byte read. This is returned when the {@code count} is absent.
* @cc.treturn [3] string The bytes read as a string. This is returned when the {@code count} is given.
*/
@LuaFunction
public final Object[] read( Optional<Integer> countArg ) throws LuaException
{
@@ -122,6 +139,13 @@ public class BinaryReadableHandle extends HandleGeneric
}
}
/**
* Read the remainder of the file.
*
* @return The file, or {@code null} if at the end of it.
* @throws LuaException If the file has been closed.
* @cc.treturn string|nil The remaining contents of the file, or {@code nil} if we are at the end.
*/
@LuaFunction
public final Object[] readAll() throws LuaException
{
@@ -151,6 +175,14 @@ public class BinaryReadableHandle extends HandleGeneric
}
}
/**
* Read a line from the file.
*
* @param withTrailingArg Whether to include the newline characters with the returned string. Defaults to {@code false}.
* @return The read string.
* @throws LuaException If the file has been closed.
* @cc.treturn string|nil The read line or {@code nil} if at the end of the file.
*/
@LuaFunction
public final Object[] readLine( Optional<Boolean> withTrailingArg ) throws LuaException
{
@@ -205,16 +237,34 @@ public class BinaryReadableHandle extends HandleGeneric
public static class Seekable extends BinaryReadableHandle
{
public Seekable( SeekableByteChannel seekable, Closeable closeable )
Seekable( SeekableByteChannel seekable, Closeable closeable )
{
super( seekable, seekable, closeable );
}
/**
* Seek to a new position within the file, changing where bytes are written to. The new position is an offset
* given by {@code offset}, relative to a start position determined by {@code whence}:
*
* - {@code "set"}: {@code offset} is relative to the beginning of the file.
* - {@code "cur"}: Relative to the current position. This is the default.
* - {@code "end"}: Relative to the end of the file.
*
* In case of success, {@code seek} returns the new file position from the beginning of the file.
*
* @param whence Where the offset is relative to.
* @param offset The offset to seek to.
* @return The new position.
* @throws LuaException If the file has been closed.
* @cc.treturn [1] number The new position.
* @cc.treturn [2] nil If seeking failed.
* @cc.treturn string The reason seeking failed.
*/
@LuaFunction
public final Object[] seek( IArguments arguments ) throws LuaException
public final Object[] seek( Optional<String> whence, Optional<Long> offset ) throws LuaException
{
checkOpen();
return handleSeek( seekable, arguments );
return handleSeek( seekable, whence, offset );
}
}
}

View File

@@ -16,7 +16,14 @@ import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.SeekableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.util.Optional;
/**
* A file handle opened by {@link dan200.computercraft.core.apis.FSAPI#open} using the {@code "wb"} or {@code "ab"}
* modes.
*
* @cc.module fs.BinaryWriteHandle
*/
public class BinaryWritableHandle extends HandleGeneric
{
private final WritableByteChannel writer;
@@ -41,6 +48,14 @@ public class BinaryWritableHandle extends HandleGeneric
return of( channel, channel );
}
/**
* Write a string or byte to the file.
*
* @param arguments The value to write.
* @throws LuaException If the file has been closed.
* @cc.tparam [1] number The byte to write.
* @cc.tparam [2] string The string to write.
*/
@LuaFunction
public final void write( IArguments arguments ) throws LuaException
{
@@ -72,6 +87,11 @@ public class BinaryWritableHandle extends HandleGeneric
}
}
/**
* Save the current file without closing it.
*
* @throws LuaException If the file has been closed.
*/
@LuaFunction
public final void flush() throws LuaException
{
@@ -93,11 +113,29 @@ public class BinaryWritableHandle extends HandleGeneric
super( seekable, seekable, closeable );
}
/**
* Seek to a new position within the file, changing where bytes are written to. The new position is an offset
* given by {@code offset}, relative to a start position determined by {@code whence}:
*
* - {@code "set"}: {@code offset} is relative to the beginning of the file.
* - {@code "cur"}: Relative to the current position. This is the default.
* - {@code "end"}: Relative to the end of the file.
*
* In case of success, {@code seek} returns the new file position from the beginning of the file.
*
* @param whence Where the offset is relative to.
* @param offset The offset to seek to.
* @return The new position.
* @throws LuaException If the file has been closed.
* @cc.treturn [1] number The new position.
* @cc.treturn [2] nil If seeking failed.
* @cc.treturn string The reason seeking failed.
*/
@LuaFunction
public final Object[] seek( IArguments args ) throws LuaException
public final Object[] seek( Optional<String> whence, Optional<Long> offset ) throws LuaException
{
checkOpen();
return handleSeek( seekable, args );
return handleSeek( seekable, whence, offset );
}
}
}

View File

@@ -20,6 +20,12 @@ import java.nio.charset.CodingErrorAction;
import java.nio.charset.StandardCharsets;
import java.util.Optional;
/**
* A file handle opened with {@link dan200.computercraft.core.apis.FSAPI#open(String, String)} with the {@code "r"}
* mode.
*
* @cc.module fs.ReadHandle
*/
public class EncodedReadableHandle extends HandleGeneric
{
private static final int BUFFER_SIZE = 8192;
@@ -37,6 +43,14 @@ public class EncodedReadableHandle extends HandleGeneric
this( reader, reader );
}
/**
* Read a line from the file.
*
* @param withTrailingArg Whether to include the newline characters with the returned string. Defaults to {@code false}.
* @return The read string.
* @throws LuaException If the file has been closed.
* @cc.treturn string|nil The read line or {@code nil} if at the end of the file.
*/
@LuaFunction
public final Object[] readLine( Optional<Boolean> withTrailingArg ) throws LuaException
{
@@ -62,6 +76,13 @@ public class EncodedReadableHandle extends HandleGeneric
}
}
/**
* Read the remainder of the file.
*
* @return The file, or {@code null} if at the end of it.
* @throws LuaException If the file has been closed.
* @cc.treturn nil|string The remaining contents of the file, or {@code nil} if we are at the end.
*/
@LuaFunction
public final Object[] readAll() throws LuaException
{
@@ -87,6 +108,15 @@ public class EncodedReadableHandle extends HandleGeneric
}
}
/**
* Read a number of characters from this file.
*
* @param countA The number of characters to read, defaulting to 1.
* @return The read characters.
* @throws LuaException When trying to read a negative number of characters.
* @throws LuaException If the file has been closed.
* @cc.treturn string|nil The read characters, or {@code nil} if at the of the file.
*/
@LuaFunction
public final Object[] read( Optional<Integer> countA ) throws LuaException
{

View File

@@ -21,6 +21,11 @@ import java.nio.charset.CharsetEncoder;
import java.nio.charset.CodingErrorAction;
import java.nio.charset.StandardCharsets;
/**
* A file handle opened by {@link dan200.computercraft.core.apis.FSAPI#open} using the {@code "w"} or {@code "a"} modes.
*
* @cc.module fs.WriteHandle
*/
public class EncodedWritableHandle extends HandleGeneric
{
private final BufferedWriter writer;
@@ -31,6 +36,13 @@ public class EncodedWritableHandle extends HandleGeneric
this.writer = writer;
}
/**
* Write a string of characters to the file.
*
* @param args The value to write.
* @throws LuaException If the file has been closed.
* @cc.param The value to write to the file.
*/
@LuaFunction
public final void write( IArguments args ) throws LuaException
{
@@ -46,6 +58,13 @@ public class EncodedWritableHandle extends HandleGeneric
}
}
/**
* Write a string of characters to the file, follwing them with a new line character.
*
* @param args The value to write.
* @throws LuaException If the file has been closed.
* @cc.param The value to write to the file.
*/
@LuaFunction
public final void writeLine( IArguments args ) throws LuaException
{
@@ -62,6 +81,11 @@ public class EncodedWritableHandle extends HandleGeneric
}
}
/**
* Save the current file without closing it.
*
* @throws LuaException If the file has been closed.
*/
@LuaFunction
public final void flush() throws LuaException
{

View File

@@ -5,7 +5,6 @@
*/
package dan200.computercraft.core.apis.handles;
import dan200.computercraft.api.lua.IArguments;
import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.api.lua.LuaFunction;
import dan200.computercraft.shared.util.IoUtil;
@@ -15,6 +14,7 @@ import java.io.Closeable;
import java.io.IOException;
import java.nio.channels.Channel;
import java.nio.channels.SeekableByteChannel;
import java.util.Optional;
public abstract class HandleGeneric
{
@@ -39,6 +39,13 @@ public abstract class HandleGeneric
closable = null;
}
/**
* Close this file, freeing any resources it uses.
*
* Once a file is closed it may no longer be read or written to.
*
* @throws LuaException If the file has already been closed.
*/
@LuaFunction( "close" )
public final void doClose() throws LuaException
{
@@ -51,27 +58,27 @@ public abstract class HandleGeneric
* Shared implementation for various file handle types.
*
* @param channel The channel to seek in
* @param args The Lua arguments to process, like Lua's {@code file:seek}.
* @param whence The seeking mode.
* @param offset The offset to seek to.
* @return The new position of the file, or null if some error occurred.
* @throws LuaException If the arguments were invalid
* @see <a href="https://www.lua.org/manual/5.1/manual.html#pdf-file:seek">{@code file:seek} in the Lua manual.</a>
*/
protected static Object[] handleSeek( SeekableByteChannel channel, IArguments args ) throws LuaException
protected static Object[] handleSeek( SeekableByteChannel channel, Optional<String> whence, Optional<Long> offset ) throws LuaException
{
String whence = args.optString( 0, "cur" );
long offset = args.optLong( 1, 0 );
long actualOffset = offset.orElse( 0L );
try
{
switch( whence )
switch( whence.orElse( "cur" ) )
{
case "set":
channel.position( offset );
channel.position( actualOffset );
break;
case "cur":
channel.position( channel.position() + offset );
channel.position( channel.position() + actualOffset );
break;
case "end":
channel.position( channel.size() + offset );
channel.position( channel.size() + actualOffset );
break;
default:
throw new LuaException( "bad argument #1 to 'seek' (invalid option '" + whence + "'" );
@@ -81,7 +88,7 @@ public abstract class HandleGeneric
}
catch( IllegalArgumentException e )
{
return new Object[] { false, "Position is negative" };
return new Object[] { null, "Position is negative" };
}
catch( IOException e )
{

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

@@ -86,7 +86,7 @@ public final class HttpRequestHandler extends SimpleChannelInboundHandler<HttpOb
{
request.headers().set( HttpHeaderNames.USER_AGENT, this.request.environment().getComputerEnvironment().getUserAgent() );
}
request.headers().set( HttpHeaderNames.HOST, uri.getHost() );
request.headers().set( HttpHeaderNames.HOST, uri.getPort() < 0 ? uri.getHost() : uri.getHost() + ":" + uri.getPort() );
request.headers().set( HttpHeaderNames.CONNECTION, HttpHeaderValues.CLOSE );
ctx.channel().writeAndFlush( request );

View File

@@ -5,7 +5,11 @@
*/
package dan200.computercraft.core.apis.http.request;
import dan200.computercraft.api.lua.IArguments;
import dan200.computercraft.api.lua.LuaFunction;
import dan200.computercraft.core.apis.HTTPAPI;
import dan200.computercraft.core.apis.handles.BinaryReadableHandle;
import dan200.computercraft.core.apis.handles.EncodedReadableHandle;
import dan200.computercraft.core.apis.handles.HandleGeneric;
import dan200.computercraft.core.asm.ObjectSource;
@@ -14,8 +18,12 @@ import java.util.Collections;
import java.util.Map;
/**
* Wraps a {@link dan200.computercraft.core.apis.handles.HandleGeneric} and provides additional methods for
* getting the response code and headers.
* A http response. This provides the same methods as a {@link EncodedReadableHandle file} (or
* {@link BinaryReadableHandle binary file} if the request used binary mode), though provides several request specific
* methods.
*
* @cc.module http.Response
* @see HTTPAPI#request(IArguments) On how to make a http request.
*/
public class HttpResponseHandle implements ObjectSource
{
@@ -32,12 +40,37 @@ public class HttpResponseHandle implements ObjectSource
this.responseHeaders = responseHeaders;
}
/**
* Returns the response code and response message returned by the server.
*
* @return The response code and message.
* @cc.treturn number The response code (i.e. 200)
* @cc.treturn string The response message (i.e. "OK")
*/
@LuaFunction
public final Object[] getResponseCode()
{
return new Object[] { responseCode, responseStatus };
}
/**
* Get a table containing the response's headers, in a format similar to that required by {@link HTTPAPI#request}.
* If multiple headers are sent with the same name, they will be combined with a comma.
*
* @return The response's headers.
* @cc.usage Make a request to [example.computercraft.cc](https://example.computercraft.cc), and print the
* returned headers.
* <pre>{@code
* local request = http.get("https://example.computercraft.cc")
* print(textutils.serialize(request.getResponseHeaders()))
* -- => {
* -- [ "Content-Type" ] = "text/plain; charset=utf8",
* -- [ "content-length" ] = 17,
* -- ...
* -- }
* request.close()
* }</pre>
*/
@LuaFunction
public final Map<String, String> getResponseHeaders()
{

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

@@ -25,6 +25,12 @@ import static dan200.computercraft.core.apis.IAPIEnvironment.TIMER_EVENT;
import static dan200.computercraft.core.apis.http.websocket.Websocket.CLOSE_EVENT;
import static dan200.computercraft.core.apis.http.websocket.Websocket.MESSAGE_EVENT;
/**
* A websocket, which can be used to send an receive messages with a web server.
*
* @cc.module http.Websocket
* @see dan200.computercraft.core.apis.HTTPAPI#websocket On how to open a websocket.
*/
public class WebsocketHandle implements Closeable
{
private final Websocket websocket;
@@ -40,8 +46,18 @@ public class WebsocketHandle implements Closeable
this.channel = channel;
}
/**
* Wait for a message from the server.
*
* @param timeout The number of seconds to wait if no message is received.
* @return The result of receiving.
* @throws LuaException If the websocket has been closed.
* @cc.treturn [1] string The received message.
* @cc.treturn boolean If this was a binary message.
* @cc.treturn [2] nil If the websocket was closed while waiting, or if we timed out.
*/
@LuaFunction
public final MethodResult result( Optional<Double> timeout ) throws LuaException
public final MethodResult receive( Optional<Double> timeout ) throws LuaException
{
checkOpen();
int timeoutId = timeout.isPresent()
@@ -51,29 +67,40 @@ public class WebsocketHandle implements Closeable
return new ReceiveCallback( timeoutId ).pull;
}
/**
* Send a websocket message to the connected server.
*
* @param message The message to send.
* @param binary Whether this message should be treated as a
* @throws LuaException If the message is too large.
* @throws LuaException If the websocket has been closed.
*/
@LuaFunction
public final void send( IArguments args ) throws LuaException
public final void send( Object message, Optional<Boolean> binary ) throws LuaException
{
checkOpen();
String text = StringUtil.toString( args.get( 0 ) );
String text = StringUtil.toString( message );
if( options.websocketMessage != 0 && text.length() > options.websocketMessage )
{
throw new LuaException( "Message is too large" );
}
boolean binary = args.optBoolean( 1, false );
websocket.environment().addTrackingChange( TrackingField.WEBSOCKET_OUTGOING, text.length() );
Channel channel = this.channel;
if( channel != null )
{
channel.writeAndFlush( binary
channel.writeAndFlush( binary.orElse( false )
? new BinaryWebSocketFrame( Unpooled.wrappedBuffer( LuaValues.encode( text ) ) )
: new TextWebSocketFrame( text ) );
}
}
/**
* Close this websocket. This will terminate the connection, meaning messages can no longer be sent or received
* along it.
*/
@LuaFunction( "close" )
public final void doClose()
{

View File

@@ -34,7 +34,7 @@ import java.util.function.Function;
import static org.objectweb.asm.Opcodes.*;
public class Generator<T>
public final class Generator<T>
{
private static final AtomicInteger METHOD_ID = new AtomicInteger();
@@ -99,26 +99,28 @@ public class Generator<T>
LuaFunction annotation = method.getAnnotation( LuaFunction.class );
if( annotation == null ) continue;
if( Modifier.isStatic( method.getModifiers() ) )
{
ComputerCraft.log.warn( "LuaFunction method {}.{} should be an instance method.", method.getDeclaringClass(), method.getName() );
continue;
}
T instance = methodCache.getUnchecked( method ).orElse( null );
if( instance == null ) continue;
if( methods == null ) methods = new ArrayList<>();
addMethod( methods, method, annotation, instance );
}
if( annotation.mainThread() ) instance = wrap.apply( instance );
for( GenericSource.GenericMethod method : GenericSource.GenericMethod.all() )
{
if( !method.target.isAssignableFrom( klass ) ) continue;
String[] names = annotation.value();
boolean isSimple = method.getReturnType() != MethodResult.class && !annotation.mainThread();
if( names.length == 0 )
{
methods.add( new NamedMethod<>( method.getName(), instance, isSimple ) );
}
else
{
for( String name : names )
{
methods.add( new NamedMethod<>( name, instance, isSimple ) );
}
}
T instance = methodCache.getUnchecked( method.method ).orElse( null );
if( instance == null ) continue;
if( methods == null ) methods = new ArrayList<>();
addMethod( methods, method.method, method.annotation, instance );
}
if( methods == null ) return Collections.emptyList();
@@ -126,19 +128,40 @@ public class Generator<T>
return Collections.unmodifiableList( methods );
}
private void addMethod( List<NamedMethod<T>> methods, Method method, LuaFunction annotation, T instance )
{
if( annotation.mainThread() ) instance = wrap.apply( instance );
String[] names = annotation.value();
boolean isSimple = method.getReturnType() != MethodResult.class && !annotation.mainThread();
if( names.length == 0 )
{
methods.add( new NamedMethod<>( method.getName(), instance, isSimple ) );
}
else
{
for( String name : names )
{
methods.add( new NamedMethod<>( name, instance, isSimple ) );
}
}
}
@Nonnull
private Optional<T> build( Method method )
{
String name = method.getDeclaringClass().getName() + "." + method.getName();
int modifiers = method.getModifiers();
if( !Modifier.isFinal( modifiers ) )
// Instance methods must be final - this prevents them being overridden and potentially exposed twice.
if( !Modifier.isStatic( modifiers ) && !Modifier.isFinal( modifiers ) )
{
ComputerCraft.log.warn( "Lua Method {} should be final.", name );
}
if( Modifier.isStatic( modifiers ) || !Modifier.isPublic( modifiers ) )
if( !Modifier.isPublic( modifiers ) )
{
ComputerCraft.log.error( "Lua Method {} should be a public instance method.", name );
ComputerCraft.log.error( "Lua Method {} should be a public method.", name );
return Optional.empty();
}
@@ -160,16 +183,20 @@ public class Generator<T>
}
}
// We have some rather ugly handling of static methods in both here and the main generate function. Static methods
// only come from generic sources, so this should be safe.
Class<?> target = Modifier.isStatic( modifiers ) ? method.getParameterTypes()[0] : method.getDeclaringClass();
try
{
String className = method.getDeclaringClass().getName() + "$cc$" + method.getName() + METHOD_ID.getAndIncrement();
byte[] bytes = generate( className, method );
byte[] bytes = generate( className, target, method );
if( bytes == null ) return Optional.empty();
Class<?> klass = DeclaringClassLoader.INSTANCE.define( className, bytes, method.getDeclaringClass().getProtectionDomain() );
return Optional.of( klass.asSubclass( base ).newInstance() );
return Optional.of( klass.asSubclass( base ).getDeclaredConstructor().newInstance() );
}
catch( InstantiationException | IllegalAccessException | ClassFormatError | RuntimeException e )
catch( ReflectiveOperationException | ClassFormatError | RuntimeException e )
{
ComputerCraft.log.error( "Error generating wrapper for {}.", name, e );
return Optional.empty();
@@ -178,7 +205,7 @@ public class Generator<T>
}
@Nullable
private byte[] generate( String className, Method method )
private byte[] generate( String className, Class<?> target, Method method )
{
String internalName = className.replace( ".", "/" );
@@ -200,19 +227,27 @@ public class Generator<T>
{
MethodVisitor mw = cw.visitMethod( ACC_PUBLIC, METHOD_NAME, methodDesc, null, EXCEPTIONS );
mw.visitCode();
mw.visitVarInsn( ALOAD, 1 );
mw.visitTypeInsn( CHECKCAST, Type.getInternalName( method.getDeclaringClass() ) );
// If we're an instance method, load the this parameter.
if( !Modifier.isStatic( method.getModifiers() ) )
{
mw.visitVarInsn( ALOAD, 1 );
mw.visitTypeInsn( CHECKCAST, Type.getInternalName( target ) );
}
int argIndex = 0;
for( java.lang.reflect.Type genericArg : method.getGenericParameterTypes() )
{
Boolean loadedArg = loadArg( mw, method, genericArg, argIndex );
Boolean loadedArg = loadArg( mw, target, method, genericArg, argIndex );
if( loadedArg == null ) return null;
if( loadedArg ) argIndex++;
}
mw.visitMethodInsn( INVOKEVIRTUAL, Type.getInternalName( method.getDeclaringClass() ), method.getName(),
Type.getMethodDescriptor( method ), false );
mw.visitMethodInsn(
Modifier.isStatic( method.getModifiers() ) ? INVOKESTATIC : INVOKEVIRTUAL,
Type.getInternalName( method.getDeclaringClass() ), method.getName(),
Type.getMethodDescriptor( method ), false
);
// We allow a reasonable amount of flexibility on the return value's type. Alongside the obvious MethodResult,
// we convert basic types into an immediate result.
@@ -250,8 +285,15 @@ public class Generator<T>
return cw.toByteArray();
}
private Boolean loadArg( MethodVisitor mw, Method method, java.lang.reflect.Type genericArg, int argIndex )
private Boolean loadArg( MethodVisitor mw, Class<?> target, Method method, java.lang.reflect.Type genericArg, int argIndex )
{
if( genericArg == target )
{
mw.visitVarInsn( ALOAD, 1 );
mw.visitTypeInsn( CHECKCAST, Type.getInternalName( target ) );
return false;
}
Class<?> arg = Reflect.getRawType( method, genericArg, true );
if( arg == null ) return null;

View File

@@ -0,0 +1,121 @@
/*
* 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.asm;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.lua.LuaFunction;
import dan200.computercraft.shared.peripheral.generic.GenericPeripheralProvider;
import dan200.computercraft.shared.util.ServiceUtil;
import net.minecraft.util.ResourceLocation;
import javax.annotation.Nonnull;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* A generic source of {@link LuaMethod} functions. This allows for injecting methods onto objects you do not own.
*
* Unlike conventional Lua objects, the annotated methods should be {@code static}, with their target as the first
* parameter.
*
* This is used by the generic peripheral system ({@link GenericPeripheralProvider}) to provide methods for arbitrary
* tile entities. Eventually this'll be be exposed in the public API. Until it is stabilised, it will remain in this
* package - do not use it in external mods!
*/
public interface GenericSource
{
/**
* A unique identifier for this generic source. This may be used in the future to allow disabling specific sources.
*
* @return This source's identifier.
*/
@Nonnull
ResourceLocation id();
/**
* Register a stream of generic sources.
*
* @param sources The source of generic methods.
* @see ServiceUtil For ways to load this. Sadly {@link java.util.ServiceLoader} is broken under Forge, but we don't
* want to add a hard-dep on Forge within core either.
*/
static void setup( Supplier<Stream<GenericSource>> sources )
{
GenericMethod.sources = sources;
}
/**
* A generic method is a method belonging to a {@link GenericSource} with a known target.
*/
class GenericMethod
{
final Method method;
final LuaFunction annotation;
final Class<?> target;
static Supplier<Stream<GenericSource>> sources;
private static List<GenericMethod> cache;
GenericMethod( Method method, LuaFunction annotation, Class<?> target )
{
this.method = method;
this.annotation = annotation;
this.target = target;
}
/**
* Find all public static methods annotated with {@link LuaFunction} which belong to a {@link GenericSource}.
*
* @return All available generic methods.
*/
static List<GenericMethod> all()
{
if( cache != null ) return cache;
if( sources == null )
{
ComputerCraft.log.warn( "Getting GenericMethods without a provider" );
return cache = Collections.emptyList();
}
return cache = sources.get()
.flatMap( x -> Arrays.stream( x.getClass().getDeclaredMethods() ) )
.map( method ->
{
LuaFunction annotation = method.getAnnotation( LuaFunction.class );
if( annotation == null ) return null;
if( !Modifier.isStatic( method.getModifiers() ) )
{
ComputerCraft.log.error( "GenericSource method {}.{} should be static.", method.getDeclaringClass(), method.getName() );
return null;
}
Type[] types = method.getGenericParameterTypes();
if( types.length == 0 )
{
ComputerCraft.log.error( "GenericSource method {}.{} has no parameters.", method.getDeclaringClass(), method.getName() );
return null;
}
Class<?> target = Reflect.getRawType( method, types[0], false );
if( target == null ) return null;
return new GenericMethod( method, annotation, target );
} )
.filter( Objects::nonNull )
.collect( Collectors.toList() );
}
}
}

View File

@@ -14,10 +14,8 @@ import java.util.Collections;
public interface LuaMethod
{
Generator<LuaMethod> GENERATOR = new Generator<>( LuaMethod.class, Collections.singletonList( ILuaContext.class ),
m -> ( target, context, args ) -> {
long id = context.issueMainThreadTask( () -> TaskCallback.checkUnwrap( m.apply( target, context, args ) ) );
return new TaskCallback( id ).pull;
} );
m -> ( target, context, args ) -> TaskCallback.make( context, () -> TaskCallback.checkUnwrap( m.apply( target, context, args ) ) )
);
IntCache<LuaMethod> DYNAMIC = new IntCache<>(
method -> ( instance, context, args ) -> ((IDynamicLuaObject) instance).callMethod( context, method, args )

View File

@@ -8,7 +8,7 @@ package dan200.computercraft.core.asm;
import javax.annotation.Nonnull;
public class NamedMethod<T>
public final class NamedMethod<T>
{
private final String name;
private final T method;

View File

@@ -19,10 +19,8 @@ import java.util.Arrays;
public interface PeripheralMethod
{
Generator<PeripheralMethod> GENERATOR = new Generator<>( PeripheralMethod.class, Arrays.asList( ILuaContext.class, IComputerAccess.class ),
m -> ( target, context, computer, args ) -> {
long id = context.issueMainThreadTask( () -> TaskCallback.checkUnwrap( m.apply( target, context, computer, args ) ) );
return new TaskCallback( id ).pull;
} );
m -> ( target, context, computer, args ) -> TaskCallback.make( context, () -> TaskCallback.checkUnwrap( m.apply( target, context, computer, args ) ) )
);
IntCache<PeripheralMethod> DYNAMIC = new IntCache<>(
method -> ( instance, context, computer, args ) -> ((IDynamicPeripheral) instance).callMethod( computer, context, method, args )

View File

@@ -6,19 +6,17 @@
package dan200.computercraft.core.asm;
import dan200.computercraft.api.lua.ILuaCallback;
import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.api.lua.MethodResult;
import dan200.computercraft.api.lua.*;
import javax.annotation.Nonnull;
import java.util.Arrays;
class TaskCallback implements ILuaCallback
public final class TaskCallback implements ILuaCallback
{
final MethodResult pull = MethodResult.pullEvent( "task_complete", this );
private final MethodResult pull = MethodResult.pullEvent( "task_complete", this );
private final long task;
TaskCallback( long task )
private TaskCallback( long task )
{
this.task = task;
}
@@ -50,9 +48,21 @@ class TaskCallback implements ILuaCallback
}
}
public static Object[] checkUnwrap( MethodResult result )
static Object[] checkUnwrap( MethodResult result )
{
if( result.getCallback() != null ) throw new IllegalStateException( "Cannot return MethodResult currently" );
if( result.getCallback() != null )
{
// Due to how tasks are implemented, we can't currently return a MethodResult. This is an
// entirely artificial limitation - we can remove it if it ever becomes an issue.
throw new IllegalStateException( "Cannot return MethodResult for mainThread task." );
}
return result.getResult();
}
public static MethodResult make( ILuaContext context, ILuaTask func ) throws LuaException
{
long task = context.issueMainThreadTask( func );
return new TaskCallback( task ).pull;
}
}

View File

@@ -395,14 +395,7 @@ public final class ComputerThread
executor.timeout.hardAbort();
executor.abort();
if( afterHardAbort >= ABORT_TIMEOUT )
{
// If we've hard aborted but we're still not dead, dump the stack trace and interrupt
// the task.
timeoutTask( executor, runner.owner, afterStart );
runner.owner.interrupt();
}
else if( afterHardAbort >= ABORT_TIMEOUT * 2 )
if( afterHardAbort >= ABORT_TIMEOUT * 2 )
{
// If we've hard aborted and interrupted, and we're still not dead, then mark the runner
// as dead, finish off the task, and spawn a new runner.
@@ -421,6 +414,13 @@ public final class ComputerThread
}
}
}
else if( afterHardAbort >= ABORT_TIMEOUT )
{
// If we've hard aborted but we're still not dead, dump the stack trace and interrupt
// the task.
timeoutTask( executor, runner.owner, afterStart );
runner.owner.interrupt();
}
}
}
}

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

@@ -10,6 +10,7 @@ import dan200.computercraft.api.filesystem.IMount;
import dan200.computercraft.api.filesystem.IWritableMount;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.IOException;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
@@ -85,7 +86,7 @@ class MountWrapper
}
catch( IOException e )
{
throw new FileSystemException( e.getMessage() );
throw localExceptionOf( path, e );
}
}
@@ -98,7 +99,7 @@ class MountWrapper
}
catch( IOException e )
{
throw localExceptionOf( e );
throw localExceptionOf( path, e );
}
}
@@ -116,7 +117,7 @@ class MountWrapper
}
catch( IOException e )
{
throw localExceptionOf( e );
throw localExceptionOf( path, e );
}
}
@@ -130,7 +131,7 @@ class MountWrapper
}
catch( IOException e )
{
throw localExceptionOf( e );
throw localExceptionOf( path, e );
}
}
@@ -145,7 +146,7 @@ class MountWrapper
}
catch( IOException e )
{
throw localExceptionOf( e );
throw localExceptionOf( path, e );
}
}
@@ -165,7 +166,7 @@ class MountWrapper
}
catch( IOException e )
{
throw localExceptionOf( e );
throw localExceptionOf( path, e );
}
}
@@ -187,7 +188,7 @@ class MountWrapper
}
catch( IOException e )
{
throw localExceptionOf( e );
throw localExceptionOf( path, e );
}
}
@@ -195,9 +196,9 @@ class MountWrapper
{
if( writableMount == null ) throw exceptionOf( path, "Access denied" );
path = toLocal( path );
try
{
path = toLocal( path );
if( mount.exists( path ) )
{
writableMount.delete( path );
@@ -209,7 +210,7 @@ class MountWrapper
}
catch( IOException e )
{
throw localExceptionOf( e );
throw localExceptionOf( path, e );
}
}
@@ -243,7 +244,7 @@ class MountWrapper
}
catch( IOException e )
{
throw localExceptionOf( e );
throw localExceptionOf( path, e );
}
}
@@ -281,7 +282,7 @@ class MountWrapper
}
catch( IOException e )
{
throw localExceptionOf( e );
throw localExceptionOf( path, e );
}
}
@@ -290,7 +291,7 @@ class MountWrapper
return FileSystem.toLocal( path, location );
}
private FileSystemException localExceptionOf( IOException e )
private FileSystemException localExceptionOf( @Nullable String localPath, @Nonnull IOException e )
{
if( !location.isEmpty() && e instanceof FileOperationException )
{
@@ -298,6 +299,14 @@ class MountWrapper
if( ex.getFilename() != null ) return localExceptionOf( ex.getFilename(), ex.getMessage() );
}
if( e instanceof java.nio.file.FileSystemException )
{
// This error will contain the absolute path, leaking information about where MC is installed. We drop that,
// just taking the reason. We assume that the error refers to the input path.
String message = ((java.nio.file.FileSystemException) e).getReason().trim();
return localPath == null ? new FileSystemException( message ) : localExceptionOf( localPath, message );
}
return new FileSystemException( e.getMessage() );
}

View File

@@ -83,9 +83,9 @@ class VarargArguments implements IArguments
public ByteBuffer getBytes( int index ) throws LuaException
{
LuaValue value = varargs.arg( index + 1 );
if( !(value instanceof LuaString) ) throw LuaValues.badArgument( index, "string", value.typeName() );
if( !(value instanceof LuaBaseString) ) throw LuaValues.badArgument( index, "string", value.typeName() );
LuaString str = (LuaString) value;
LuaString str = ((LuaBaseString) value).strvalue();
return ByteBuffer.wrap( str.bytes, str.offset, str.length ).asReadOnlyBuffer();
}
@@ -94,9 +94,9 @@ class VarargArguments implements IArguments
{
LuaValue value = varargs.arg( index + 1 );
if( value.isNil() ) return Optional.empty();
if( !(value instanceof LuaString) ) throw LuaValues.badArgument( index, "string", value.typeName() );
if( !(value instanceof LuaBaseString) ) throw LuaValues.badArgument( index, "string", value.typeName() );
LuaString str = (LuaString) value;
LuaString str = ((LuaBaseString) value).strvalue();
return Optional.of( ByteBuffer.wrap( str.bytes, str.offset, str.length ).asReadOnlyBuffer() );
}
}

View File

@@ -10,6 +10,8 @@ import dan200.computercraft.shared.util.Palette;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.network.PacketBuffer;
import javax.annotation.Nonnull;
public class Terminal
{
private static final String base16 = "0123456789abcdef";
@@ -29,7 +31,6 @@ public class Terminal
private final Palette m_palette = new Palette();
private boolean m_changed = false;
private final Runnable onChanged;
public Terminal( int width, int height )
@@ -184,6 +185,7 @@ public class Terminal
return m_cursorBackgroundColour;
}
@Nonnull
public Palette getPalette()
{
return m_palette;
@@ -305,15 +307,9 @@ public class Terminal
public final void setChanged()
{
m_changed = true;
if( onChanged != null ) onChanged.run();
}
public final void clearChanged()
{
m_changed = false;
}
public synchronized void write( PacketBuffer buffer )
{
buffer.writeInt( m_cursorX );

View File

@@ -23,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 ) );
generator.addProvider( new Tags( generator, event.getExistingFileHelper() ) );
}
}

View File

@@ -13,11 +13,11 @@ import dan200.computercraft.ComputerCraft;
import net.minecraft.data.DataGenerator;
import net.minecraft.data.DirectoryCache;
import net.minecraft.data.IDataProvider;
import net.minecraft.loot.LootParameterSets;
import net.minecraft.loot.LootTable;
import net.minecraft.loot.LootTableManager;
import net.minecraft.loot.ValidationTracker;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.storage.loot.LootParameterSets;
import net.minecraft.world.storage.loot.LootTable;
import net.minecraft.world.storage.loot.LootTableManager;
import net.minecraft.world.storage.loot.ValidationTracker;
import javax.annotation.Nonnull;
import java.io.IOException;

View File

@@ -7,16 +7,18 @@
package dan200.computercraft.data;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.Registry;
import dan200.computercraft.shared.data.BlockNamedEntityLootCondition;
import dan200.computercraft.shared.data.HasComputerIdLootCondition;
import dan200.computercraft.shared.data.PlayerCreativeLootCondition;
import dan200.computercraft.shared.proxy.ComputerCraftProxyCommon;
import net.minecraft.block.Block;
import net.minecraft.data.DataGenerator;
import net.minecraft.loot.*;
import net.minecraft.loot.conditions.Alternative;
import net.minecraft.loot.conditions.SurvivesExplosion;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.storage.loot.*;
import net.minecraft.world.storage.loot.conditions.Alternative;
import net.minecraft.world.storage.loot.conditions.SurvivesExplosion;
import net.minecraftforge.fml.RegistryObject;
import java.util.function.BiConsumer;
@@ -30,19 +32,19 @@ public class LootTables extends LootTableProvider
@Override
protected void registerLoot( BiConsumer<ResourceLocation, LootTable> add )
{
basicDrop( add, ComputerCraft.Blocks.diskDrive );
basicDrop( add, ComputerCraft.Blocks.monitorNormal );
basicDrop( add, ComputerCraft.Blocks.monitorAdvanced );
basicDrop( add, ComputerCraft.Blocks.printer );
basicDrop( add, ComputerCraft.Blocks.speaker );
basicDrop( add, ComputerCraft.Blocks.wiredModemFull );
basicDrop( add, ComputerCraft.Blocks.wirelessModemNormal );
basicDrop( add, ComputerCraft.Blocks.wirelessModemAdvanced );
basicDrop( add, Registry.ModBlocks.DISK_DRIVE );
basicDrop( add, Registry.ModBlocks.MONITOR_NORMAL );
basicDrop( add, Registry.ModBlocks.MONITOR_ADVANCED );
basicDrop( add, Registry.ModBlocks.PRINTER );
basicDrop( add, Registry.ModBlocks.SPEAKER );
basicDrop( add, Registry.ModBlocks.WIRED_MODEM_FULL );
basicDrop( add, Registry.ModBlocks.WIRELESS_MODEM_NORMAL );
basicDrop( add, Registry.ModBlocks.WIRELESS_MODEM_ADVANCED );
computerDrop( add, ComputerCraft.Blocks.computerNormal );
computerDrop( add, ComputerCraft.Blocks.computerAdvanced );
computerDrop( add, ComputerCraft.Blocks.turtleNormal );
computerDrop( add, ComputerCraft.Blocks.turtleAdvanced );
computerDrop( add, Registry.ModBlocks.COMPUTER_NORMAL );
computerDrop( add, Registry.ModBlocks.COMPUTER_ADVANCED );
computerDrop( add, Registry.ModBlocks.TURTLE_NORMAL );
computerDrop( add, Registry.ModBlocks.TURTLE_ADVANCED );
add.accept( ComputerCraftProxyCommon.ForgeHandlers.LOOT_TREASURE_DISK, LootTable
.builder()
@@ -50,8 +52,9 @@ public class LootTables extends LootTableProvider
.build() );
}
private static void basicDrop( BiConsumer<ResourceLocation, LootTable> add, Block block )
private static <T extends Block> void basicDrop( BiConsumer<ResourceLocation, LootTable> add, RegistryObject<T> wrapper )
{
Block block = wrapper.get();
add.accept( block.getLootTable(), LootTable
.builder()
.setParameterSet( LootParameterSets.BLOCK )
@@ -63,8 +66,9 @@ public class LootTables extends LootTableProvider
).build() );
}
private static void computerDrop( BiConsumer<ResourceLocation, LootTable> add, Block block )
private static <T extends Block> void computerDrop( BiConsumer<ResourceLocation, LootTable> add, RegistryObject<T> wrapper )
{
Block block = wrapper.get();
add.accept( block.getLootTable(), LootTable
.builder()
.setParameterSet( LootParameterSets.BLOCK )
@@ -73,9 +77,9 @@ public class LootTables extends LootTableProvider
.rolls( ConstantRange.of( 1 ) )
.addEntry( DynamicLootEntry.func_216162_a( new ResourceLocation( ComputerCraft.MOD_ID, "computer" ) ) )
.acceptCondition( Alternative.builder(
BlockNamedEntityLootCondition.builder(),
HasComputerIdLootCondition.builder(),
PlayerCreativeLootCondition.builder().inverted()
BlockNamedEntityLootCondition.BUILDER,
HasComputerIdLootCondition.BUILDER,
PlayerCreativeLootCondition.BUILDER.inverted()
) )
).build() );
}

View File

@@ -8,6 +8,7 @@ package dan200.computercraft.data;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.data.Tags.CCTags;
import dan200.computercraft.shared.Registry;
import dan200.computercraft.shared.TurtleUpgrades;
import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.pocket.items.PocketComputerItemFactory;
@@ -20,7 +21,7 @@ import net.minecraft.advancements.criterion.ItemPredicate;
import net.minecraft.block.Blocks;
import net.minecraft.data.*;
import net.minecraft.item.*;
import net.minecraft.tags.Tag;
import net.minecraft.tags.ITag;
import net.minecraft.util.IItemProvider;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.common.Tags;
@@ -55,12 +56,12 @@ public class Recipes extends RecipeProvider
for( Colour colour : Colour.VALUES )
{
ShapelessRecipeBuilder
.shapelessRecipe( ComputerCraft.Items.disk )
.shapelessRecipe( Registry.ModItems.DISK.get() )
.addIngredient( Tags.Items.DUSTS_REDSTONE )
.addIngredient( Items.PAPER )
.addIngredient( DyeItem.getItem( ofColour( colour ) ) )
.setGroup( "computercraft:disk" )
.addCriterion( "has_drive", inventoryChange( ComputerCraft.Blocks.diskDrive ) )
.addCriterion( "has_drive", inventoryChange( Registry.ModBlocks.DISK_DRIVE.get() ) )
.build( RecipeWrapper.wrap(
ImpostorShapelessRecipe.SERIALIZER, add,
x -> x.putInt( "color", colour.getHex() )
@@ -140,7 +141,7 @@ public class Recipes extends RecipeProvider
private void basicRecipes( @Nonnull Consumer<IFinishedRecipe> add )
{
ShapedRecipeBuilder
.shapedRecipe( ComputerCraft.Items.cable, 6 )
.shapedRecipe( Registry.ModItems.CABLE.get(), 6 )
.patternLine( " # " )
.patternLine( "#R#" )
.patternLine( " # " )
@@ -151,7 +152,7 @@ public class Recipes extends RecipeProvider
.build( add );
ShapedRecipeBuilder
.shapedRecipe( ComputerCraft.Blocks.computerNormal )
.shapedRecipe( Registry.ModBlocks.COMPUTER_NORMAL.get() )
.patternLine( "###" )
.patternLine( "#R#" )
.patternLine( "#G#" )
@@ -162,7 +163,7 @@ public class Recipes extends RecipeProvider
.build( add );
ShapedRecipeBuilder
.shapedRecipe( ComputerCraft.Blocks.computerAdvanced )
.shapedRecipe( Registry.ModBlocks.COMPUTER_ADVANCED.get() )
.patternLine( "###" )
.patternLine( "#R#" )
.patternLine( "#G#" )
@@ -173,7 +174,7 @@ public class Recipes extends RecipeProvider
.build( add );
ShapedRecipeBuilder
.shapedRecipe( ComputerCraft.Blocks.computerCommand )
.shapedRecipe( Registry.ModBlocks.COMPUTER_COMMAND.get() )
.patternLine( "###" )
.patternLine( "#R#" )
.patternLine( "#G#" )
@@ -184,7 +185,7 @@ public class Recipes extends RecipeProvider
.build( add );
ShapedRecipeBuilder
.shapedRecipe( ComputerCraft.Blocks.diskDrive )
.shapedRecipe( Registry.ModBlocks.DISK_DRIVE.get() )
.patternLine( "###" )
.patternLine( "#R#" )
.patternLine( "#R#" )
@@ -194,7 +195,7 @@ public class Recipes extends RecipeProvider
.build( add );
ShapedRecipeBuilder
.shapedRecipe( ComputerCraft.Blocks.monitorNormal )
.shapedRecipe( Registry.ModBlocks.MONITOR_NORMAL.get() )
.patternLine( "###" )
.patternLine( "#G#" )
.patternLine( "###" )
@@ -204,7 +205,7 @@ public class Recipes extends RecipeProvider
.build( add );
ShapedRecipeBuilder
.shapedRecipe( ComputerCraft.Blocks.monitorAdvanced, 4 )
.shapedRecipe( Registry.ModBlocks.MONITOR_ADVANCED.get(), 4 )
.patternLine( "###" )
.patternLine( "#G#" )
.patternLine( "###" )
@@ -214,7 +215,7 @@ public class Recipes extends RecipeProvider
.build( add );
ShapedRecipeBuilder
.shapedRecipe( ComputerCraft.Items.pocketComputerNormal )
.shapedRecipe( Registry.ModItems.POCKET_COMPUTER_NORMAL.get() )
.patternLine( "###" )
.patternLine( "#A#" )
.patternLine( "#G#" )
@@ -226,7 +227,7 @@ public class Recipes extends RecipeProvider
.build( add );
ShapedRecipeBuilder
.shapedRecipe( ComputerCraft.Items.pocketComputerAdvanced )
.shapedRecipe( Registry.ModItems.POCKET_COMPUTER_ADVANCED.get() )
.patternLine( "###" )
.patternLine( "#A#" )
.patternLine( "#G#" )
@@ -238,7 +239,7 @@ public class Recipes extends RecipeProvider
.build( add );
ShapedRecipeBuilder
.shapedRecipe( ComputerCraft.Blocks.printer )
.shapedRecipe( Registry.ModBlocks.PRINTER.get() )
.patternLine( "###" )
.patternLine( "#R#" )
.patternLine( "#D#" )
@@ -249,7 +250,7 @@ public class Recipes extends RecipeProvider
.build( add );
ShapedRecipeBuilder
.shapedRecipe( ComputerCraft.Blocks.speaker )
.shapedRecipe( Registry.ModBlocks.SPEAKER.get() )
.patternLine( "###" )
.patternLine( "#N#" )
.patternLine( "#R#" )
@@ -260,29 +261,29 @@ public class Recipes extends RecipeProvider
.build( add );
ShapedRecipeBuilder
.shapedRecipe( ComputerCraft.Items.wiredModem )
.shapedRecipe( Registry.ModItems.WIRED_MODEM.get() )
.patternLine( "###" )
.patternLine( "#R#" )
.patternLine( "###" )
.key( '#', Tags.Items.STONE )
.key( 'R', Tags.Items.DUSTS_REDSTONE )
.addCriterion( "has_computer", inventoryChange( CCTags.COMPUTER ) )
.addCriterion( "has_cable", inventoryChange( ComputerCraft.Items.cable ) )
.addCriterion( "has_cable", inventoryChange( Registry.ModItems.CABLE.get() ) )
.build( add );
ShapelessRecipeBuilder
.shapelessRecipe( ComputerCraft.Blocks.wiredModemFull )
.addIngredient( ComputerCraft.Items.wiredModem )
.shapelessRecipe( Registry.ModBlocks.WIRED_MODEM_FULL.get() )
.addIngredient( Registry.ModItems.WIRED_MODEM.get() )
.addCriterion( "has_modem", inventoryChange( CCTags.WIRED_MODEM ) )
.build( add, new ResourceLocation( ComputerCraft.MOD_ID, "wired_modem_full_from" ) );
ShapelessRecipeBuilder
.shapelessRecipe( ComputerCraft.Items.wiredModem )
.addIngredient( ComputerCraft.Blocks.wiredModemFull )
.shapelessRecipe( Registry.ModItems.WIRED_MODEM.get() )
.addIngredient( Registry.ModBlocks.WIRED_MODEM_FULL.get() )
.addCriterion( "has_modem", inventoryChange( CCTags.WIRED_MODEM ) )
.build( add, new ResourceLocation( ComputerCraft.MOD_ID, "wired_modem_full_to" ) );
ShapedRecipeBuilder
.shapedRecipe( ComputerCraft.Blocks.wirelessModemNormal )
.shapedRecipe( Registry.ModBlocks.WIRELESS_MODEM_NORMAL.get() )
.patternLine( "###" )
.patternLine( "#E#" )
.patternLine( "###" )
@@ -292,14 +293,14 @@ public class Recipes extends RecipeProvider
.build( add );
ShapedRecipeBuilder
.shapedRecipe( ComputerCraft.Blocks.wirelessModemAdvanced )
.shapedRecipe( Registry.ModBlocks.WIRELESS_MODEM_ADVANCED.get() )
.patternLine( "###" )
.patternLine( "#E#" )
.patternLine( "###" )
.key( '#', Tags.Items.INGOTS_GOLD )
.key( 'E', Items.ENDER_EYE )
.addCriterion( "has_computer", inventoryChange( CCTags.COMPUTER ) )
.addCriterion( "has_wireless", inventoryChange( ComputerCraft.Blocks.wirelessModemNormal ) )
.addCriterion( "has_wireless", inventoryChange( Registry.ModBlocks.WIRELESS_MODEM_NORMAL.get() ) )
.build( add );
}
@@ -308,7 +309,7 @@ public class Recipes extends RecipeProvider
return DyeColor.byId( 15 - colour.ordinal() );
}
private static InventoryChangeTrigger.Instance inventoryChange( Tag<Item> stack )
private static InventoryChangeTrigger.Instance inventoryChange( ITag<Item> stack )
{
return InventoryChangeTrigger.Instance.forItems( ItemPredicate.Builder.create().tag( stack ).build() );
}

View File

@@ -7,46 +7,56 @@
package dan200.computercraft.data;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.Registry;
import net.minecraft.data.BlockTagsProvider;
import net.minecraft.data.DataGenerator;
import net.minecraft.data.ItemTagsProvider;
import net.minecraft.item.Item;
import net.minecraft.tags.ITag;
import net.minecraft.tags.ItemTags;
import net.minecraft.tags.Tag;
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_;
public static class CCTags
{
public static final Tag<Item> COMPUTER = item( "computer" );
public static final Tag<Item> TURTLE = item( "turtle" );
public static final Tag<Item> WIRED_MODEM = item( "wired_modem" );
public static final Tag<Item> MONITOR = item( "monitor" );
public static final ITag.INamedTag<Item> COMPUTER = item( "computer" );
public static final ITag.INamedTag<Item> TURTLE = item( "turtle" );
public static final ITag.INamedTag<Item> WIRED_MODEM = item( "wired_modem" );
public static final ITag.INamedTag<Item> MONITOR = item( "monitor" );
}
public Tags( DataGenerator generator )
public Tags( DataGenerator generator, ExistingFileHelper helper )
{
super( generator );
super( generator, new BlockTagsProvider( generator, ComputerCraft.MOD_ID, helper ), ComputerCraft.MOD_ID, helper );
}
@Override
protected void registerTags()
{
getBuilder( COMPUTER )
.add( ComputerCraft.Items.computerNormal )
.add( ComputerCraft.Items.computerAdvanced )
.add( ComputerCraft.Items.computerCommand );
getBuilder( TURTLE ).add( ComputerCraft.Items.turtleNormal, ComputerCraft.Items.turtleAdvanced );
getBuilder( WIRED_MODEM ).add( ComputerCraft.Items.wiredModem, ComputerCraft.Blocks.wiredModemFull.asItem() );
getBuilder( MONITOR )
.add( ComputerCraft.Blocks.monitorNormal.asItem() )
.add( ComputerCraft.Blocks.monitorAdvanced.asItem() );
getOrCreateBuilder( COMPUTER ).add(
Registry.ModItems.COMPUTER_NORMAL.get(),
Registry.ModItems.COMPUTER_ADVANCED.get(),
Registry.ModItems.COMPUTER_COMMAND.get()
);
getOrCreateBuilder( TURTLE ).add( Registry.ModItems.TURTLE_NORMAL.get(), Registry.ModItems.TURTLE_ADVANCED.get() );
getOrCreateBuilder( WIRED_MODEM ).add( Registry.ModItems.WIRED_MODEM.get(), Registry.ModItems.WIRED_MODEM_FULL.get() );
getOrCreateBuilder( MONITOR ).add( Registry.ModItems.MONITOR_NORMAL.get(), Registry.ModItems.MONITOR_ADVANCED.get() );
getOrCreateBuilder( PIGLIN_LOVED ).add(
Registry.ModItems.COMPUTER_ADVANCED.get(), Registry.ModItems.TURTLE_ADVANCED.get(),
Registry.ModItems.WIRELESS_MODEM_ADVANCED.get(), Registry.ModItems.POCKET_COMPUTER_ADVANCED.get(),
Registry.ModItems.MONITOR_ADVANCED.get()
);
}
private static Tag<Item> item( String name )
private static ITag.INamedTag<Item> item( String name )
{
return new ItemTags.Wrapper( new ResourceLocation( ComputerCraft.MOD_ID, name ) );
return ItemTags.makeWrapperTag( new ResourceLocation( ComputerCraft.MOD_ID, name ).toString() );
}
}

View File

@@ -45,6 +45,7 @@ public final class Config
private static final ConfigValue<String> defaultComputerSettings;
private static final ConfigValue<Boolean> debugEnabled;
private static final ConfigValue<Boolean> logComputerErrors;
private static final ConfigValue<Boolean> commandRequireCreative;
private static final ConfigValue<Integer> computerThreads;
private static final ConfigValue<Integer> maxMainGlobalTime;
@@ -72,7 +73,19 @@ public final class Config
private static final ConfigValue<Boolean> turtlesCanPush;
private static final ConfigValue<List<? extends String>> turtleDisabledActions;
private static final ConfigValue<Integer> computerTermWidth;
private static final ConfigValue<Integer> computerTermHeight;
private static final ConfigValue<Integer> pocketTermWidth;
private static final ConfigValue<Integer> pocketTermHeight;
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;
private static final ForgeConfigSpec serverSpec;
private static final ForgeConfigSpec clientSpec;
@@ -118,6 +131,11 @@ public final class Config
.comment( "Log exceptions thrown by peripherals and other Lua objects.\n" +
"This makes it easier for mod authors to debug problems, but may result in log spam should people use buggy methods." )
.define( "log_computer_errors", ComputerCraft.logComputerErrors );
commandRequireCreative = builder
.comment( "Require players to be in creative mode and be opped in order to interact with command computers." +
"This is the default behaviour for vanilla's Command blocks." )
.define( "command_require_creative", ComputerCraft.commandRequireCreative );
}
{
@@ -254,6 +272,39 @@ public final class Config
builder.pop();
}
{
builder.comment( "Configure the size of various computer's terminals.\n" +
"Larger terminals require more bandwidth, so use with care." ).push( "term_sizes" );
builder.comment( "Terminal size of computers" ).push( "computer" );
computerTermWidth = builder.defineInRange( "width", ComputerCraft.computerTermWidth, 1, 255 );
computerTermHeight = builder.defineInRange( "height", ComputerCraft.computerTermHeight, 1, 255 );
builder.pop();
builder.comment( "Terminal size of pocket computers" ).push( "pocket_computer" );
pocketTermWidth = builder.defineInRange( "width", ComputerCraft.pocketTermWidth, 1, 255 );
pocketTermHeight = builder.defineInRange( "height", ComputerCraft.pocketTermHeight, 1, 255 );
builder.pop();
builder.comment( "Maximum size of monitors (in blocks)" ).push( "monitor" );
monitorWidth = builder.defineInRange( "width", ComputerCraft.monitorWidth, 1, 32 );
monitorHeight = builder.defineInRange( "height", ComputerCraft.monitorHeight, 1, 32 );
builder.pop();
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();
@@ -261,10 +312,14 @@ public final class Config
.comment( "The renderer to use for monitors. Generally this should be kept at \"best\" - if " +
"monitors have performance issues, you may wish to experiment with alternative renderers." )
.defineEnum( "monitor_renderer", MonitorRenderer.BEST );
monitorDistance = clientBuilder
.comment( "The maximum distance monitors will render at. This defaults to the standard tile entity limit, " +
"but may be extended if you wish to build larger monitors." )
.defineInRange( "monitor_distance", 64, 16, 1024 );
clientSpec = clientBuilder.build();
}
public static void load()
public static void setup()
{
ModLoadingContext.get().registerConfig( ModConfig.Type.SERVER, serverSpec );
ModLoadingContext.get().registerConfig( ModConfig.Type.CLIENT, clientSpec );
@@ -281,6 +336,7 @@ public final class Config
ComputerCraft.debugEnable = debugEnabled.get();
ComputerCraft.computerThreads = computerThreads.get();
ComputerCraft.logComputerErrors = logComputerErrors.get();
ComputerCraft.commandRequireCreative = commandRequireCreative.get();
// Execution
ComputerCraft.computerThreads = computerThreads.get();
@@ -315,8 +371,20 @@ public final class Config
ComputerCraft.turtleDisabledActions.clear();
for( String value : turtleDisabledActions.get() ) ComputerCraft.turtleDisabledActions.add( getAction( value ) );
// Terminal size
ComputerCraft.computerTermWidth = computerTermWidth.get();
ComputerCraft.computerTermHeight = computerTermHeight.get();
ComputerCraft.pocketTermWidth = pocketTermWidth.get();
ComputerCraft.pocketTermHeight = pocketTermHeight.get();
ComputerCraft.monitorWidth = monitorWidth.get();
ComputerCraft.monitorHeight = monitorHeight.get();
// Experimental
ComputerCraft.genericPeripheral = genericPeripheral.get();
// Client
ComputerCraft.monitorRenderer = monitorRenderer.get();
ComputerCraft.monitorDistanceSq = monitorDistance.get() * monitorDistance.get();
}
@SubscribeEvent

View File

@@ -8,6 +8,7 @@ package dan200.computercraft.shared;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.api.peripheral.IPeripheralProvider;
import dan200.computercraft.shared.peripheral.generic.GenericPeripheralProvider;
import dan200.computercraft.shared.util.CapabilityUtil;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
@@ -66,7 +67,7 @@ public final class Peripherals
}
}
return null;
return CapabilityUtil.unwrap( GenericPeripheralProvider.getPeripheral( world, pos, side ), invalidate );
}
}

View File

@@ -22,6 +22,10 @@ import dan200.computercraft.shared.media.items.ItemPrintout;
import dan200.computercraft.shared.media.items.ItemTreasureDisk;
import dan200.computercraft.shared.media.recipes.DiskRecipe;
import dan200.computercraft.shared.media.recipes.PrintoutRecipe;
import dan200.computercraft.shared.network.container.ComputerContainerData;
import dan200.computercraft.shared.network.container.ContainerData;
import dan200.computercraft.shared.network.container.HeldItemContainerData;
import dan200.computercraft.shared.network.container.ViewComputerContainerData;
import dan200.computercraft.shared.peripheral.diskdrive.BlockDiskDrive;
import dan200.computercraft.shared.peripheral.diskdrive.ContainerDiskDrive;
import dan200.computercraft.shared.peripheral.diskdrive.TileDiskDrive;
@@ -49,10 +53,12 @@ import dan200.computercraft.shared.turtle.recipes.TurtleRecipe;
import dan200.computercraft.shared.turtle.recipes.TurtleUpgradeRecipe;
import dan200.computercraft.shared.turtle.upgrades.*;
import dan200.computercraft.shared.util.CreativeTabMain;
import dan200.computercraft.shared.util.FixedPointTileEntityType;
import dan200.computercraft.shared.util.ImpostorRecipe;
import dan200.computercraft.shared.util.ImpostorShapelessRecipe;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.entity.EntityClassification;
import net.minecraft.entity.EntityType;
import net.minecraft.inventory.container.ContainerType;
import net.minecraft.item.BlockItem;
@@ -60,12 +66,20 @@ import net.minecraft.item.Item;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.Items;
import net.minecraft.item.crafting.IRecipeSerializer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.RegistryObject;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.registries.IForgeRegistry;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import java.util.function.BiFunction;
import java.util.function.Function;
@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD )
public final class Registry
@@ -76,211 +90,153 @@ public final class Registry
{
}
@SubscribeEvent
public static void registerBlocks( RegistryEvent.Register<Block> event )
public static final class ModBlocks
{
IForgeRegistry<Block> registry = event.getRegistry();
static final DeferredRegister<Block> BLOCKS = DeferredRegister.create( ForgeRegistries.BLOCKS, ComputerCraft.MOD_ID );
// Computers
ComputerCraft.Blocks.computerNormal = new BlockComputer(
Block.Properties.create( Material.ROCK ).hardnessAndResistance( 2.0f ),
ComputerFamily.NORMAL, TileComputer.FACTORY_NORMAL
);
private static Block.Properties properties()
{
return Block.Properties.create( Material.ROCK ).hardnessAndResistance( 2 );
}
ComputerCraft.Blocks.computerAdvanced = new BlockComputer(
Block.Properties.create( Material.ROCK ).hardnessAndResistance( 2.0f ),
ComputerFamily.ADVANCED, TileComputer.FACTORY_ADVANCED
);
private static Block.Properties turtleProperties()
{
return Block.Properties.create( Material.ROCK ).hardnessAndResistance( 2.5f );
}
ComputerCraft.Blocks.computerCommand = new BlockComputer(
private static Block.Properties modemProperties()
{
return Block.Properties.create( Material.ROCK ).hardnessAndResistance( 1.5f );
}
public static final RegistryObject<BlockComputer> COMPUTER_NORMAL = BLOCKS.register( "computer_normal",
() -> new BlockComputer( properties(), ComputerFamily.NORMAL, ModTiles.COMPUTER_NORMAL ) );
public static final RegistryObject<BlockComputer> COMPUTER_ADVANCED = BLOCKS.register( "computer_advanced",
() -> new BlockComputer( properties(), ComputerFamily.ADVANCED, ModTiles.COMPUTER_ADVANCED ) );
public static final RegistryObject<BlockComputer> COMPUTER_COMMAND = BLOCKS.register( "computer_command", () -> new BlockComputer(
Block.Properties.create( Material.ROCK ).hardnessAndResistance( -1, 6000000.0F ),
ComputerFamily.COMMAND, TileCommandComputer.FACTORY
);
ComputerFamily.COMMAND, ModTiles.COMPUTER_COMMAND
) );
registry.registerAll(
ComputerCraft.Blocks.computerNormal.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "computer_normal" ) ),
ComputerCraft.Blocks.computerAdvanced.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "computer_advanced" ) ),
ComputerCraft.Blocks.computerCommand.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "computer_command" ) )
);
public static final RegistryObject<BlockTurtle> TURTLE_NORMAL = BLOCKS.register( "turtle_normal",
() -> new BlockTurtle( turtleProperties(), ComputerFamily.NORMAL, ModTiles.TURTLE_NORMAL ) );
public static final RegistryObject<BlockTurtle> TURTLE_ADVANCED = BLOCKS.register( "turtle_advanced",
() -> new BlockTurtle( turtleProperties(), ComputerFamily.ADVANCED, ModTiles.TURTLE_ADVANCED ) );
// Turtles
ComputerCraft.Blocks.turtleNormal = new BlockTurtle(
Block.Properties.create( Material.ROCK ).hardnessAndResistance( 2.5f ),
ComputerFamily.NORMAL, TileTurtle.FACTORY_NORMAL
);
public static final RegistryObject<BlockSpeaker> SPEAKER = BLOCKS.register( "speaker", () -> new BlockSpeaker( properties() ) );
public static final RegistryObject<BlockDiskDrive> DISK_DRIVE = BLOCKS.register( "disk_drive", () -> new BlockDiskDrive( properties() ) );
public static final RegistryObject<BlockPrinter> PRINTER = BLOCKS.register( "printer", () -> new BlockPrinter( properties() ) );
ComputerCraft.Blocks.turtleAdvanced = new BlockTurtle(
Block.Properties.create( Material.ROCK ).hardnessAndResistance( 2.5f ),
ComputerFamily.ADVANCED, TileTurtle.FACTORY_ADVANCED
);
public static final RegistryObject<BlockMonitor> MONITOR_NORMAL = BLOCKS.register( "monitor_normal",
() -> new BlockMonitor( properties(), ModTiles.MONITOR_NORMAL ) );
public static final RegistryObject<BlockMonitor> MONITOR_ADVANCED = BLOCKS.register( "monitor_advanced",
() -> new BlockMonitor( properties(), ModTiles.MONITOR_ADVANCED ) );
registry.registerAll(
ComputerCraft.Blocks.turtleNormal.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "turtle_normal" ) ),
ComputerCraft.Blocks.turtleAdvanced.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "turtle_advanced" ) )
);
public static final RegistryObject<BlockWirelessModem> WIRELESS_MODEM_NORMAL = BLOCKS.register( "wireless_modem_normal",
() -> new BlockWirelessModem( properties(), ModTiles.WIRELESS_MODEM_NORMAL ) );
public static final RegistryObject<BlockWirelessModem> WIRELESS_MODEM_ADVANCED = BLOCKS.register( "wireless_modem_advanced",
() -> new BlockWirelessModem( properties(), ModTiles.WIRELESS_MODEM_ADVANCED ) );
// Peripherals
ComputerCraft.Blocks.speaker = new BlockSpeaker(
Block.Properties.create( Material.ROCK ).hardnessAndResistance( 2 )
);
ComputerCraft.Blocks.diskDrive = new BlockDiskDrive(
Block.Properties.create( Material.ROCK ).hardnessAndResistance( 2 )
);
ComputerCraft.Blocks.monitorNormal = new BlockMonitor(
Block.Properties.create( Material.ROCK ).hardnessAndResistance( 2 ),
TileMonitor.FACTORY_NORMAL
);
ComputerCraft.Blocks.monitorAdvanced = new BlockMonitor(
Block.Properties.create( Material.ROCK ).hardnessAndResistance( 2 ),
TileMonitor.FACTORY_ADVANCED
);
ComputerCraft.Blocks.printer = new BlockPrinter(
Block.Properties.create( Material.ROCK ).hardnessAndResistance( 2 )
);
ComputerCraft.Blocks.wirelessModemNormal = new BlockWirelessModem(
Block.Properties.create( Material.ROCK ).hardnessAndResistance( 2 ),
TileWirelessModem.FACTORY_NORMAL
);
ComputerCraft.Blocks.wirelessModemAdvanced = new BlockWirelessModem(
Block.Properties.create( Material.ROCK ).hardnessAndResistance( 2 ),
TileWirelessModem.FACTORY_ADVANCED
);
ComputerCraft.Blocks.wiredModemFull = new BlockWiredModemFull(
Block.Properties.create( Material.ROCK ).hardnessAndResistance( 1.5f )
);
ComputerCraft.Blocks.cable = new BlockCable(
Block.Properties.create( Material.ROCK ).hardnessAndResistance( 1.5f )
);
registry.registerAll(
ComputerCraft.Blocks.speaker.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "speaker" ) ),
ComputerCraft.Blocks.diskDrive.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "disk_drive" ) ),
ComputerCraft.Blocks.monitorNormal.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "monitor_normal" ) ),
ComputerCraft.Blocks.monitorAdvanced.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "monitor_advanced" ) ),
ComputerCraft.Blocks.printer.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "printer" ) ),
ComputerCraft.Blocks.wirelessModemNormal.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "wireless_modem_normal" ) ),
ComputerCraft.Blocks.wirelessModemAdvanced.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "wireless_modem_advanced" ) ),
ComputerCraft.Blocks.wiredModemFull.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "wired_modem_full" ) ),
ComputerCraft.Blocks.cable.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "cable" ) )
);
public static final RegistryObject<BlockWiredModemFull> WIRED_MODEM_FULL = BLOCKS.register( "wired_modem_full",
() -> new BlockWiredModemFull( modemProperties() ) );
public static final RegistryObject<BlockCable> CABLE = BLOCKS.register( "cable", () -> new BlockCable( modemProperties() ) );
}
@SubscribeEvent
public static void registerTileEntities( RegistryEvent.Register<TileEntityType<?>> event )
public static class ModTiles
{
IForgeRegistry<TileEntityType<?>> registry = event.getRegistry();
static final DeferredRegister<TileEntityType<?>> TILES = DeferredRegister.create( ForgeRegistries.TILE_ENTITIES, ComputerCraft.MOD_ID );
// Computers
registry.registerAll( TileComputer.FACTORY_NORMAL, TileComputer.FACTORY_ADVANCED, TileCommandComputer.FACTORY );
private static <T extends TileEntity> RegistryObject<TileEntityType<T>> ofBlock( RegistryObject<? extends Block> block, Function<TileEntityType<T>, T> factory )
{
return TILES.register( block.getId().getPath(), () -> FixedPointTileEntityType.create( block, factory ) );
}
// Turtles
registry.registerAll( TileTurtle.FACTORY_NORMAL, TileTurtle.FACTORY_ADVANCED );
public static final RegistryObject<TileEntityType<TileMonitor>> MONITOR_NORMAL =
ofBlock( ModBlocks.MONITOR_NORMAL, f -> new TileMonitor( f, false ) );
public static final RegistryObject<TileEntityType<TileMonitor>> MONITOR_ADVANCED =
ofBlock( ModBlocks.MONITOR_ADVANCED, f -> new TileMonitor( f, true ) );
// Peripherals
registry.registerAll(
TileSpeaker.FACTORY,
TileDiskDrive.FACTORY,
TileMonitor.FACTORY_NORMAL,
TileMonitor.FACTORY_ADVANCED,
TilePrinter.FACTORY,
TileWirelessModem.FACTORY_NORMAL,
TileWirelessModem.FACTORY_ADVANCED,
TileWiredModemFull.FACTORY,
TileCable.FACTORY
);
public static final RegistryObject<TileEntityType<TileComputer>> COMPUTER_NORMAL =
ofBlock( ModBlocks.COMPUTER_NORMAL, f -> new TileComputer( ComputerFamily.NORMAL, f ) );
public static final RegistryObject<TileEntityType<TileComputer>> COMPUTER_ADVANCED =
ofBlock( ModBlocks.COMPUTER_ADVANCED, f -> new TileComputer( ComputerFamily.ADVANCED, f ) );
public static final RegistryObject<TileEntityType<TileCommandComputer>> COMPUTER_COMMAND =
ofBlock( ModBlocks.COMPUTER_COMMAND, f -> new TileCommandComputer( ComputerFamily.COMMAND, f ) );
public static final RegistryObject<TileEntityType<TileTurtle>> TURTLE_NORMAL =
ofBlock( ModBlocks.TURTLE_NORMAL, f -> new TileTurtle( f, ComputerFamily.NORMAL ) );
public static final RegistryObject<TileEntityType<TileTurtle>> TURTLE_ADVANCED =
ofBlock( ModBlocks.TURTLE_ADVANCED, f -> new TileTurtle( f, ComputerFamily.ADVANCED ) );
public static final RegistryObject<TileEntityType<TileSpeaker>> SPEAKER = ofBlock( ModBlocks.SPEAKER, TileSpeaker::new );
public static final RegistryObject<TileEntityType<TileDiskDrive>> DISK_DRIVE = ofBlock( ModBlocks.DISK_DRIVE, TileDiskDrive::new );
public static final RegistryObject<TileEntityType<TilePrinter>> PRINTER = ofBlock( ModBlocks.PRINTER, TilePrinter::new );
public static final RegistryObject<TileEntityType<TileWiredModemFull>> WIRED_MODEM_FULL = ofBlock( ModBlocks.WIRED_MODEM_FULL, TileWiredModemFull::new );
public static final RegistryObject<TileEntityType<TileCable>> CABLE = ofBlock( ModBlocks.CABLE, TileCable::new );
public static final RegistryObject<TileEntityType<TileWirelessModem>> WIRELESS_MODEM_NORMAL =
ofBlock( ModBlocks.WIRELESS_MODEM_NORMAL, f -> new TileWirelessModem( f, false ) );
public static final RegistryObject<TileEntityType<TileWirelessModem>> WIRELESS_MODEM_ADVANCED =
ofBlock( ModBlocks.WIRELESS_MODEM_ADVANCED, f -> new TileWirelessModem( f, true ) );
}
private static <T extends BlockItem> T setupItemBlock( T item )
public static final class ModItems
{
item.setRegistryName( item.getBlock().getRegistryName() );
return item;
}
static final DeferredRegister<Item> ITEMS = DeferredRegister.create( ForgeRegistries.ITEMS, ComputerCraft.MOD_ID );
private static Item.Properties defaultItem()
{
return new Item.Properties().group( mainItemGroup );
private static Item.Properties properties()
{
return new Item.Properties().group( mainItemGroup );
}
private static <B extends Block, I extends Item> RegistryObject<I> ofBlock( RegistryObject<B> parent, BiFunction<B, Item.Properties, I> supplier )
{
return ITEMS.register( parent.getId().getPath(), () -> supplier.apply( parent.get(), properties() ) );
}
public static final RegistryObject<ItemComputer> COMPUTER_NORMAL = ofBlock( ModBlocks.COMPUTER_NORMAL, ItemComputer::new );
public static final RegistryObject<ItemComputer> COMPUTER_ADVANCED = ofBlock( ModBlocks.COMPUTER_ADVANCED, ItemComputer::new );
public static final RegistryObject<ItemComputer> COMPUTER_COMMAND = ofBlock( ModBlocks.COMPUTER_COMMAND, ItemComputer::new );
public static final RegistryObject<ItemPocketComputer> POCKET_COMPUTER_NORMAL = ITEMS.register( "pocket_computer_normal",
() -> new ItemPocketComputer( properties().maxStackSize( 1 ), ComputerFamily.NORMAL ) );
public static final RegistryObject<ItemPocketComputer> POCKET_COMPUTER_ADVANCED = ITEMS.register( "pocket_computer_advanced",
() -> new ItemPocketComputer( properties().maxStackSize( 1 ), ComputerFamily.ADVANCED ) );
public static final RegistryObject<ItemTurtle> TURTLE_NORMAL = ofBlock( ModBlocks.TURTLE_NORMAL, ItemTurtle::new );
public static final RegistryObject<ItemTurtle> TURTLE_ADVANCED = ofBlock( ModBlocks.TURTLE_ADVANCED, ItemTurtle::new );
public static final RegistryObject<ItemDisk> DISK =
ITEMS.register( "disk", () -> new ItemDisk( properties().maxStackSize( 1 ) ) );
public static final RegistryObject<ItemTreasureDisk> TREASURE_DISK =
ITEMS.register( "treasure_disk", () -> new ItemTreasureDisk( properties().maxStackSize( 1 ) ) );
public static final RegistryObject<ItemPrintout> PRINTED_PAGE = ITEMS.register( "printed_page",
() -> new ItemPrintout( properties().maxStackSize( 1 ), ItemPrintout.Type.PAGE ) );
public static final RegistryObject<ItemPrintout> PRINTED_PAGES = ITEMS.register( "printed_pages",
() -> new ItemPrintout( properties().maxStackSize( 1 ), ItemPrintout.Type.PAGES ) );
public static final RegistryObject<ItemPrintout> PRINTED_BOOK = ITEMS.register( "printed_book",
() -> new ItemPrintout( properties().maxStackSize( 1 ), ItemPrintout.Type.BOOK ) );
public static final RegistryObject<BlockItem> SPEAKER = ofBlock( ModBlocks.SPEAKER, BlockItem::new );
public static final RegistryObject<BlockItem> DISK_DRIVE = ofBlock( ModBlocks.DISK_DRIVE, BlockItem::new );
public static final RegistryObject<BlockItem> PRINTER = ofBlock( ModBlocks.PRINTER, BlockItem::new );
public static final RegistryObject<BlockItem> MONITOR_NORMAL = ofBlock( ModBlocks.MONITOR_NORMAL, BlockItem::new );
public static final RegistryObject<BlockItem> MONITOR_ADVANCED = ofBlock( ModBlocks.MONITOR_ADVANCED, BlockItem::new );
public static final RegistryObject<BlockItem> WIRELESS_MODEM_NORMAL = ofBlock( ModBlocks.WIRELESS_MODEM_NORMAL, BlockItem::new );
public static final RegistryObject<BlockItem> WIRELESS_MODEM_ADVANCED = ofBlock( ModBlocks.WIRELESS_MODEM_ADVANCED, BlockItem::new );
public static final RegistryObject<BlockItem> WIRED_MODEM_FULL = ofBlock( ModBlocks.WIRED_MODEM_FULL, BlockItem::new );
public static final RegistryObject<ItemBlockCable.Cable> CABLE = ITEMS.register( "cable",
() -> new ItemBlockCable.Cable( ModBlocks.CABLE.get(), properties() ) );
public static final RegistryObject<ItemBlockCable.WiredModem> WIRED_MODEM = ITEMS.register( "wired_modem",
() -> new ItemBlockCable.WiredModem( ModBlocks.CABLE.get(), properties() ) );
}
@SubscribeEvent
public static void registerItems( RegistryEvent.Register<Item> event )
{
IForgeRegistry<Item> registry = event.getRegistry();
// Computer
ComputerCraft.Items.computerNormal = new ItemComputer( ComputerCraft.Blocks.computerNormal, defaultItem() );
ComputerCraft.Items.computerAdvanced = new ItemComputer( ComputerCraft.Blocks.computerAdvanced, defaultItem() );
ComputerCraft.Items.computerCommand = new ItemComputer( ComputerCraft.Blocks.computerCommand, defaultItem() );
registry.registerAll(
setupItemBlock( ComputerCraft.Items.computerNormal ),
setupItemBlock( ComputerCraft.Items.computerAdvanced ),
setupItemBlock( ComputerCraft.Items.computerCommand )
);
// Turtle
ComputerCraft.Items.turtleNormal = new ItemTurtle( ComputerCraft.Blocks.turtleNormal, defaultItem() );
ComputerCraft.Items.turtleAdvanced = new ItemTurtle( ComputerCraft.Blocks.turtleAdvanced, defaultItem() );
registry.registerAll(
setupItemBlock( ComputerCraft.Items.turtleNormal ),
setupItemBlock( ComputerCraft.Items.turtleAdvanced )
);
// Pocket computer
ComputerCraft.Items.pocketComputerNormal = new ItemPocketComputer( defaultItem().maxStackSize( 1 ), ComputerFamily.NORMAL );
ComputerCraft.Items.pocketComputerAdvanced = new ItemPocketComputer( defaultItem().maxStackSize( 1 ), ComputerFamily.ADVANCED );
registry.registerAll(
ComputerCraft.Items.pocketComputerNormal.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "pocket_computer_normal" ) ),
ComputerCraft.Items.pocketComputerAdvanced.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "pocket_computer_advanced" ) )
);
// Floppy disk
ComputerCraft.Items.disk = new ItemDisk( defaultItem().maxStackSize( 1 ) );
ComputerCraft.Items.treasureDisk = new ItemTreasureDisk( defaultItem().maxStackSize( 1 ) );
registry.registerAll(
ComputerCraft.Items.disk.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "disk" ) ),
ComputerCraft.Items.treasureDisk.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "treasure_disk" ) )
);
// Printouts
ComputerCraft.Items.printedPage = new ItemPrintout( defaultItem().maxStackSize( 1 ), ItemPrintout.Type.PAGE );
ComputerCraft.Items.printedPages = new ItemPrintout( defaultItem().maxStackSize( 1 ), ItemPrintout.Type.PAGES );
ComputerCraft.Items.printedBook = new ItemPrintout( defaultItem().maxStackSize( 1 ), ItemPrintout.Type.BOOK );
registry.registerAll(
ComputerCraft.Items.printedPage.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "printed_page" ) ),
ComputerCraft.Items.printedPages.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "printed_pages" ) ),
ComputerCraft.Items.printedBook.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "printed_book" ) )
);
// Peripherals
registry.registerAll(
setupItemBlock( new BlockItem( ComputerCraft.Blocks.speaker, defaultItem() ) ),
setupItemBlock( new BlockItem( ComputerCraft.Blocks.diskDrive, defaultItem() ) ),
setupItemBlock( new BlockItem( ComputerCraft.Blocks.printer, defaultItem() ) ),
setupItemBlock( new BlockItem( ComputerCraft.Blocks.monitorNormal, defaultItem() ) ),
setupItemBlock( new BlockItem( ComputerCraft.Blocks.monitorAdvanced, defaultItem() ) ),
setupItemBlock( new BlockItem( ComputerCraft.Blocks.wirelessModemNormal, defaultItem() ) ),
setupItemBlock( new BlockItem( ComputerCraft.Blocks.wirelessModemAdvanced, defaultItem() ) ),
setupItemBlock( new BlockItem( ComputerCraft.Blocks.wiredModemFull, defaultItem() ) )
);
ComputerCraft.Items.cable = new ItemBlockCable.Cable( ComputerCraft.Blocks.cable, defaultItem() );
ComputerCraft.Items.wiredModem = new ItemBlockCable.WiredModem( ComputerCraft.Blocks.cable, defaultItem() );
registry.registerAll(
ComputerCraft.Items.cable.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "cable" ) ),
ComputerCraft.Items.wiredModem.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "wired_modem" ) )
);
registerTurtleUpgrades();
registerPocketUpgrades();
}
@@ -303,7 +259,7 @@ public final class Registry
ComputerCraft.TurtleUpgrades.diamondSword = new TurtleSword( new ResourceLocation( "minecraft", "diamond_sword" ), Items.DIAMOND_SWORD );
ComputerCraftAPI.registerTurtleUpgrade( ComputerCraft.TurtleUpgrades.diamondSword );
ComputerCraft.TurtleUpgrades.diamondShovel = new TurtleShovel( new ResourceLocation( "minecraft", "diamond_shovel" ), net.minecraft.item.Items.DIAMOND_SHOVEL );
ComputerCraft.TurtleUpgrades.diamondShovel = new TurtleShovel( new ResourceLocation( "minecraft", "diamond_shovel" ), Items.DIAMOND_SHOVEL );
ComputerCraftAPI.registerTurtleUpgrade( ComputerCraft.TurtleUpgrades.diamondShovel );
ComputerCraft.TurtleUpgrades.diamondPickaxe = new TurtleTool( new ResourceLocation( "minecraft", "diamond_pickaxe" ), Items.DIAMOND_PICKAXE );
@@ -323,32 +279,47 @@ public final class Registry
ComputerCraftAPI.registerPocketUpgrade( ComputerCraft.PocketUpgrades.speaker = new PocketSpeaker() );
}
@SubscribeEvent
public static void registerEntities( RegistryEvent.Register<EntityType<?>> registry )
public static class ModEntities
{
registry.getRegistry().register( TurtlePlayer.TYPE.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "turtle_player" ) ) );
static final DeferredRegister<EntityType<?>> ENTITIES = DeferredRegister.create( ForgeRegistries.ENTITIES, ComputerCraft.MOD_ID );
public static final RegistryObject<EntityType<TurtlePlayer>> TURTLE_PLAYER = ENTITIES.register( "turtle_player", () ->
EntityType.Builder.<TurtlePlayer>create( EntityClassification.MISC )
.disableSerialization()
.disableSummoning()
.size( 0, 0 )
.build( ComputerCraft.MOD_ID + ":turtle_player" ) );
}
public static class ModContainers
{
static final DeferredRegister<ContainerType<?>> CONTAINERS = DeferredRegister.create( ForgeRegistries.CONTAINERS, ComputerCraft.MOD_ID );
public static final RegistryObject<ContainerType<ContainerComputer>> COMPUTER = CONTAINERS.register( "computer",
() -> ContainerData.toType( ComputerContainerData::new, ContainerComputer::new ) );
public static final RegistryObject<ContainerType<ContainerPocketComputer>> POCKET_COMPUTER = CONTAINERS.register( "pocket_computer",
() -> ContainerData.toType( ComputerContainerData::new, ContainerPocketComputer::new ) );
public static final RegistryObject<ContainerType<ContainerTurtle>> TURTLE = CONTAINERS.register( "turtle",
() -> ContainerData.toType( ComputerContainerData::new, ContainerTurtle::new ) );
public static final RegistryObject<ContainerType<ContainerDiskDrive>> DISK_DRIVE = CONTAINERS.register( "disk_drive",
() -> new ContainerType<>( ContainerDiskDrive::new ) );
public static final RegistryObject<ContainerType<ContainerPrinter>> PRINTER = CONTAINERS.register( "printer",
() -> new ContainerType<>( ContainerPrinter::new ) );
public static final RegistryObject<ContainerType<ContainerHeldItem>> PRINTOUT = CONTAINERS.register( "printout",
() -> ContainerData.toType( HeldItemContainerData::new, ContainerHeldItem::createPrintout ) );
public static final RegistryObject<ContainerType<ContainerViewComputer>> VIEW_COMPUTER = CONTAINERS.register( "view_computer",
() -> ContainerData.toType( ViewComputerContainerData::new, ContainerViewComputer::new ) );
}
@SubscribeEvent
public static void registerContainers( RegistryEvent.Register<ContainerType<?>> event )
public static void registerRecipeSerializers( RegistryEvent.Register<IRecipeSerializer<?>> event )
{
event.getRegistry().registerAll(
ContainerComputer.TYPE.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "computer" ) ),
ContainerPocketComputer.TYPE.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "pocket_computer" ) ),
ContainerTurtle.TYPE.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "turtle" ) ),
ContainerDiskDrive.TYPE.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "disk_drive" ) ),
ContainerPrinter.TYPE.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "printer" ) ),
ContainerHeldItem.PRINTOUT_TYPE.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "printout" ) ),
ContainerViewComputer.TYPE.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "view_computer" ) )
);
}
@SubscribeEvent
public static void regsterRecipeSerializers( RegistryEvent.Register<IRecipeSerializer<?>> event )
{
event.getRegistry().registerAll(
ColourableRecipe.SERIALIZER.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "colour" ) ),
ComputerUpgradeRecipe.SERIALIZER.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "computer_upgrade" ) ),
@@ -361,4 +332,14 @@ public final class Registry
ImpostorRecipe.SERIALIZER.setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "impostor_shaped" ) )
);
}
public static void setup()
{
IEventBus bus = FMLJavaModLoadingContext.get().getModEventBus();
ModBlocks.BLOCKS.register( bus );
ModTiles.TILES.register( bus );
ModItems.ITEMS.register( bus );
ModEntities.ENTITIES.register( bus );
ModContainers.CONTAINERS.register( bus );
}
}

View File

@@ -11,6 +11,7 @@ import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.server.ServerWorld;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
@@ -20,13 +21,12 @@ public final class TurtlePermissions
public static boolean isBlockEnterable( World world, BlockPos pos, PlayerEntity player )
{
MinecraftServer server = world.getServer();
return server == null || world.isRemote || !server.isBlockProtected( world, pos, player );
return server == null || world.isRemote || (world instanceof ServerWorld && !server.isBlockProtected( (ServerWorld) world, pos, player ));
}
public static boolean isBlockEditable( World world, BlockPos pos, PlayerEntity player )
{
MinecraftServer server = world.getServer();
return server == null || world.isRemote || !server.isBlockProtected( world, pos, player );
return isBlockEnterable( world, pos, player );
}
@SubscribeEvent

View File

@@ -30,6 +30,7 @@ import net.minecraft.inventory.container.Container;
import net.minecraft.inventory.container.INamedContainerProvider;
import net.minecraft.network.play.server.SPlayerPositionLookPacket;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.IFormattableTextComponent;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.util.text.TranslationTextComponent;
@@ -283,16 +284,16 @@ public final class CommandComputerCraft
private static ITextComponent linkComputer( CommandSource source, ServerComputer serverComputer, int computerId )
{
ITextComponent out = new StringTextComponent( "" );
IFormattableTextComponent out = new StringTextComponent( "" );
// Append the computer instance
if( serverComputer == null )
{
out.appendSibling( text( "?" ) );
out.append( text( "?" ) );
}
else
{
out.appendSibling( link(
out.append( link(
text( Integer.toString( serverComputer.getInstanceID() ) ),
"/computercraft dump " + serverComputer.getInstanceID(),
translate( "commands.computercraft.dump.action" )
@@ -300,20 +301,20 @@ public final class CommandComputerCraft
}
// And ID
out.appendText( " (id " + computerId + ")" );
out.appendString( " (id " + computerId + ")" );
// And, if we're a player, some useful links
if( serverComputer != null && UserLevel.OP.test( source ) && isPlayer( source ) )
{
out
.appendText( " " )
.appendSibling( link(
.appendString( " " )
.append( link(
text( "\u261b" ),
"/computercraft tp " + serverComputer.getInstanceID(),
translate( "commands.computercraft.tp.action" )
) )
.appendText( " " )
.appendSibling( link(
.appendString( " " )
.append( link(
text( "\u20e2" ),
"/computercraft view " + serverComputer.getInstanceID(),
translate( "commands.computercraft.view.action" )

View File

@@ -12,6 +12,7 @@ import net.minecraft.client.Minecraft;
import net.minecraft.command.CommandSource;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.util.text.Style;
import net.minecraft.util.text.TranslationTextComponent;
import net.minecraft.util.text.event.ClickEvent;
import net.minecraft.util.text.event.HoverEvent;
@@ -57,10 +58,8 @@ public final class CommandCopy
public static ITextComponent createCopyText( String text )
{
StringTextComponent name = new StringTextComponent( text );
name.getStyle()
return new StringTextComponent( text ).mergeStyle( Style.EMPTY
.setClickEvent( new ClickEvent( ClickEvent.Action.RUN_COMMAND, PREFIX + text ) )
.setHoverEvent( new HoverEvent( HoverEvent.Action.SHOW_TEXT, new TranslationTextComponent( "gui.computercraft.tooltip.copy" ) ) );
return name;
.setHoverEvent( new HoverEvent( HoverEvent.Action.SHOW_TEXT, new TranslationTextComponent( "gui.computercraft.tooltip.copy" ) ) ) );
}
}

View File

@@ -13,6 +13,7 @@ import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.tree.CommandNode;
import com.mojang.brigadier.tree.LiteralCommandNode;
import net.minecraft.command.CommandSource;
import net.minecraft.util.text.IFormattableTextComponent;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.util.text.TextFormatting;
@@ -173,12 +174,12 @@ public final class HelpingArgumentBuilder extends LiteralArgumentBuilder<Command
temp.addChild( node );
String usage = dispatcher.getSmartUsage( temp, context.getSource() ).get( node ).substring( node.getName().length() );
ITextComponent output = new StringTextComponent( "" )
.appendSibling( coloured( "/" + command + usage, HEADER ) )
.appendText( " " )
.appendSibling( coloured( translate( "commands." + id + ".synopsis" ), SYNOPSIS ) )
.appendText( "\n" )
.appendSibling( translate( "commands." + id + ".desc" ) );
IFormattableTextComponent output = new StringTextComponent( "" )
.append( coloured( "/" + command + usage, HEADER ) )
.appendString( " " )
.append( coloured( translate( "commands." + id + ".synopsis" ), SYNOPSIS ) )
.appendString( "\n" )
.append( translate( "commands." + id + ".desc" ) );
for( CommandNode<CommandSource> child : node.getChildren() )
{
@@ -187,16 +188,16 @@ public final class HelpingArgumentBuilder extends LiteralArgumentBuilder<Command
continue;
}
output.appendText( "\n" );
output.appendString( "\n" );
ITextComponent component = coloured( child.getName(), NAME );
IFormattableTextComponent component = coloured( child.getName(), NAME );
component.getStyle().setClickEvent( new ClickEvent(
ClickEvent.Action.SUGGEST_COMMAND,
"/" + command + " " + child.getName()
) );
output.appendSibling( component );
output.append( component );
output.appendText( " - " ).appendSibling( translate( "commands." + id + "." + child.getName() + ".synopsis" ) );
output.appendString( " - " ).append( translate( "commands." + id + "." + child.getName() + ".synopsis" ) );
}
return output;

View File

@@ -19,69 +19,67 @@ public final class ChatHelpers
private ChatHelpers() {}
public static ITextComponent coloured( String text, TextFormatting colour )
public static IFormattableTextComponent coloured( String text, TextFormatting colour )
{
ITextComponent component = new StringTextComponent( text == null ? "" : text );
component.getStyle().setColor( colour );
return new StringTextComponent( text == null ? "" : text ).mergeStyle( colour );
}
public static <T extends IFormattableTextComponent> T coloured( T component, TextFormatting colour )
{
component.mergeStyle( colour );
return component;
}
public static <T extends ITextComponent> T coloured( T component, TextFormatting colour )
{
component.getStyle().setColor( colour );
return component;
}
public static ITextComponent text( String text )
public static IFormattableTextComponent text( String text )
{
return new StringTextComponent( text == null ? "" : text );
}
public static ITextComponent translate( String text )
public static IFormattableTextComponent translate( String text )
{
return new TranslationTextComponent( text == null ? "" : text );
}
public static ITextComponent translate( String text, Object... args )
public static IFormattableTextComponent translate( String text, Object... args )
{
return new TranslationTextComponent( text == null ? "" : text, args );
}
public static ITextComponent list( ITextComponent... children )
public static IFormattableTextComponent list( ITextComponent... children )
{
ITextComponent component = new StringTextComponent( "" );
IFormattableTextComponent component = new StringTextComponent( "" );
for( ITextComponent child : children )
{
component.appendSibling( child );
component.append( child );
}
return component;
}
public static ITextComponent position( BlockPos pos )
public static IFormattableTextComponent position( BlockPos pos )
{
if( pos == null ) return translate( "commands.computercraft.generic.no_position" );
return translate( "commands.computercraft.generic.position", pos.getX(), pos.getY(), pos.getZ() );
}
public static ITextComponent bool( boolean value )
public static IFormattableTextComponent bool( boolean value )
{
return value
? coloured( translate( "commands.computercraft.generic.yes" ), TextFormatting.GREEN )
: coloured( translate( "commands.computercraft.generic.no" ), TextFormatting.RED );
}
public static ITextComponent link( ITextComponent component, String command, ITextComponent toolTip )
public static IFormattableTextComponent link( IFormattableTextComponent component, String command, ITextComponent toolTip )
{
Style style = component.getStyle();
if( style.getColor() == null ) style.setColor( TextFormatting.YELLOW );
style.setClickEvent( new ClickEvent( ClickEvent.Action.RUN_COMMAND, command ) );
style.setHoverEvent( new HoverEvent( HoverEvent.Action.SHOW_TEXT, toolTip ) );
if( style.getColor() == null ) style = style.setFormatting( TextFormatting.YELLOW );
style = style.setClickEvent( new ClickEvent( ClickEvent.Action.RUN_COMMAND, command ) );
style = style.setHoverEvent( new HoverEvent( HoverEvent.Action.SHOW_TEXT, toolTip ) );
return component;
return component.setStyle( style );
}
public static ITextComponent header( String text )
public static IFormattableTextComponent header( String text )
{
return coloured( text, HEADER );
}

View File

@@ -79,12 +79,12 @@ public interface TableFormatter
StringTextComponent line = new StringTextComponent( "" );
for( int i = 0; i < columns - 1; i++ )
{
line.appendSibling( headers[i] );
line.append( headers[i] );
ITextComponent padding = getPadding( headers[i], maxWidths[i] );
if( padding != null ) line.appendSibling( padding );
line.appendSibling( SEPARATOR );
if( padding != null ) line.append( padding );
line.append( SEPARATOR );
}
line.appendSibling( headers[columns - 1] );
line.append( headers[columns - 1] );
writeLine( rowId++, line );
@@ -100,12 +100,12 @@ public interface TableFormatter
StringTextComponent line = new StringTextComponent( "" );
for( int i = 0; i < columns - 1; i++ )
{
line.appendSibling( row[i] );
line.append( row[i] );
ITextComponent padding = getPadding( row[i], maxWidths[i] );
if( padding != null ) line.appendSibling( padding );
line.appendSibling( SEPARATOR );
if( padding != null ) line.append( padding );
line.append( SEPARATOR );
}
line.appendSibling( row[columns - 1] );
line.append( row[columns - 1] );
writeLine( rowId++, line );
}

View File

@@ -5,7 +5,6 @@
*/
package dan200.computercraft.shared.common;
import dan200.computercraft.shared.util.NamedTileEntityType;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
@@ -19,6 +18,7 @@ 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;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -26,13 +26,12 @@ import java.util.Random;
public abstract class BlockGeneric extends Block
{
private final TileEntityType<? extends TileGeneric> type;
private final RegistryObject<? extends TileEntityType<? extends TileGeneric>> type;
public BlockGeneric( Properties settings, NamedTileEntityType<? extends TileGeneric> type )
public BlockGeneric( Properties settings, RegistryObject<? extends TileEntityType<? extends TileGeneric>> type )
{
super( settings );
this.type = type;
type.setBlock( this );
}
@Override
@@ -89,7 +88,7 @@ public abstract class BlockGeneric extends Block
@Override
public TileEntity createTileEntity( @Nonnull BlockState state, @Nonnull IBlockReader world )
{
return type.create();
return type.get().create();
}
@Override

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