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

Compare commits

...

516 Commits

Author SHA1 Message Date
Merith-TK
1a52275dcb release 1.96.0 2021-06-04 16:09:43 -07:00
Merith
2fc2cf2e29 Merge pull request #49 from Toad-Dev/fabric-fix-48
Fix crash while playing a music disk in a drive on server.
2021-06-04 14:29:21 -07:00
ToadDev
80c2fc68aa Fix crash playing a music disc from drive on server.
#48
2021-06-03 21:54:28 -07:00
ToadDev
7c0664b9f2 Fix mixin from latest PR getting left behind in refactor.
I refactored the mixin package to be within a fabric package so other
fabric specific code could be kept nearby. But a mixin from a recent PR
got left behind in the merge. Github's empty merge conflict might have
been about this.
2021-06-03 21:32:37 -07:00
Merith
4d1a950fbf Merge pull request #42 from Toad-Dev/merith-buffer-fix
Fix: Monitor render buffers not being released properly.
2021-06-03 15:28:23 -07:00
ToadDev
135a3f56a5 Refactor: Begin consolidating fabric only classes.
Made a top-level fabric package so mixins and their ancillary classes
can be grouped together. Also removed a stub duck interface that got
left behind somewhere along the line (MixedFirstPersonRenderer).
2021-06-03 13:48:34 -07:00
ToadDev
1f117b7c47 Fix: Inform block entities when chunk is unloaded.
Forge's ITileEntity interface adds a onChunkUnloaded handler method into
block entities. The fabric port doesn't have a re-implementation of this
feature, which meant TileMonitors weren't releasing their buffers when
unloaded. This commit adds that handler method back into TileGeneric,
which all CC block entities inherit from. Handler logic for the four
block entities that use this feature were copied over from the forge
repo.
2021-06-03 13:48:34 -07:00
ToadDev
c820e051b3 Fix: Release monitor buffers on *client* thread
These buffers were being released on the server thread, causing the
logical server in a single player session to crash just before shutting
down. It seems the crash happened late enough to not cause world
corruption issues, and so went unnoticed. It was however causing a
memory leak when quitting/rejoining worlds, and it left the save file
lock in limbo.
2021-06-03 13:48:34 -07:00
Merith
01d7aaf062 Merge pull request #38 from Jummit/port-10
Port all recent commits
2021-06-03 07:58:58 -07:00
Merith-TK
1e75e4ff6e update issue templates, remove travis.yml
issue templates needed a revamp,
2021-06-03 06:45:32 -07:00
Merith
f967a70121 Merge pull request #45 from hugeblank/disk-use
Fix Disk Drive & Disk Interaction
2021-06-02 19:24:25 -07:00
Merith
ac5150a664 Merge pull request #46 from hugeblank/implement-details
Properly implement turtle.getItemDetails()
2021-06-02 18:03:32 -07:00
hugeblank
0318e62524 Implement tag functionality 2021-06-02 17:58:04 -07:00
hugeblank
ca69d755e6 Re-implement turtle.getItemDetails() detailed mode
Incomplete - Missing item "tags", otherwise fully functional.

- Fixes #41
2021-06-02 17:29:06 -07:00
Merith
3ba7acc414 Merge pull request #43 from Toad-Dev/merith-chat-fix
Fix: Display peripheral chat messages in multiplayer and improve /computercraft command.
2021-06-02 15:59:09 -07:00
hugeblank
4c27eea73b Fix Disk Drive & Disk Interaction
Inject Special case into ServerPlayerInteractionManager that handles disks being sneak + right clicked onto disk drives.

Fixes  #12
2021-06-02 14:23:19 -07:00
ToadDev
225a64dd6b Send terminal state with /computercraft view 2021-05-31 16:40:09 -07:00
Jonathan Coates
1831e81dd4 Add button to view computer's folder
Implementation is a little awkward, as we can't send OPEN_FILE links
from the server, so we ensure the client runs a
/computercraft open-computer ID command instead. We then intercept this
on the client side and use that to open the folder.
2021-05-30 23:59:39 -07:00
Merith
a4dd6c24e5 Update README.md 2021-05-29 07:17:19 -07:00
Jonathan Coates
936742895b Bump version to 1.94.0 2021-05-25 22:16:57 +02:00
Jonathan Coates
b5d1e618b9 Set stack size when crafting coloured items
Fixes #793
2021-05-25 22:16:57 +02:00
JackMacWindows
10aa6c5297 Add the ability to call cc.expect directly 2021-05-25 22:16:57 +02:00
Jonathan Coates
010ebacd1a Fix mount suggestion always being printed out 2021-05-25 22:16:57 +02:00
Lupus590
9e002beed7 Add cc.expect.range (#790) 2021-05-25 22:16:57 +02:00
Jonathan Coates
6029defb20 Use a separate region for the bottom pocket computer border
This is definitely not a good solution, but it's probably the best we
can do right now given resizable computers are a thing.

Fixes #775, closes #776
2021-05-25 22:16:57 +02:00
Jonathan Coates
c16aa5f247 Fix build failures
- Add license headers. Also check these during pre-commit.
 - Fix javadoc issue.
2021-05-25 22:16:57 +02:00
Jummit
8d27bdca7b Expose GenericSource to the public API
- Remove the service provider code and require people to explicitly
   register these. This is definitely more ugly, but easier than people
   pulling in AutoService or similar!
 - Add an API for registering capabilities.
 - Expand the doc comments a little. Not sure how useful they'll be, but
   let's see!

There's still so much work to be done on this, but it's a "good enough"
first step.
2021-05-25 22:16:57 +02:00
Jonathan Coates
41aa8fa163 Add example to turtle.inspect
A pretty common but non-trivial API, so worth having something. Even if
not perfect.
2021-05-25 22:16:57 +02:00
Jummit
e40fb67b50 Add inventory.getItemLimit
Closes #781
2021-05-25 22:16:57 +02:00
Jonathan Coates
96d46ffd2c Bump Cobalt version 2021-05-25 22:16:57 +02:00
Jonathan Coates
652b7ebba6 Use lightGrey for folders on normal computers
This way we still get some differences between files and folders on
normal computers. I did try with just green, but I think the contrast is
too low.

Closes #656
2021-05-25 22:16:57 +02:00
Jonathan Coates
f0d7a1165d Don't close file handles from ResourceMounts
Unlike short handles, we don't read these immediately, and so we can't
close it right away. Otherwise the file is considered empty!

Fixes SquidDev-CC/treasure-programs#1
2021-05-25 22:16:57 +02:00
Euric
4a20eea852 Defer monitor tile update when placed by another TE 2021-05-25 22:16:57 +02:00
Jonathan Coates
ccdd2bf477 Add some examples to inventory methods
Closes #761. It's not perfect, but it's a little better. Maybe??
2021-05-25 22:16:57 +02:00
Jonathan Coates
8d8f41a50b Simplify our overrides of load/loadstring
- Remove auto-prefixing of load/loadstring
 - Use Cobalt's normal load implementation, with a simple hook to
   set _ENV on the environment.
2021-05-25 22:16:57 +02:00
Jonathan Coates
72c78db28b Correctly handle sparse arrays in cc.pretty
This also swaps the order we display mixed array/maps in, so that the
array part comes first. I think this is more sensible.

Closes #777
2021-05-25 22:16:57 +02:00
Merith-TK
bf8a992273 update readme with tasks to be done 2021-05-25 12:24:50 -07:00
Merith
9c214fcd8a Merge pull request #40 from Jummit/remove-test
Remove the Java and Lua test suites
2021-05-25 12:08:48 -07:00
Merith
082cc9d2d8 Merge pull request #39 from o-iM-nI/readme
Merge 3prm3 Readme into repo
2021-05-25 12:07:23 -07:00
Jummit
bff2e81713 remove partial java and lua test suites 2021-05-25 18:17:44 +02:00
Merith
63aa3d8877 add known issue "file not found" 2021-05-24 11:15:48 -07:00
ƐqɿmƐ
74c5d7e719 Readme update
readme sourced from https://github.com/3prm3/cc-restitched
2021-05-23 09:06:34 -07:00
Merith-TK
78a685c2cb Fix Github Actions
Make github actions pull submodules
2021-05-16 14:01:28 -07:00
Merith
a475f55b9c Merge pull request #10 from Toad-Dev/fabric-merith
Bugfixes
2021-05-16 13:00:47 -07:00
David Queneau
9353ded2d5 Update readme to reflect bugfix. 2021-05-16 12:54:23 -07:00
Merith
d197268e53 Merge pull request #32 from Jummit/remove-docs
Remove docs folder
2021-05-16 11:19:02 -07:00
David Queneau
9648265056 Fix github actions 2021-05-16 11:16:01 -07:00
David Queneau
264dbc570f Fixed turtle tool upgrades not rendering in GUI. 2021-05-16 11:16:01 -07:00
David Queneau
e4ad8bc117 Fixed turtle ability to feed/breed passive mobs. 2021-05-16 11:16:01 -07:00
David Queneau
1b31972092 Fixed turtle ability to place signs with text. 2021-05-16 11:16:01 -07:00
David Queneau
6cd9fa9fb2 Fixed turtle bone meal usage 2021-05-16 11:16:01 -07:00
David Queneau
d10f297ca0 Turtles handle double chest inventories correctly. Cleaned up generic inventory code. 2021-05-16 11:16:01 -07:00
Merith-TK
9ae5636d41 update readme, add overhaul resourcepack as submodule 2021-05-16 11:12:12 -07:00
Jummit
a60daf78cf remove docs folder 2021-05-16 19:39:57 +02:00
Merith
76e0507c3b Merge pull request #31 from Jummit/new-textures
Update the textures to fit Jappa's style
2021-05-16 09:58:11 -07:00
Jummit
d8e2fab2b1 Update the textures and add an optional programmer art texturepack 2021-05-16 18:51:40 +02:00
Merith
5c5e510075 Merge pull request #24 from Toad-Dev/merith-1.16.5-pr
Merith 1.16.5 pr
2021-05-16 09:44:21 -07:00
Merith
5a309258af Merge branch 'fabric' into merith-1.16.5-pr 2021-05-16 09:42:11 -07:00
Merith
b0782ec38b Merge pull request #29 from Jummit/port-9
Brings us to CC:T 8494ba8ce2 so... who is gonna complain?
2021-05-16 09:21:31 -07:00
Jonathan Coates
46846a4fde Improve UX when a resource mount cannot be found
- Add a full example of the docs. Hopefully is a little more explicit.
 - Print a warning when the mount is empty.

Closes #762
2021-05-16 14:25:09 +02:00
Jonathan Coates
d955443b21 Add citation to cc.pretty
ust to look extra pretentious.
2021-05-16 14:18:48 +02:00
Jonathan Coates
57e6c49844 Make the peripheral API examples a little clearer 2021-05-16 14:18:43 +02:00
Jonathan Coates
66dbab7a6b "Finish" documentation for several modules
- Add remaining docs for the turtle API
 - Add documentation for the fluid storage peripheral.
 - Enforce undocumented warning for most modules (only io and window
   remaining).

"Finish" in quotes, because these are clearly a long way from perfect.
I'm bad at writing docs, OK!
2021-05-16 14:17:57 +02:00
lily
558976e4ca Fixed sortCoords for draw functions (#749) 2021-05-16 14:17:01 +02:00
Jonathan Coates
3a7470a108 Add documentation for io.setvbuf
Fixes #746.

Love how "good first issue" guarantees that nobody will do it. Not
actually true, and thank you for those people who have contributed!
2021-05-16 14:16:55 +02:00
Wojbie
cf2b332c3c Fix missing term.setCursorBlink(true) in edit.lua 2021-05-16 14:15:41 +02:00
Ronan Hanley
8984ebcf80 Refactor and add tests for TextBuffer (#738) 2021-05-16 14:15:35 +02:00
Jonathan Coates
a28e7e2db3 Bump version to 1.95.3 2021-05-16 14:14:31 +02:00
Jonathan Coates
3860e2466c Add User-Agent to Websockets
I think, haven't actually tested this :D:. Closes #730.
2021-05-16 14:13:19 +02:00
Wojbie
5b31c2536a Make edit display errors/results of execution and handle require. (#723) 2021-05-16 14:10:53 +02:00
Weblate
98dc7a6e58 Translations for Portuguese (Brazil)
Co-authored-by: Matheus Medeiros Souza <mmedeiros.cbp@gmail.com>
2021-05-16 14:10:48 +02:00
Jonathan Coates
5e0ceda7ce Clarify the turtle.place docs a little
Closes #714
2021-05-16 14:10:43 +02:00
SkyTheCodeMaster
7fe3ac9222 Fix redstone.getBundledInput(side) returning the output of said side. 2021-05-16 14:09:10 +02:00
Jonathan Coates
a65b8ed04c Migrate all examples to use tweaked.cc
Might as well, I've got the server capacity to spare. Hopefully.
2021-05-16 14:08:25 +02:00
JackMacWindows
3e14b84c23 Finish the rest of the event documentation (#683) 2021-05-16 14:01:59 +02:00
FensieRenaud
1710ad9861 Serialise sparse arrays into JSON (#685) 2021-05-16 14:00:29 +02:00
Jonathan Coates
9c48c99be7 Bump version to 1.95.2 2021-05-16 13:57:43 +02:00
Jonathan Coates
d10d1b45fe Bump several action versions 2021-05-16 13:54:37 +02:00
Wojbie
70a1cf5c5a id.lua now handles more disk types (#677)
Co-authored-by: Lupus590 <lupussolitarius590@gmail.com>
2021-05-16 13:53:00 +02:00
Jonathan Coates
b546a10bd6 Preserve registration order of upgrades
Makes them display in a more reasonable order within JEI. Closes #647
(note, the title is an entirley separate issue)!
2021-05-16 13:51:01 +02:00
SquidDev
2f35bbb538 Add some initial documentation for events
Credit to @BradyFromDiscord for writing these. See #640 and #565.

Co-authored-by: Brady <bradyakent@gmail.com
2021-05-16 13:25:17 +02:00
Jonathan Coates
891dde43a9 Clarify the cc.strings.wrap docs a little
Also make the example a bit more "useful". Hopefully this should clarify
that the function returns a table rather than a single string.

Closes #678.
2021-05-16 13:24:54 +02:00
Jonathan Coates
094e0d4f33 Fix mounts being usable after a disk is ejected
This probably fails "responsible disclosure", but it's not an RCE and
frankly the whole bug is utterly hilarious so here we are...

It's possible to open a file on a disk drive and continue to read/write
to them after the disk has been removed:

    local disk = peripheral.find("drive")
    local input = fs.open(fs.combine(disk.getMountPath(), "stream"), "rb")
    local output = fs.open(fs.combine(disk.getMountPath(), "stream"), "wb")
    disk.ejectDisk()

    -- input/output can still be interacted with.

This is pretty amusing, as now it allows us to move the disk somewhere
else and repeat - we've now got a private tunnel which two computers can
use to communicate.

Fixing this is intuitively quite simple - just close any open files
belonging to this mount. However, this is where things get messy thanks
to the wonderful joy of how CC's streams are handled.

As things stand, the filesystem effectively does the following flow::
 - There is a function `open : String -> Channel' (file modes are
   irrelevant here).

 - Once a file is opened, we transform it into some <T extends
   Closeable>. This is, for instance, a BufferedReader.

 - We generate a "token" (i.e. FileSystemWrapper<T>), which we generate
   a week reference to and map it to a tuple of our Channel and T. If
   this token is ever garbage collected (someone forgot to call close()
   on a file), then we close our T and Channel.

 - This token and T are returned to the calling function, which then
   constructs a Lua object.

The problem here is that if we close the underlying Channel+T before the
Lua object calls .close(), then it won't know the underlying channel is
closed, and you get some pretty ugly errors (e.g. "Stream Closed"). So
we've moved the "is open" state into the FileSystemWrapper<T>.

The whole system is incredibly complex at this point, and I'd really
like to clean it up. Ideally we could treat the HandleGeneric as the
token instead - this way we could potentially also clean up
FileSystemWrapperMount.

BBut something to play with in the future, and not when it's 10:30pm.

---

All this wall of text, and this isn't the only bug I've found with disks
today :/.
2021-05-16 13:23:37 +02:00
Wojbie
df40adce20 Make rightAlt only close menu, never open it. (#672)
Fixes #669
2021-05-16 09:22:11 +02:00
Jummit
e12ce95b2d Update to 1.16.4 2021-05-16 09:18:02 +02:00
Jonathan Coates
bcc0effd00 Fix impostor recipes for disks
Well, this is embarrassing. See #652
2021-05-16 07:57:06 +02:00
Jonathan Coates
64f3aa2dba Fix problem with RepeatArgumentType
The whole "flatten" thing can probably be dropped TBH. We don't use it
anywhere. Fixes #661
2021-05-16 07:48:07 +02:00
Wojbie
515ccfebd3 Added Numpad Enter Support in rom lua programs. (#657) 2021-05-16 07:43:06 +02:00
Lupus590
0b6dbe7778 Add isReadOnly to fs.attributes (#639) 2021-05-16 07:42:55 +02:00
Jonathan Coates
19054684c6 Merge branch 'mc-1.15.x' into mc-1.16.x 2021-05-16 07:42:39 +02:00
Jonathan Coates
a72a5e6deb Fix disk recipes
Closes #652. This has been broken since the 1.13 update. Not filling
myself with confidence here.
2021-05-16 07:42:12 +02:00
Jonathan Coates
eb2d9482a2 Prevent reflection errors crashing the game
.getMethods() may throw if a method references classes which don't exist
(such as client-only classes on a server). This is an Error, and so is
unchecked - hence us not handling it before.

Fixes #645
2021-05-16 07:41:22 +02:00
Jummit
95794fdaf3 Add back command computer block drops
This has been broken for almost a year (28th Jan 2020), and I never
noticed. Good job me.

Fixes #641, closes #648 (basically the same, but targetting 1.15.x)
2021-05-16 07:40:43 +02:00
David Queneau
af477a401a Update to loom 0.6 2021-05-15 11:06:35 -07:00
David Queneau
27531c161d Update to mc 1.16.5 and latest yarn mappings. 2021-05-15 11:06:35 -07:00
Merith-TK
a8f208c394 Update banner with cooler banner 2021-05-15 10:31:59 -07:00
Merith
148d9e9dda Merge pull request #22 from Jummit/update-mod-json
Update fabric.mod.json
2021-05-15 09:37:40 -07:00
Jummit
67fc21271b Add Jummit to authors and fix dead links 2021-05-16 02:34:53 +02:00
Merith-TK
ce28e2659a Update Readme from 3prm3 2021-05-15 09:36:26 -07:00
Merith
47e4826f2b Merge pull request #14 from Jummit/fix-mouse-up-events
fix mouse_up events not being emitted
2021-05-15 09:04:35 -07:00
Merith
9bde2d8d13 Merge Commits from Jummit/cc-restitched PR21 2021-05-15 08:45:21 -07:00
Jummit
46acb6866e 2020 -> 2021
Oh, the most useless part of my build process.
2021-05-16 01:27:46 +02:00
Jummit
c0506108f9 Fixed missing argument names in file handle docs (#632) 2021-05-16 01:27:44 +02:00
Jummit
0dd7c3695f Add explicit @module annotation
This feels like a bug - it should be inferred automatically.
2021-05-16 01:27:31 +02:00
Jummit
2a290be248 Bump version to 1.95.0
As is tradition.
2021-05-16 01:26:56 +02:00
Jummit
c4a6c16330 Manually wrap strings for help (#602)
This saves us writing to a buffer multiple times, and so makes things much,
much faster.
2021-05-16 01:26:43 +02:00
Jummit
f8b3b544d1 Add functions to wrap text 2021-05-16 01:26:32 +02:00
Jonathan Coates
53ae689468 Fix licence issues
I knew I shouldn't do modding on things which aren't my main computer.

I actually did run checkstyleMain before committing, but entirely forgot
about this one. Go me.
2021-05-16 01:26:21 +02:00
Merith
73e460e533 Merge Commits from Jummit/cc-restitched PR20 2021-05-15 08:05:59 -07:00
Jummit
a4e68d637a Make upgrade recipe requirements a little more lax
- Move some common upgrade code to IUpgradeBase. 99% sure this this
   preserves binary compatibility (on the JVM at least).

 - Instead of requiring the share tag to match, allow upgrades to
   specify their own predicate. IMO this is a little ugly, but required
   to fix #614 as other mods chuck their own NBT on items.
2021-05-16 00:50:24 +02:00
Jonathan Coates
1f1b20c81e Fix overflow in os.epoch
Closes #611
2021-05-16 00:10:49 +02:00
Jonathan Coates
20a9ff7a3f Fix double URL decode
Closes #613
2021-05-16 00:10:40 +02:00
Jonathan Coates
58cd5e3df7 Fix copy-paste error in inventory docs
I'm a very silly squid.
2021-05-16 00:10:19 +02:00
Jonathan Coates
5922d7548c Merge pull request #606 from TheWireLord/numpadenter-support
Added Numpad Enter Support - bios.lua
2021-05-16 00:06:13 +02:00
Merith
386e01364e Merge Commits from Jummit/cc-restitched PR19 2021-05-15 06:53:14 -07:00
Jummit
70eff6aa63 Skip "Docs for energy and inventory methods" 2021-05-15 20:34:30 +02:00
SquidDev
45ac601946 Generate docs for generic peripherals
This was the easy bit. Now I've got to write them!
2021-05-15 20:21:15 +02:00
SquidDev
d6c5a5bd27 Some sanity checks for get{Direction,Orientation}
Silly bodge, but should fix #600.
2021-05-15 20:18:04 +02:00
SquidDev
02c7903cb7 Remove a couple of todos 2021-05-15 20:06:21 +02:00
Jummit
37e856efdc Skip 737b3cb5
Don't use capabilities for generic peripherals
2021-05-15 20:04:51 +02:00
Merith-TK
8a38097887 [Patchwork] fix github workflow 2021-05-15 06:46:23 -07:00
Merith
884b417ec2 Merge Commits from Jummit/cc-restitched
SquidDev-CC/CC-Tweaked@511eea3
SquidDev-CC/CC-Tweaked@826797c
SquidDev-CC/CC-Tweaked@24d3777
SquidDev-CC/CC-Tweaked@d83a68f
2021-05-14 06:16:56 -07:00
JackMacWindows
1d1d6227eb Added improved help viewer (#595)
- Pagination, with (page) up/down, q(uit) and scrolling support.
 - Render markdown style bullets ('-'/'*') using a '•' instead.
2021-05-14 21:36:08 +02:00
Jummit
d5eb82db60 Allow $private HTTP rule to block any private IP
This is a little magic compared with our previous approach of "list
every private IP range", but given then the sheer number we were
missing[1][2] this feels more reasonable.

Also refactor out some of the logic into separate classes, hopefully to
make things a little cleaner.
2021-05-14 21:31:03 +02:00
JackMacWindows
3575654d02 Added documentation for global functions (#592) 2021-05-14 19:37:54 +02:00
Jonathan Coates
79fcc7241b Remove <!-- -->s in usages
We fixed the bug in illuaminate, so this should be redundant now.
2021-05-14 18:51:10 +02:00
Merith-TK
b203d3aa0a Try to handle a turtle being broken while ticked
Hopefully fixes #585. Hopefully.
2021-05-07 15:05:00 -07:00
Merith-TK
f1176af9d1 Make fs.combine accept multiple arguments
Means we can now do fs.combine("a", "b", "c"). Of course, one may just
write "a/b/c" in this case, but it's definitely useful elsewhere.

This is /technically/ a breaking change as fs.combine(a, b:gsub(...))
will no longer function (as gsub returns multiple arguments). However,
I've done a quick search through GH and my Pastebin archives and can't
find any programs which would break. Fingers crossed.
2021-05-07 13:27:04 -07:00
Merith-TK
717686d855 Allow strings or numbers in textutils.*tabulate
Allow strings or numbers in textutils.*tabulate

A little dubious, but apparently CC used to support it. This means we're
consistent with methods like io.write or string.len which accept strings
or numbers.

Fixes #591
2021-05-07 11:26:24 -07:00
Jummit
92811ca0bc fix mouse_up events not being emitted
fixes #11
2021-04-24 19:03:35 +02:00
Merith-TK
f8a58dbcb1 Fixed length check on function name in expect (#589) 2021-04-22 11:54:56 -07:00
Merith-TK
98aabe2cfb Remove extra space (#586) 2021-04-22 11:43:58 -07:00
Merith-TK
f938ed9779 Strict Globals (#583) 2021-04-22 11:35:15 -07:00
Merith-TK
03c9274b27 More examples
Yay!
2021-04-22 11:23:31 -07:00
Merith-TK
92c94ac039 Cleanup examples for the various modules 2021-04-21 19:32:03 -07:00
Merith-TK
5c6fd80b0c Use term.blit on original paint render
This makes it super speedy, meaning an initial refresh doesn't take ages to load.
2021-04-21 08:57:32 -07:00
Merith-TK
f1ec59df15 Clear gets an option to reset the palette (#582)
Fixes #555.
2021-04-21 08:32:34 -07:00
Merith-TK
624b23c7ac Fix epoch documentation to use milliseconds (#580) 2021-04-09 20:45:59 -07:00
Merith-TK
9b77a4aaee Update Readme with Known Issues 2021-04-09 20:03:14 -07:00
Merith-TK
d8b0037cfa CC:R 1.94.1-beta
Update version info, re-brand from CC:Tweaked For Fabric, to CC:Restitched
2021-03-28 22:49:15 -07:00
Merith-TK
91a9e7fdf7 Update .gitignore 2021-03-27 16:40:59 -07:00
Merith-TK
2c3573719b [Patchwork] Fix Network Config
Network config should now work in a stable mannor, the previous person did not port over the imports and thats why this broke in the first place, possibly required import did not exist for fabric at the time?
2021-03-27 15:19:09 -07:00
Devan-Kerman
46bc42d5a7 Update README.md 2021-03-04 19:23:36 -06:00
Devan-Kerman
1b9e93a80f Merge pull request #31 from davidqueneau/fabric
Revert "Cable modems can be placed against all blocks, including ches…
2021-03-04 19:23:07 -06:00
Devan-Kerman
7b93f91ffa Merge pull request #36 from Merith-TK/fabric
Update to Match CC:T version
2021-03-04 19:22:59 -06:00
Merith-TK
31a1027401 Clean up some examples a little bit
Would be good if they didn't crash and burn on entry :).
2021-03-02 23:12:53 -08:00
Merith-TK
e0fc994819 [TODO] Auto-generate monitor models
I didn't think it was worth it, and then I found myself needing to
update a dozen of them. The code isn't especially pretty, but it works,
so that's fine.

Also fixes several issues with us using the wrong texture (closes #572).
I've put together a wiki page[1] which describes each texture in a
little more detail.

[1] https://github.com/SquidDev-CC/CC-Tweaked/wiki/Monitor-texture-reference
2021-03-02 22:47:44 -08:00
Merith-TK
43408bf085 CC:R 1.94.0 2021-03-02 19:21:12 -08:00
Merith-TK
d28f42e8b7 use arg[0] in all usage printouts (#571) 2021-03-02 18:22:26 -08:00
Merith-TK
ac452582c1 Use blit to draw boxes, add colors.toBlit (#570) 2021-02-22 18:49:39 -08:00
Merith-TK
7e65c6b25c Fix JSON objects failing to pass 2021-02-22 18:11:27 -08:00
Merith-TK
457a863842 Dont fail when codecov is being finicky 2021-02-22 18:09:31 -08:00
Merith-TK
eef36e1358 Various SNBT parsing improvements 2021-02-22 17:45:44 -08:00
Merith-TK
feda08b915 Draw in-hand pocket computers with blending 2021-02-22 17:43:54 -08:00
Merith-TK
0240ce50ce Bump cct-javadoc version 2021-02-22 17:34:20 -08:00
Merith-TK
592b83e784 [TODO] Fix players not getting advancements when they own turtles 2021-02-22 17:32:26 -08:00
Merith-TK
5d91491ec7 Remove superfluous imports 2021-02-22 12:25:13 -08:00
Merith-TK
7326d1110d Make generic peripherals on by default 2021-02-22 12:17:03 -08:00
Merith-TK
0aa6ac05a0 Add function to get window visibility 2021-02-22 11:56:22 -08:00
Merith-TK
27a2c063b9 Update configuration to match latest illuaminate 2021-02-22 11:50:33 -08:00
Merith-TK
89a195ec06 CC:R 1.93.1 2021-02-22 11:05:23 -08:00
Merith-TK
0e5fd4e8e0 Fix TBO norm issues on old GPUs 2021-02-22 10:56:52 -08:00
Merith-TK
aa4ec53bb6 Bump JEI/crafttweaker versions 2021-02-22 10:50:57 -08:00
Merith-TK
6b49327462 Document remaining OS functions (#554) 2021-02-22 10:49:52 -08:00
Merith-TK
74ad934889 Add color table to docs (#553) 2021-02-22 10:43:27 -08:00
Merith-TK
08b3dbbad5 Fix My Docs, Update Patchwork Format 2021-02-22 10:38:52 -08:00
Merith-TK
54eac0a2f8 CC:R 1.93 2021-02-22 10:27:15 -08:00
Merith-TK
51ca5e620c Don't propagate adjacent redstone signals for computers (#549)
[PatchWork] Also updated patchwork format information
2021-02-22 10:22:10 -08:00
Merith-TK
076d572831 Fix io.open documentation 2021-02-22 03:25:08 -08:00
Merith-TK
75f2b91fef Translations for Swedish 2021-02-22 03:23:58 -08:00
Merith-TK
79534e5630 Fix incorrect open container check 2021-02-22 03:22:39 -08:00
Merith-TK
d483a91459 Use tags to check if something is a dye 2021-02-22 03:08:41 -08:00
Merith-TK
71d764f122 HTTP rules now allow filtering by port 2021-02-22 02:56:04 -08:00
Merith-TK
2e527eb11e Fix additional - in docs 2021-02-22 01:45:26 -08:00
Merith-TK
19273b3696 CC:R 1.92.0 2021-02-22 01:42:34 -08:00
Merith-TK
4643641d51 Update Patchwork, Handle Tabs when Parsing Json 2021-02-22 01:23:39 -08:00
Merith-TK
63cd9c5bc7 Update Patchwork.md with format 2021-02-22 01:20:51 -08:00
Merith-TK
e9c11ff325 Translations for Vienamese 2021-02-22 01:13:56 -08:00
Merith-TK
452464aa01 add changelog + vienamese support 2021-02-22 01:11:29 -08:00
Merith-TK
8885462175 Don't use entity.captureDrops at all (removed line) 2021-02-22 01:05:22 -08:00
Merith-TK
b8bd64913b Add date-specific MOTDs (like Minecraft) (CCT#533) 2021-02-22 01:02:56 -08:00
David Queneau
00b458c39a Revert "Cable modems can be placed against all blocks, including chests."
This reverts commit 664df62d
2021-02-07 10:47:50 -08:00
Devan-Kerman
88722d484f Merge pull request #29 from davidqueneau/fabric
Porting GenericPeripherals from upstream CC: Tweaked
2021-02-03 10:44:02 -06:00
David Queneau
6d103e2114 Item movement methods now respect inventory slot rules (i.e. no pickaxes in the fuel slot of a furnace). 2021-02-01 23:21:25 -08:00
David Queneau
42f23d56ae Double chest inventories are now handled correctly. 2021-02-01 19:04:02 -08:00
David Queneau
89d5211bd7 Fixed bad assumption about empty ItemStacks being reset to ItemStack.EMPTY. Items no longer transfer into an inventory as a different item than they began. 2021-02-01 00:02:28 -08:00
David Queneau
83e70377f7 Fixed off by one error. Commented not very nice inventory code. 2021-01-31 20:13:59 -08:00
David Queneau
f6a26f75c3 Reverted change to how GenericPeripherals report type. Instead, added generic lua function that returns the name of Nameable targets. Might not be at home in InventoryMethods since it could apply to other types of targets. 2021-01-30 20:45:08 -08:00
David Queneau
664df62d5d Cable modems can be placed against all blocks, including chests. 2021-01-30 17:12:09 -08:00
David Queneau
1348ee0588 Ported the generic peripheral feature from upstream forge version along with initial implementation of generic inventory peripherals. 2021-01-30 15:28:11 -08:00
Jacob Farley
145dce7653 Merge pull request #27 from techninja1008/fix-http-config
Fix http config
2021-01-21 20:09:23 -06:00
Jacob Farley
7f2651c23e Merge pull request #28 from techninja1008/fix-turtle-breaking-computer
Change turtle block breaking to call onBreak
2021-01-20 15:06:17 -06:00
Danny Wensley
05464107a8 Update ComputerCraft.httpRules on config sync.
Also removes a bit of http config related legacy code.
2021-01-20 20:03:00 +00:00
Danny Wensley
86705787f0 Change turtle block breaking to call onBreak
Fixes #25
2021-01-20 14:30:11 +00:00
Devan-Kerman
b34d8387d9 Update README.md 2020-12-29 15:17:00 -06:00
Devan-Kerman
4d00969ef0 fix #10
Signed-off-by: Devan-Kerman <devan@cleverpath.com>
2020-09-15 11:52:23 -05:00
Devan-Kerman
01d3d12992 update commits
Signed-off-by: Devan-Kerman <devan@cleverpath.com>
2020-09-15 11:38:16 -05:00
Devan-Kerman
5e31dcde83 fix CCE
Signed-off-by: Devan-Kerman <devan@cleverpath.com>
2020-09-12 20:20:38 -05:00
Devan-Kerman
5184883af1 fix potential bug
Signed-off-by: Devan-Kerman <devan@cleverpath.com>
2020-09-09 10:07:38 -05:00
Devan-Kerman
0c45112262 fix npe 2020-09-09 09:36:47 -05:00
Jacob Farley
0bf1672f45 Update README.md 2020-09-08 12:31:17 -05:00
Devan-Kerman
e1b8ac1f84 does this work? I don't know, it probably does 2020-09-07 13:19:14 -06:00
Jacob Farley
deea552d99 Merge remote-tracking branch 'origin/fabric' into fabric 2020-09-07 10:54:52 -05:00
Jacob Farley
54229c2ce1 I suppose Netherite Pick turtle recipe is important. 2020-09-07 10:54:46 -05:00
Devan-Kerman
1346a26179 remove all filthy access wideners 2020-09-06 20:04:23 -05:00
Jacob Farley
14df44f09d Fix crash from inspecting sign text 2020-09-06 18:45:30 -05:00
Jacob Farley
1a21529499 Merge remote-tracking branch 'origin/fabric' into fabric 2020-09-06 16:50:36 -05:00
Jacob Farley
2546990f41 Fix playNote not working for Speaker peripheral. 2020-09-06 11:21:20 -05:00
Devan-Kerman
b39ca02464 Merge pull request #5 from immibis/fabric
Turtles can read sign text.
2020-09-06 08:47:09 -06:00
immibis
628618105c Turtles can read sign text. 2020-09-06 12:14:41 +02:00
Jacob Farley
075ba03f5d Merge pull request #2 from Zundrel/fix_ids
Fix IDs
2020-09-05 18:57:34 -05:00
Mary
10bf84b631 Update ViewComputerContainerData.java 2020-09-05 20:58:05 +02:00
Jacob Farley
c346e22a45 Fix creative tab localization. 2020-09-05 10:10:07 -05:00
Jacob Farley
418e1335b1 Netherite pick turtle. 2020-09-05 10:08:53 -05:00
Jacob Farley
d52372df31 Fix Turtle tool rendering. 2020-09-05 10:02:41 -05:00
Jacob Farley
cc72e1c2bd Fix turtle digging. 2020-09-04 21:49:07 -05:00
Jacob Farley
d28afcc6a9 Update Gradle and, you know, actually give it RAM. 2020-09-04 20:33:43 -05:00
Jacob Farley
220ed21e6e Oops forgot this. 2020-09-04 20:15:43 -05:00
Jacob Farley
09d465774d Bumped version to 1.91.1 (same as 1.16.2 Forge version) 2020-09-04 20:12:14 -05:00
Jacob Farley
dfc8f48f12 Disable TurtleTool rendering temporarily. 2020-09-04 20:08:53 -05:00
Jacob Farley
abe2ec4686 Fixed pocket and turtle upgrades. (Turtle tools render weird in inventories) 2020-09-04 19:55:15 -05:00
Devan-Kerman
5333cda44e the final sin, I hope 2020-09-04 18:18:10 -05:00
Devan-Kerman
dc88fbeb12 Merge remote-tracking branch 'origin/fabric' into fabric
# Conflicts:
#	src/main/java/dan200/computercraft/shared/computer/blocks/BlockComputerBase.java
2020-09-04 18:09:36 -05:00
Devan-Kerman
c5eb7a9501 reformat 2020-09-04 18:07:48 -05:00
Jacob Farley
bc969db2be Merge remote-tracking branch 'origin/fabric' into fabric 2020-09-04 18:06:03 -05:00
Jacob Farley
50b7646178 Fix block setting more and fix computer break noise and particles. 2020-09-04 18:05:53 -05:00
Devan-Kerman
3fa6b5bc9d god forgive me, for I have sinned 2 2020-09-04 17:49:41 -05:00
Devan-Kerman
33e65e39e3 god forgive me, for I have sinned 2020-09-04 17:29:46 -05:00
Jacob Farley
0380e60590 Fixed block settings. 2020-09-04 14:14:14 -05:00
Jacob Farley
2918892ee2 Oops 2020-09-04 14:12:23 -05:00
Jacob Farley
e43dd9f7c6 Fix cables and turtle rendering. 2020-09-04 14:05:56 -05:00
Jacob Farley
244fd95034 Fix computer and monitor syncing. 2020-09-04 12:35:55 -05:00
Jacob Farley
14e98e2fcb Add AW to fabric.mod.json 2020-09-04 10:25:09 -05:00
Jacob Farley
dcf5d59109 fix peripherals 2020-09-01 11:44:08 -05:00
shedaniel
b95083c77e make gui work 2020-09-01 23:41:50 +08:00
shedaniel
c54c8c3ea6 computers block themselves render 2020-09-01 22:37:43 +08:00
Devan-Kerman
f79c67e243 CRAB GAME IS LAUNCH CRAB 2020-08-31 20:03:40 -05:00
Jacob Farley
6ec7ebe439 Yes hello and hey 0.5 Loom 2020-08-31 19:43:11 -05:00
Jacob Farley
76fe33760d It now compiles. 2020-08-31 19:09:22 -05:00
Devan-Kerman
cb549d8f43 help 2020-08-31 13:44:05 -05:00
Martmists
7b400fdcdd Merge branch 'fabric' of github.com:Zundrel/cc-tweaked-fabric into fabric 2020-08-30 15:47:01 +02:00
Martmists
ab70d918b5 yeef 2020-08-30 15:46:57 +02:00
Devan-Kerman
c64644b9ec time to make a diff of the fabric branch with ours to see what we are miss 2020-08-30 08:35:44 -05:00
Jacob Farley
afb12eb342 Fix FrameInfo 2020-08-29 22:16:06 -05:00
Jacob Farley
64f5ca02b3 Auto stash before merge of "fabric" and "origin/fabric" 2020-08-29 22:14:32 -05:00
Devan-Kerman
84bca21b0c show true error count 2020-08-29 22:10:14 -05:00
Devan-Kerman
b6757c416f ClientRegistry 2020-08-29 22:06:04 -05:00
Devan-Kerman
dc9d3f2d15 TurtlePlayer 2020-08-29 21:55:11 -05:00
Devan-Kerman
807825d74e registry is gone 2020-08-29 21:42:17 -05:00
Jacob Farley
14c17676c6 Some basic fixes, will work on this some other time. 2020-08-29 20:13:35 -05:00
Devan-Kerman
324519575c remap with yarrnforge 2020-08-29 19:38:26 -05:00
Devan-Kerman
fbcf26bdc9 remap with yarrnforge 2020-08-29 19:32:53 -05:00
Devan-Kerman
30ab6bd045 Merge remote-tracking branch 'origin/fabric' into fabric 2020-08-29 18:47:57 -05:00
Devan-Kerman
2ea816b78b printout renderer, terminal, tile printer, fake player, guicomputer, fixed width font renderer 2020-08-29 18:47:47 -05:00
Jacob Farley
56dcc57755 Fix some issues, add AW. 2020-08-29 18:44:19 -05:00
Devan-Kerman
a4830aff86 cloth config 2020-08-29 18:01:13 -05:00
Devan-Kerman
621bc526be remap 2020-08-29 18:01:01 -05:00
Alex Evelyn
605e1f6b9b Started work on upgrading to 1.16.1. Not in a compilable state yet 2020-07-07 13:27:13 -04:00
parly
cb66ef7e30 v1.14.4-1.83.2+build.9 2019-12-02 00:19:02 +09:00
parly
fd2f6a38c1 Update dependencies 2019-12-02 00:17:49 +09:00
parly
229821d398 Organize imports 2019-12-02 00:00:36 +09:00
hugeblank
1f2e0c444d Initial Implementation of Feature
Adds the ability for the command computer to get block information from other dimensions by passing the dimension ID as the last argument in both getBlockInfo and getBlockInfos
2019-12-01 23:55:54 +09:00
parly
429baa350c Fix issues with building with Java 9+, take 2
Fix another potential issues when using Java 9+ at build time and Java
8 at runtime.
2019-10-24 01:11:25 +09:00
parly
7fe62485fa v1.14.4-1.83.2+build.8 2019-10-20 00:40:48 +09:00
parly
fe10c68099 Update dependencies 2019-10-20 00:29:50 +09:00
parly
06092cfddd Fix issues with building with Java 9+
Fix for NoSuchMethodError when using Java 9+ at build time and Java 8
at runtime.

Fixes #14
2019-10-19 23:58:34 +09:00
parly
9967dc5740 Cleanup build.gradle
Based on #18 (thanks to hugeblank and Fuyukai), made the following
changes:

* Shade Cobalt
It seems that NoClassDefFoundError occurs on the CC thread if the
library Cobalt is not shaded.

* More cleanup
Removed more unnecessary parts.
2019-10-19 23:38:25 +09:00
hugeblank
b920e04c59 oneline fix command parsing
(Merged from #17)
2019-10-18 19:14:38 -07:00
parly
baa1b5a5c9 v1.14.4-1.83.2+build.7 2019-10-01 16:07:19 +09:00
parly
e84663a5c5 Update ClothConfig 2019-10-01 15:41:36 +09:00
parly
1c46220c42 Update Fabric toolchain 2019-10-01 15:41:16 +09:00
parly
889b445855 Add time unit conversion
Task execution times are stored in the config file in milliseconds, but
they're stored internally in nanoseconds. This commit adds time unit
conversions from milliseconds to nanoseconds.

Fixes #9
2019-10-01 15:21:37 +09:00
parly
19553a981e v1.14.4-1.83.2+build.5 2019-09-28 00:17:28 +09:00
parly
15f4dbd061 Update ClothConfig 2019-09-28 00:06:23 +09:00
parly
98e12c7c3e Quick patch to fix rendering issues with OptiFine
OptiFine seems to cause NullPointerException when it cannot find loader.spriteAtlas::getSprite method in ModelItemPropertyOverrideList constructor.

Fixes #1
2019-09-27 23:36:03 +09:00
svitoos
dfad319864 Fix build (jankson version in 'include') 2019-09-23 02:33:33 +09:00
parly
111b58f533 v1.14.4-1.83.2+build.4 2019-09-22 23:59:26 +09:00
parly
9345652808 Change repository url 2019-09-22 23:50:07 +09:00
svitoos
d40163b409 Fix mod metadata 2019-09-22 23:26:12 +09:00
svitoos
96400966d7 - Add config (json5, jankson)
- Add config gui (Cloth Config API and Mod Menu)
2019-09-22 23:26:12 +09:00
parly
db83bd4f64 v1.14.4-1.83.2+build.3 2019-09-16 22:52:10 +09:00
parly
579a38d366 Format code 2019-09-16 22:45:32 +09:00
parly
0e6797c7da Update fabric toolchain 2019-09-16 22:34:25 +09:00
parly
c935577768 Update gradle wrapper to 5.5.1 2019-09-16 22:23:41 +09:00
parly
c2b4077aa1 Update group 2019-09-16 22:22:19 +09:00
svitoos
ac020859f3 code cleanup 2019-09-16 22:19:16 +09:00
svitoos
238be8955b Fix turtle can't place water in waterloggable blocks 2019-09-16 22:19:16 +09:00
svitoos
f997b02b8f Fix the use of the item on the entity 2019-09-16 22:19:16 +09:00
svitoos
799bb77847 Fix turtle place bucket in the wrong block 2019-09-16 22:19:16 +09:00
parly
2f66792a0d v1.14.4-1.83.2+build.2 2019-08-19 21:38:50 +09:00
doomy64
6cae8e211e Update ServerComputer.java
Fix os.time and os.day

(Merged from #4)
2019-08-18 16:31:15 +09:00
parly
48b1b2f01d v1.14.4-1.83.2 2019-08-09 22:26:46 +09:00
parly
8c45fd362a Update to Minecraft 1.14.4 2019-08-09 22:26:46 +09:00
parly
07b13dd2b4 Prepare for cc-tweaked-fabric 2019-08-09 22:26:46 +09:00
SquidDev
45e84e1ede Merge branch 'mc-1.13.x' into mc-1.14-fabric 2019-06-02 18:41:53 +01:00
SquidDev
b6715bd812 Fix a couple of build failures 2019-06-02 18:36:34 +01:00
SquidDev
725dfa764f Add highlight rendering for monitors and cables 2019-06-02 18:24:08 +01:00
SquidDev
c221502ec9 Correctly offset touch position on a monitor
Fixes #223
2019-06-02 18:06:24 +01:00
SquidDev
234f18c228 Merge branch 'mc-1.13.x' into mc-1.14-fabric 2019-06-02 17:54:00 +01:00
SquidDev
006ad109cb Update to 1.14.2
Ughr, mapping changes. Though this time they weren't too bad I guess.
2019-06-02 17:42:07 +01:00
SquidDev
18aee02221 Mark CurseForge builds as release
They're almost definitely not, but I've had no bug reports so they must
work!
2019-06-02 17:28:13 +01:00
SquidDev
401bbf2e6a Fix turtle block placing failing 2019-06-02 17:25:49 +01:00
SquidDev
7467b7f88a Fix several deprecated warnings 2019-06-02 17:23:33 +01:00
SquidDev
c82d8a7c2a Merge branch 'master' into mc-1.13.x 2019-06-02 16:46:45 +01:00
SquidDev
6b81bcf334 Bump version 2019-06-02 16:20:15 +01:00
SquidDev
3d67421d98 Bump Forge version 2019-06-02 16:18:44 +01:00
SquidDev
acac70675d Add link to CF on the README
Not sure how useful this is - people are far more likely to come across
the CurseForge page than the GH one, but there's no harm I guess.

Closes #227
2019-06-01 15:15:39 +01:00
JakobDev
56434259c1 Add Checks for Turtle and Pocket programs (#226)
Error if turtle and pocket computers programs are not run on
their respective devices.
2019-06-01 12:48:33 +01:00
JakobDev
da7e4b9016 Add more MOTD messages. (#225) 2019-06-01 12:41:01 +01:00
SquidDev
d4b8650d21 Use select('#', ...) instead of ipairs on varargs
This means we don't discard any value after nil, meaning that
calls such as colors.combine(nil, 1, 2, 3) will error, rather
than returning 0.
2019-06-01 10:12:10 +01:00
SquidDev
17645a79f0 Fix type check on rednet.lookup
Fixes #224
2019-06-01 09:23:18 +01:00
SquidDev
ce1f14a010 Fix a couple of problems in the release buildscript
Otherwise that went pretty smoothly!
2019-05-31 13:56:48 +01:00
SquidDev
43050426de Bump version
First time using the new changelog tooling, let's see how this goes.
2019-05-31 13:53:15 +01:00
SquidDev
b05f60c98b Add small task to verify changelog is correct
Also use the changelog contents as the GH release notes
2019-05-31 10:19:24 +01:00
SquidDev
c44c560f96 Update changelog and whatsnew
- Convert existing changelog over to use Markdown. This mostly involves
   wrapping code in backticks, and marking things as headers where
   appropriate.
 - Copy all of CC:T's release notes over to the changelog. This is
   somewhat more verbose than Dan's notes, but keeping them in sync
   seems reasonable (and allows for automation!).
2019-05-31 09:35:45 +01:00
SquidDev
e839ef54af Forbid mutating empty_json_array
It's definitely still possible (rawset), but should prevent people
accidentally trying to modify it when they shouldn't.
2019-05-30 20:01:09 +01:00
SquidDev
0cb659d78c Ensure require is usable within the REPL
As 'require' operates relative to the current program's directory,
rather than the current directory, it meant we were trying to load files
from /rom/programs.

This is never a good idea, so we add the current directory to the
package path, allowing you to use require as one'd expect.
2019-05-30 19:52:55 +01:00
hydraz
9048deeb95 Add a function for type-checking arguments (#207)
- Define an expect(index, actual_value, types...) helper function which
   takes an argument index, value and list of permissable types and
   ensures the value is of one of those types.
   If not, it will produce an error message with the expected and actual
   type, as well as the argument number and (if available) the function
   name.
 - Expose expect in the global scope as _G["~expect"], hopefully making
   it clear it is internal.
 - Replace most manual type checks with this helper method.
 - Write tests to ensure this argument validation works as expected

Also fix a couple of bugs exposed by this refactor and the subsequent
tests:
 - Make rednet checks a little more strict - rednet.close(false) is no
   longer valid.
 - Error when attempting to redirect the terminal to itself 
   (term.redirect(term)).
2019-05-30 19:36:28 +01:00
SquidDev
5592ebae7d A small bit of housekeeping
- Add a link to discord and the forums. Oh goodness, I hope this
   doesn't count as making things official.
   I've had a couple of people email me with support requests, which is
   /fine/, but there's better channels for it!
 - Add a couple of PR templates
   - Ask people to write tests for CraftOS changes. This is a standard
     I'm trying to impose on myself, so seems reasonable to impose on
     everyone. Sorry!
   - Require same levels of explanation for PRs as we do for issues.
 - Try to expand on the feature request "rationale" section a little.
   Just trying to explan my process a little bit more.
2019-05-30 08:44:15 +01:00
SquidDev
b076c32fd1 Merge remote-tracking branch 'origin' 2019-05-30 07:57:30 +01:00
SquidDev
a48f1e310f Add a custom renderer for monitor block highlights (#220)
This only renders the bounding box on non-screen edges of the monitor,
meaning you have an uninterrupted view of the screen when hovering
hover.

Closes #219
2019-05-30 07:51:35 +01:00
SquidDev
19aca001d7 A couple of stability improvements to ComputerThread
- Be more generous in what errors we catch, handling some of the more
   "recoverable" ones.
 - Should a runner crash, attempt to restart it.
2019-05-29 09:03:31 +01:00
SquidDev
0db080154c Fix incorrect inventory check
Closes #209
2019-05-26 16:29:28 +01:00
SquidDev
114f913bf8 Rework rendering of in-hand pocket computers (#215)
Rendering an item worked in principle, but had several caveats:
 - The terminal did not fit well within the item's texture, so we had a
   rather large border.
 - The "correctness" of this was very tied to Minecraft's item rendering
   code. This changed a little in 1.13, causing problems like #208.

Instead we effectively reuse the computer GUI rendering code, though
also handling coloured pocket computers and rendering the modem light.

This fixes #208, and hopefully fixes #212.
2019-05-26 15:24:37 +01:00
Daniel Ratcliffe
1c9810890a Merge pull request #577 from SquidDev-CC/feature/get-blink
Add .getCursorBlink to monitors and terminals
2019-05-26 00:14:02 +01:00
SquidDev
b11beb508b Convert mkdir motd note to plural
*shrug*
2019-05-25 19:17:10 +01:00
SquidDev
af8d4da594 Ensure the test name is ASCII
Gradle really doesn't like unicode apparently
2019-05-25 18:11:14 +01:00
JakobDev
a81db2cda6 Allow multiple arguments for mkdir (#216) 2019-05-25 18:04:56 +01:00
SquidDev
99bdff0f92 Automatically label issues created with templates 2019-05-25 14:53:48 +01:00
SquidDev
bb138326df Use correct model for blinking pocket computers
Fixes #211211211211211211211211211211211211211211211211211211211211211
2019-05-25 09:28:15 +01:00
hydraz
5b0ce7410d Make delete delete many files (#210)
Actually, many *globs*. It additionally prints the glob if no files
matched it, since that's clearer.

Also move the ComputerTestDelegate's filesystem to be disk-based. This
is what actual computers use, and the MemoryMount is a little broken.
2019-05-25 09:02:42 +01:00
SquidDev
d5ea22d1a0 Jolly good job 2019-05-24 22:43:59 +01:00
SquidDev
210f3fa9e2 Add mostly standard compliant os.time/os.date
- os.time, when given a table, will act the same as PUC Lua - returning
   the seconds since the epoch. We preserve the previous string/nil
   behaviour though - os.epoch("local") is equivalent to PUC's
   os.time().

 - os.date will now act accept a string and (optional) time, returning
   an appropriate table.

Somewhat resolves the madness which was dan200/ComputerCraft#183, and
hopefully (though probably not) makes @Vexatos happy.
2019-05-24 22:33:56 +01:00
SquidDev
d661cfa88b Set the arg table within shell.run
This makes us a little more compatible with Lua
2019-05-24 18:42:19 +01:00
SquidDev
68bf3a71dc Lazilly instantiate the terminal packet
This means we don't create an NBT tag every tick if the screen is
updating, unless we actually need to.
2019-05-24 18:32:56 +01:00
SquidDev
200311033f Small bodgey patch to fix NPEs when turtles place tiles 2019-05-14 17:17:34 +01:00
SquidDev
3192dc81ac Bump to 1.14.1 2019-05-14 16:35:40 +01:00
SquidDev
3cdb12d293 Stop shipping jars with GH releases
The build appears to be a little bit broken, I haven't got willpower to
look into it, and it's not really used anyway.
2019-05-14 07:44:19 +01:00
Wilma456 (Jakob0815)
ad33acd7d1 Add MOTD (#175) 2019-05-13 16:54:19 +01:00
SquidDev
0ec3884e98 Handle websockets which close while receiving
This changes the previous behaviour a little, but hopefully is more
sane:

 - Only require the socket to be open when first calling receive. This
   means if it closes while receving, you won't get an error.

   This behaviour is still not perfect - the socket could have closed,
   but the event not reached the user yet, but it's better.

 - Listen to websocket_close events while receiving, and return null
   should it match ours.

See #201
2019-05-08 08:16:21 +01:00
SquidDev
7f2471d6b2 Fix list-like config options not reloading
Closes #199
2019-05-08 08:00:07 +01:00
SquidDev
b11d4bb209 Bump to 1.14.1pr1
Which means bumping mappings version. Oh boy, this was not a bundle of
laughs...
2019-05-07 20:40:55 +01:00
SquidDev
2a716244e9 Don't use the TileTurtle as our property source
We probably need to do this for some other inventories too - to
investigate.

Fixes #198
2019-05-06 22:59:44 +01:00
SquidDev
19b7ed538a Hopefuly stub out all the network methods
Fixes #197
2019-05-06 22:46:44 +01:00
SquidDev
b0d9dc0b88 Merge branch 'mc-1.13.x' into mc-1.14-fabric 2019-05-06 21:53:59 +01:00
xuyu0v0
e0660b1dab Create zh_cn.json 2019-05-06 21:47:43 +01:00
SquidDev
2182cfbeb7 Merge branch 'master' into mc-1.13.x 2019-05-06 21:32:56 +01:00
SquidDev
8fafec4915 Fix budget growing too much
We were using += instead of =, meaning the budget always grew,
rather than growing while there was still space. As a result, computers
were never correctly rate limited.

Further more, if a computer went into a deficit, we would continue to
increase the budget by a negative amount, exponentially decreasing until
overflowing!

Yes, this is a very embarrassing mistake. I'd been aware that rate
limiting wasn't working as expected for a while, I hadn't realised
the problem would be this stupid.
2019-05-01 17:24:30 +01:00
SquidDev
b9fd690ecb Mark CC:T as incompatible with ComputerCraft
Just so people using the Twitch client don't try to use both.
2019-05-01 17:24:30 +01:00
SquidDev
e6094a59fa Get us booting on a dedicated server
It doesn't appear that blocks are syncing, so we'll need to look into
that. Hopefully fixes #193
2019-04-29 08:04:24 +01:00
SquidDev
e8d7e6a562 Fix a whole bunch of bugs 2019-04-25 11:31:40 +01:00
SquidDev
536c2d9b2d Merge branch 'mc-1.13.x' into mc-1.14-fabric 2019-04-25 08:39:32 +01:00
xuyu0v0
2f2ada4416 Create zh_cn.lang (#186) 2019-04-24 15:41:13 +01:00
SquidDev
9c951c58d9 Revert "Switch over to Curse maven for now"
This reverts commit 4b4b47e231.

Didn't need it for that long. Woops.
2019-04-24 15:17:13 +01:00
SquidDev
4b4b47e231 Switch over to Curse maven for now
It stinks, but it's a suitable workaround.

Closes #184
2019-04-24 14:48:11 +01:00
SquidDev
2c027adb68 Fix advancements
Looks like these were never properly updated. Woops.
2019-04-24 12:15:03 +01:00
SquidDev
f15a278f3b Bump versions 2019-04-24 11:54:03 +01:00
SquidDev
26b73c2ff3 Merge branch 'mc-1.13.x' into mc-1.14-fabric 2019-04-24 10:53:28 +01:00
SquidDev
4a25e7a178 Fix GH release uploading 2019-04-24 10:40:44 +01:00
SquidDev
55d54fec63 Bump versions 2019-04-24 10:33:50 +01:00
SquidDev
220e4bd660 Merge branch 'master' into mc-1.13.x 2019-04-24 10:15:33 +01:00
SquidDev
978c28a686 Bump version 2019-04-24 09:48:28 +01:00
SquidDev
b867ada5e5 Merge pull request #182 from SquidDev-CC/hotfix/redstone-checks
Redstone behaviour tweaks
2019-04-24 09:45:28 +01:00
SquidDev
7071cc972b Make redstone behaviour consistent with repeaters
This uses the same behaviour that repeaters and comparators do for
determining their input, meaning that redstone directly connected to the
computer is read (as you would expect).

It's worth noting that this is a shift from previous behaviour.
Therefore, it runs the (small) risk of breaking existing builds.
However, I believe it is more consistent with the expected behaviour.
2019-04-22 11:52:53 +01:00
SquidDev
6898f932a0 Remove redstone blocked checks
This has been returning false for almost 2 years (since
8abff95441). At this point, it's probably
worth just dropping it entirely.
2019-04-22 11:40:19 +01:00
SquidDev
2e0ef6385d Fix TurtleCompareCommand throwing exceptions
Originally introduced in 173ea72001, but
the underlying cause has been happening for much longer.

 - Fix order of method name parameters. Looks like this has been broken
   since 1.11. Woops.
 - Catch RuntimeExceptions too, as Forge converts checked into unchecked
   ones.

Fixes #179
2019-04-19 18:57:12 +01:00
SquidDev
f93da7ea51 Bump Cobalt version
I promise! The joys of using -SNAPSHOT I guess...

This will now correctly cause orphaned threads to be cleaned up,
reducing the risk of thread saturation.
2019-04-18 09:49:52 +01:00
SquidDev
1210bb8a4d Fix Gradle dependencies
I'm not entirely sure why it didn't like the previous version, but there
we go.
2019-04-16 10:43:11 +01:00
SquidDev
48a71e96eb Bump version 2019-04-16 10:35:15 +01:00
SquidDev
3bf47b5290 Make refuelling a little more flexible
This removes the link between item size and refuel limit, meaning
working with other items (such as FE items) is a little easier.
2019-04-16 10:28:10 +01:00
SquidDev
9e9f199e55 Remove a couple of over-eager error logs 2019-04-16 10:08:12 +01:00
SquidDev
5a8a111857 You didn't see nothing 2019-04-15 18:33:59 +01:00
SquidDev
48ba247ab4 Create an IMultipartTile for all BlockPeripheral tiles
Fixes #176
2019-04-15 09:21:10 +01:00
SquidDev
c1e08fc3c7 Fix computer block drops not being handles
This is still not 100% perfect - we don't drop them when in creative.
However, it's a notable improvement on what it was.

Closes #174
2019-04-12 19:54:08 +01:00
SquidDev
b9ec6f236d Update to 1.14pr2 2019-04-12 19:49:39 +01:00
SquidDev
b1fff97bff Bump to 1.14pr1 2019-04-11 09:40:32 +01:00
SquidDev
c81bc70475 Merge branch 'mc-1.13.x' into mc-1.14-fabric 2019-04-11 08:57:04 +01:00
SquidDev
362dbd97ac Correctly handle capability creation & invalidation
Also make cable part detection more consistent.
2019-04-09 17:29:23 +01:00
SquidDev
aa0e1883d1 Add check for if item/block registration has failed
If mod loading fails, we'll continue to load colour handlers. As
blocks/items have not been registered, then we'll throw an NPE.

See MinecraftForge/MinecraftForge#5682. Somewhat fixes #168.
2019-04-09 16:32:20 +01:00
SquidDev
9cdbcb4332 Use int instead of long for configs
Forge's config system will read the default values as integers, meaning
it fails to validate against the config spec. Ideally this'd be fixed in
forge, but this is a suitable work around.
2019-04-09 16:31:00 +01:00
SquidDev
23ddd4feb5 Fix several deprecation warnings 2019-04-09 16:30:44 +01:00
SquidDev
fcaa777c95 Merge branch 'master' into mc-1.13.x 2019-04-09 11:11:12 +01:00
SquidDev
b195cab6a7 Add a couple of colours unit tests 2019-04-09 10:35:23 +01:00
SquidDev
63dc0daa09 Convert computer sides to an enum
Previously we just relied on magic int values, which was confusing and
potentially error-prone. We could use EnumFacing, but that's a)
dependent on MC and b) incorrect, as we're referring to local
coordinates.
2019-04-09 10:02:54 +01:00
SquidDev
34602ec4be Move null checks from Preconditions to Objects 2019-04-08 14:54:57 +01:00
SquidDev
f3ce44042f Update all inputs if the block is not a neighbour
Fixes #172, and acts as a workaround for MrTJP/ProjectRed#1472.
2019-04-08 14:52:24 +01:00
SquidDev
4205f18f0c Publish jar files to GH too
I'm not sure if I'll keep this, as it's a little redundant. We're on an
older version of the plugin, as 2.2.7 seems to fail for me.

Closes #165.
2019-04-07 15:30:27 +01:00
SquidDev
6be330ae8d Expose Computer.getRootMount again
It's a little evil, but we need it for CCEmuX. There's other ways of
achieving this, but not with supporting CC and CC:T.
2019-04-07 14:58:25 +01:00
SquidDev
4569af2130 Bump version 2019-04-06 22:42:44 +01:00
SquidDev
765c31315a Make redstone updates identical to how MC does it
Also fixes rather embarassing bug with redstone not updating.
2019-04-06 22:42:03 +01:00
SquidDev
55a7ee4acf Initial update to Fabric 2019-04-03 23:27:10 +01:00
Wilma456 (Jakob0815)
0e191e42a0 Update de_de.lang (#166) 2019-04-03 14:58:04 +01:00
SquidDev
ca34b2a1b8 Update the dependency info a little 2019-04-02 21:37:19 +01:00
SquidDev
7afc3e5260 And fix the build failing 2019-04-02 21:33:55 +01:00
SquidDev
f9e13ca67a Update CC: Tweaked to 1.13
Look, I originally had this split into several commits, but lots of
other cleanups got mixed in. I then backported some of the cleanups to
1.12, did other tidy ups there, and eventually the web of merges was
unreadable.

Yes, this is a horrible mess, but it's still nicer than it was. Anyway,
changes:

 - Flatten everything. For instance, there are now three instances of
   BlockComputer, two BlockTurtle, ItemPocketComputer. There's also no
   more BlockPeripheral (thank heavens) - there's separate block classes
   for each peripheral type.

 - Remove pretty much all legacy code. As we're breaking world
   compatibility anyway, we can remove all the code to load worlds from
   1.4 days.
 - The command system is largely rewriten to take advantage of 1.13's
   new system. It's very fancy!

 - WidgetTerminal now uses Minecraft's "GUI listener" system.

 - BREAKING CHANGE: All the codes in keys.lua are different, due to the
   move to LWJGL 3. Hopefully this won't have too much of an impact.

   I don't want to map to the old key codes on the Java side, as there
   always ends up being small but slight inconsistencies. IMO it's
   better to make a clean break - people should be using keys rather
   than hard coding the constants anyway.

 - commands.list now allows fetching sub-commands. The ROM has already
   been updated to allow fancy usage such as commands.time.set("noon").

 - Turtles, modems and cables can be waterlogged.
2019-04-02 20:59:48 +01:00
SquidDev
810258e9b8 Update and rename all resources
- Languages are converted to JSON
 - Rename most *(_advanced) blocks to *_{advanced,normal}. It's more
   verbose, but means they're sorted together.
 - A couple of changes to the ROM to work with some Java changes.
 - Update recipes and advancements to not use damage values.
2019-04-02 13:18:43 +01:00
SquidDev
5e462adc5c Relocate all resource files
- textures/{block,item}s -> textures/{block,item}
 - assets/*/{advancements,lua,recipes} -> data/*/...
2019-04-02 13:18:43 +01:00
SquidDev
1fd0b40776 Fix printing not updating the output display state 2019-04-02 12:21:59 +01:00
SquidDev
2965fb666f Some further cleanup and 1.13 cherry-picks
Are most of these changes small and petty? Yes. However, IMO they do
make the code more readable. Anyway, a summary of some of the more
interesting changes:

 - Expose Abstract*Upgrade classes in the API
 - Fix the spelling of Jonathan in the API docs (*shakes fist*)
 - Fix bug with printout not working in the offhand.
 - Rename any argments/variables accidentally named "m_*", and add an
   inspection to prevent it happening again.
 - Remove most of the Block*.Properties classes - just inline them in
   the parent class.
 - Return super.writeToNBT instead of reassigning at the top.
2019-04-02 12:08:03 +01:00
Luca S
390575ab4d rednet.send now returns if the message was send (#164)
This makes use of the "sent" variable, which would otherwise go unused. It also makes rednet.send compliant to the behaviour specified in the Wiki: http://www.computercraft.info/wiki/Rednet.send
2019-04-01 19:31:21 +01:00
SquidDev
e4ef92ca2d Expose a stub "cctweaked" mod
This is largely invisible (it's marked as a child of the main
"computercraft" mod), but allows other mods (such as Plethora) to add
hard/soft dependencies on CC:T in a user-friendly manner.
2019-03-30 16:41:45 +00:00
SquidDev
9bf586b018 Make turtle crafting more consistent with vanilla
- Fire all the appropriate Forge hooks
 - Crafting will now attempt to craft one item at a time in a loop,
   instead of multiplying the resulting stack by the number of crafts.
   This means we function as expected on recipes which consume
   durability instead.
 - Cache the recipe between crafting and getting the remainder (and each
   craft loop). This should reduce any performance hit we would
   otherwise get.
2019-03-30 16:12:49 +00:00
SquidDev
173ea72001 Turn inspections up to 11
OK, so let's get this out of the way, there's some actual changes mixed
in here too. I'm really sorry:
 - Turtles can now not be renamed with unnamed item tags (previously it
   would clear the name, this seemed a little unideal).
 - commands.getBlock(s)Data will also include NBT.

Now, onto the horror story which is these inspection changes:
 - Make a lot of methods static
 - Typo fixes
 - Make utility classes final + private constructor
 - Lots of reformatting (ifs -> ternary, invert control flow, etc...)
 - ???
 - Profit!

I'm so going to regret this - can pretty much guarantee this is going to
break something.
2019-03-29 21:26:21 +00:00
SquidDev
1230cabcb0 Add an event for inspecting items too
We've had one for blocks for ever after all.
2019-03-27 20:58:14 +00:00
SquidDev
6ed03e1fcd Convert turtle refuelling into an event
This should allow us (or other mods) to register custom refuel handlers
should they so wish.
2019-03-27 20:38:39 +00:00
SquidDev
c4b371b124 Cherry pick several improvements from 1.13
- Move container opening (and gui handling) into a separate class
 - Move turtle/computer placement code onto the block
 - GUIs now use gui{Left,Top} instead of calculating it manually.
 - IPeripheralTile is now exposed in the API.
2019-03-27 19:20:59 +00:00
SquidDev
a600213b00 Merge pull request #153 from SquidDev-CC/feature/main-thread-limits 2019-03-26 11:28:35 +00:00
SquidDev
7799b8d4cb Convert MainThread into a priority queue
This uses a similar approach to ComputerThread: executors store how long
they've spent executing tasks. We then use that time to prioritise
executors.

One should note that we use the current runtime at the point of adding
to the queue - external tasks will not contribute towards it until a
later execution.
2019-03-26 11:21:40 +00:00
SquidDev
245bf26480 Expose max computer/global times as config options
These do have a direct impact on server performance, so are definitely
worthwhile exposing.
2019-03-26 11:21:40 +00:00
SquidDev
5d05205d69 Introduce IWorkMonitor into the public API
This effectively acts as a public interface to canExecuteExternal() and
consumeTime(). It's hopefully sufficiently general that we can mess
around with the backend as much as we like in the future.

One thing to note here is that this is based on a polling API, as it's
largely intended for people running work every tick. It would be
possible to adapt this with callbacks for when work is available,
etc..., but that was not needed immediately.

This also removes IComputerOwned, as Plethora no longer needs it.
2019-03-26 11:21:16 +00:00
SquidDev
853e2622a1 An initial prototype of main thread rate limiting
Unlike ComputerThread, we do not have a single source of tasks, and so
need a smarter way to handle scheduling and rate limiting. This
introduces a cooldown system, which works on both a global and
per-computer level:

Each computer is allowed to do some work for 5ms. If they go over that
budget, then they are marked as "hot", and will not execute work on the
next tick, until they have cooled down. This ensures that _on average_
computers perform at most 5ms of work per tick.

Obviously this is a rather large time span, so we also apply a global
10ms to all computers. This uses the same cooldown principle, meaning we
keep to an average of 10ms, even if we go over budget.
2019-03-26 11:21:16 +00:00
SquidDev
d0bf9e9cd7 Fix config reloading not working as expected
We were not updating the property instances, so we never actually used
the new values. This changes the syncing method to just copy values from
the new config file, meaning comments and structure are preserved from
the old one.

Note, we cannot just call Config.load(File) again, as the defaults are
no longer accurate.
2019-03-26 11:06:33 +00:00
SquidDev
7a7951ae68 Keep track of the current input state on the server
- We send special packets for key and mouse events, which are then
   processed by the container's InputState.
 - InputState keeps track of currently held keys and mouse buttons.
 - When closing the container, we queue key_up/mouse_up events for any
   pending buttons.
2019-03-24 21:58:13 +00:00
SquidDev
bd28955c8e Fix ComputerThread not updating the minimumVirtualRuntime
We attempted to simplify this 0bfb7049b0,
but that change now means that minimumVirtualRuntime is not updated. As
a result, new tasks will have a runtime of 0 when the queue is empty.
2019-03-24 18:13:00 +00:00
SquidDev
e46f09a939 Several recipe improvements
- Some performance improvements to JEI recipe resolver
   - Use a shared map for upgrade items, meaning we only need one map
     lookup.
   - Cache the basic upgrade recipes.
 - Use the MC version within project rather than version name.
2019-03-19 11:59:23 +00:00
daelvn
71b1f8138d Localize ComputerCraft for es_ES
Español de España (Castellano)
2019-03-19 09:50:21 +00:00
Wilma456 (Jakob0815)
1d82a1c98c Update German translation (#145) 2019-03-19 09:43:32 +00:00
Wilma456 (Jakob0815)
b5f60f3f11 Correct typo within en_us.lang (#144) 2019-03-16 17:00:26 +00:00
SquidDev
259665d9f1 Add a more strict form of IPocketAccess.getEntity
Before IPocketAccess.getEntity would return the entity which last held
fthis computer, even if not holding it any more. As
ba823bae13 describes, this caused
pocket.equip/pocket.unequip to dupe items.

We move the validation from the PocketAPI into the main IPocketAccess
implementation, to ensure this issue does not occur elsewhere. Note, we
require a separate method, as this is no longer thread-safe.

We also now return ok, err instead of throwing an exception, in order to
be consistent with the turtle functions. See dan200/ComputerCraft#328.
2019-03-16 11:18:03 +00:00
Iunius118
ba823bae13 Fix Pocket API working outside of player inventory
This makes Pocket API not equip/unequip upgrades when the pocket
computer is outside of the player inventory (e.g. dragging,
dropped, placed in a chest).
2019-03-16 11:08:44 +00:00
SquidDev
1290a4402c Add a tool to verify language files are well formed
I'm not going to pretend this is a beautiful script, but it's good
enough for basic validation of language files.
2019-03-16 11:04:37 +00:00
absolument
379076a5e2 Localize ComputerCraft for fr_fr
Following #488
Here is my translation in french fr_fr
2019-03-16 11:00:41 +00:00
SquidDev
d12bdf50d8 Remove most instances of non-translatable strings
Oh goodness, this is going to painful to update to 1.13.

We now translate:
 - Computer/Disk ID tooltips
 - /computercraft descriptions, synopsises and usages. The last of these
   may not always be translated when in SMP, as it is sometimes done on
   the server, but the alternative would be more complex than I'm happy
   with.
 - Tracking field names. Might be worth adding descriptions too in the
   future.

Also cleanup a couple of other translation keys, so they're more
consistent with Minecraft.

Closes #141
2019-03-16 10:26:40 +00:00
SquidDev
cbfd5aeeee Use Minecraft's "can use command blocks" check
Just means we're a little more consistent, and hopefully can remove
canPlayerUseCommands in the future, once Plethora stops using it.
2019-03-16 01:55:38 +00:00
SquidDev
41429bdc0b Improve our JEI integration a little bit
- Turtle and pocket computers provide a "creator mod id" based on their
   upgrade(s).
   We track which mod was active when the upgrade was registered, and
   use that to determine the owner. Technically we could use the
   RegistryLocation ID, but this is not always correct (such as
   Plethora's vanilla modules).
 - We show all upgraded turtles/pocket computers in JEI now, rather than
   just CC ones.
 - We provide a custom IRecipeRegistryPlugin for upgrades, which
   provides custom usage/recipes for any upgrade or upgraded item. We
   also hide our generated turtle/pocket computer recipes in order to
   prevent duplicates.
2019-03-16 01:51:12 +00:00
SquidDev
54b9966feb Make upgrade crafting even more lenient
This now allows items with empty tags to equal those with no tag.
2019-03-16 01:51:00 +00:00
SquidDev
105c66127c Automatically generate impostor recipes
Previously we would register the recipes within our code, but the
advancements were written manually. This now generates JSON files for
both the advancement and recipe.

While this does mean we're shipping even more JSON, we'll need to do
this for 1.13 anyway, and means our advancements are guaranteed to be
consistent.

On a side note, a couple of other changes:
 - Turtle upgrades are now mounted on the right in the creative
   menu/fake recipes. This means the upgrade is now clearly visible in
   the inventory.
 - We no longer generate legacy turtle items at all: we'll always
   construct turtle_expanded.
 - Several peripheral items are no longer registered as having sub-types
   (namely advanced and full-block modems).
 - We only have one disk advancement now, which unlocks all 16 recipes.
 - We have removed the disk conversion recipes - these can be
   exposed through JEI if needed.
2019-03-16 00:15:31 +00:00
SquidDev
765ad0bd3f Some basic integration with MCMP
This allows wireless modems (advanced and normal) to be used in
multiparts. There's a very limited set of uses for this (mostly allows
using Chisel and Bits with them), but it's very simple to do.

I'd like to look into MCMP support for wired modems/cables in the
future, but this will be somewhat harder due to their pre-existing
multiblock structure.

Similarly, might be fun to look into CBMP compatibility.
2019-03-14 22:14:47 +00:00
Linus Ramneborg
dd05478483 Localize for Swedish (#139) 2019-03-14 22:14:13 +00:00
hydraz
5d028dea39 Add pt_BR lang file 2019-03-14 17:15:34 +00:00
SquidDev
629c51d260 Fix language silliness 2019-03-14 17:15:05 +00:00
Alessandro
9ea57961af Added Italian language (#138) 2019-03-14 16:55:38 +00:00
Luca
07b9b1c9c7 os.time() and os.day() join the "Finally Case-Insensitive Party" 2019-03-13 15:42:39 +00:00
SquidDev
5b942ff9c1 Some changes to Lua machines and string loading
- Share the ILuaContext across all method calls, as well as shifting it
   into an anonymous class.
 - Move the load/loadstring prefixing into bios.lua
 - Be less militant in prefixing chunk names:
   - load will no longer do any auto-prefixing.
   - loadstring will not prefix when there no chunk name is supplied.
     Before we would do `"=" .. supplied_program`, which made no sense.
2019-03-10 12:24:55 +00:00
SquidDev
7b5a918941 Improve AddressPredicate error messages a little
See #134.
2019-03-10 11:22:11 +00:00
SquidDev
47721bf76b Allow running pastebin with the URL
For instance, `pastebin run https://pastebin.com/LYAxmSby` will now
extract the code and download appropriately. Also add an error message
when we received something which is not a valid pastebin code.

See #134.
2019-03-10 11:11:49 +00:00
SquidDev
35ce0974cd Fix NPE when checking URLs
If the host was null due to a malformed URL, we'd try to verify that it
was allowed, throwing an NPE.

Fixes #135
2019-03-10 10:45:30 +00:00
SquidDev
52e1906d42 Add a basic test framework for CraftOS
This runs tests on CraftOS using a tiny test runner that I originally
knocked up for LuaDash. It can be run both from JUnit (so IDEA and
Gradle) and in-game in the shell, so is pretty accessible to work with.

I also add a very basic POC test for the io library. I'd like to flesh
this out soon enough to contain most of the things from the original io
test.
2019-03-10 10:45:25 +00:00
SquidDev
eaf24a3ceb Update to JUnit 5
Also display test results within the Gradle build
2019-03-10 09:40:06 +00:00
SquidDev
62760e371e Add a section on how to depend on CC:T
It's not immediatly obvious where our maven repository is.
2019-03-04 22:59:38 +00:00
SquidDev
e154e11186 Select the initial multishell tab when starting up
Before it was not actually selected until the task had yielded for the
first time. If a computer did not yield (or took a while to do so),
nothing would actually show up.
2019-03-04 16:37:08 +00:00
SquidDev
72d079ef61 Merge pull request #119 from SquidDev-CC/feature/computer-thread-schedule
- CobaltLuaMachine/ComputerExecutor can now be paused - this suspends 
   the machine via a debug hook. When doing work again, we resume the 
   machine, rather than starting a new task.
 - TimeoutState keeps track of how long the current execution of this task
   has gone on for, when its deadline is, and the cumulative execution time of
   this task.
 - ComputerThread now uses a CFS based scheduler in order to determine which
   computer to next run.
2019-03-04 15:46:28 +00:00
SquidDev
0bfb7049b0 Document everything, and several further improvements
- Only update all runtimes and the minimum runtime when queuing new
   exectors. We only need to update the current executor's runtime.
 - Fix overflows when comparing times within TimeoutState.
   System.nanotime() may (though probably won't) return negative values.
 - Hopefully explain how the scheduler works a little bit.
2019-03-04 10:22:17 +00:00
SquidDev
f7cb526793 Attempt to fix race condition in ComputerThread
- Runners would set their active executor before starting resetting the
   time, meaning it would be judged as running and terminated.
 - Similarly, the cumulative time start was reset to 0, meaning the
   computer had been judged to run for an impossibly long time.
 - If a computer hit the terminate threshold, but not the hard abort
   one, then we'd print the stack trace of the terminated thread - we
   now do it before interrupting.

There's still race conditions here when terminating a computer, but
hopefully these changes will mean they never occur under normal
operations (only when a computer has run for far too long).
2019-03-04 09:22:14 +00:00
SquidDev
e34e833d3d Small changes to ComputerThread
- Fix the timeout error message displaying utter rot.
 - Don't resize the runner array. We don't handle this correctly, so
   we shouldn't handle it at all.
 - Increment virtualRuntime after a task has executed.
2019-03-02 09:16:25 +00:00
SquidDev
a125a19728 Implement a CFS based scheduler
- The computer queue is a priority queue sorted by "virtual runtime".
 - Virtual runtime is based on the time this task has executed, divided
   by the number of pending tasks.
 - We try to execute every task within a given period. Each computer is
   allocated a fair share of that period, depending how many tasks are
   in the queue. Once a computer has used more than that period, the
   computer is paused and the next one resumed.
2019-02-28 17:23:09 +00:00
SquidDev
b3e6a53868 Allow pausing Lua machines
TimeoutState now introduces a TIMESLICE, which is the maximum period of
time a computer can run before we will look into pausing it.

When we have executed a task for more than this period, and if there are
other computers waiting to execute work, then we will suspend the
machine.

Suspending the machine sets a flag on the ComputerExecutor, and pauses
the "cumulative" time - the time spent handling this particular event.
When resuming the machine, we restart our timer and resume the machine.
2019-02-28 16:49:06 +00:00
SquidDev
218f8e53bb Further improvements to computer execution
Oh goodness, when will it end?

 - Computer errors are shown in red.

 - Lua machine operations provide whether they succeeded, and an
   optional error message (reason bios failed to load, timeout error,
   another Lua error), which is then shown to the user.

 - Clear the Cobalt "thrown soft abort" flag when resuming, rather than
   every n instructions.

 - Computers will clear their "should start" flag once the time has
   expired, irrespective of whether it turned on or not. Before
   computers would immediately restart after shutting down if the flag
   had been set much earlier.

Errors within the Lua machine are displayed in a more friendly
2019-02-28 15:44:43 +00:00
SquidDev
d02575528b Fix leaking file descriptors when closing
When closing a BufferedWriter, we close the underlying writer. As we're
using channels, this is an instance of sun.nio.cs.StreamEncoder. This
will attempt to flush the pending character.

However, if throwing an exception within .write errors, the flush will
fail and so the underlying stream is not closed. This was causing us to
leak file descriptors.

We fix this by introducing ChannelWrappers - this holds the wrapper
object (say, a BufferedWriter) and underlying channel. When closed, we
dispose of the wrapper, and then the channel. You could think of this as
doing a nested try-with-resources, rather than a single one.

Note, this is not related to JDK-6378948 - this occurs in the underlying
stream encoder instead.
2019-02-28 11:24:12 +00:00
SquidDev
c78adb2cdc Several improvements to the computer thread rework
- TimeoutState uses nanoseconds rather than milliseconds. While this is
   slightly less efficient on Windows, it's a) not the bottleneck of Lua
   execution and b) we need a monotonic counter, otherwise we could
   fail to terminate computers if the time changes.
 - Add an exception handler to all threads.
 - Document several classes a little better - I'm not sure how useful
   all of these are, but _hopefully_ it'll make the internals a little
   more accessible.
2019-02-27 20:56:45 +00:00
SquidDev
3e28f79ce9 Shutdown computers in /computercraft shutdown
Unloading them now means they'll never be turned on again, which is a
little unideal.
2019-02-27 13:49:07 +00:00
SquidDev
67af7a698b Migrate the computer tasks into a separate thread
- Move state management (turnOn, shutdown, etc...) event handling and
   the command queue into a ComputerExecutor

 - This means the computer thread now just handles running "work" on
   computer executors, rather than managing a separate command queue +
   requeuing it.
2019-02-26 13:50:09 +00:00
SquidDev
06e76f9b15 Rewrite ComputerThread and the timeout system
- Instead of setting soft/hard timeouts on the ILuaMachine, we instead
   provide it with a TimeoutState instance. This holds the current abort
   flags, which can then be polled within debug hooks.

   This means the Lua machine has to do less state management, but also
   allows a more flexible implementation of aborts.

 - Soft aborts are now handled by the TimeoutState - we track when the
   task was started, and now only need to check we're more than 7s since
   then.

   Note, these timers work with millisecond granularity, rather than
   nano, as this invokes substantially less overhead.

 - Instead of having n runners being observed with n managers, we now
   have n runners and 1 manager (or Monitor).

   The runners are now responsible for pulling work from the queue. When
   the start to execute a task, they set the time execution commenced.
   The monitor then just checks each runner every 0.1s and handles hard
   aborts (or killing the thread if need be).
2019-02-26 13:46:10 +00:00
SquidDev
6d383d005c A couple of minor tweaks
- Rename unload -> close to be a little more consistent
 - Make pollAndResetChanged be atomic, so we don't need to aquire a lock
 - Get the computer queue from the task owner, rather than a separate
   argument.
2019-02-26 12:43:45 +00:00
SquidDev
c373583723 Add a test which boots a computer and runs forever
Ideally we'd add a couple more tests in the future, but this'll do for
now.

The bootstrap class is largely yoinked from CCTweaks-Lua, so is a tad
ugly. It works though.
2019-02-26 08:44:17 +00:00
SquidDev
f1d10809d5 Make commands.collapseArgs a little more sane
We now generate a table and concatinate the elements together. This has
several benefits:
 - We no longer emit emit trailing spaces, which caused issues on 1.13's
   command system.
 - We no longer need the error level variable, nor have the weird
   recursion system - it's just easier to understand.
2019-02-26 08:40:48 +00:00
SquidDev
474f571798 Attach peripherals directly rather than deferring
Prior to this change we would schedule a new task which attached
peripherals on the ComputerThread on the empty task queue. This had a
couple of issues:
 - Slow running tasks on the computer thread could result in delays in
   peripherals being attached (technically, though rarely seen in
   practice).
 - Now that the ComputerThread runs tasks at once, there was a race
   condition in computers being turned on/off and peripherals being
   attached/detached.

Note, while the documentation said that peripherals would only be
(at|de)tached on the computer thread, wired modems would attach on the
server thread, so this was not the case in practice.

One should be aware that peripherals are still detached on the
computer thread, most notably when turning a computer on/off.

This is almost definitely going to break some less well-behaved mods,
and possible some of the well behaved ones. I've tested this on SC, so
it definitely works fine with Computronics and Plethora.
2019-02-25 19:11:35 +00:00
SquidDev
fb9c125ab8 Update Cobalt version for latest bugfixes/changes
- Fix load not unwinding stack
 - Allow transferring control between coroutines when unwinding is
   disabled

Fixes #128
2019-02-25 14:18:45 +00:00
SquidDev
162fb37421 Handle Pastebin spam protection and add a cache buster (#127) 2019-02-24 20:06:02 +00:00
Drew Lemmy
d953f031f0 Remove debugging line 😬 2019-02-24 20:00:26 +00:00
Drew Lemmy
7fde89ad95 Use stderr for pastebin errors, and a prettier cache buster 2019-02-24 19:59:10 +00:00
Drew Lemmy
bd04a93ffb Handle pastebin spam protection and add a cache buster 2019-02-24 13:47:09 +00:00
SquidDev
e2bfaafe28 Bump version for colour fix 2019-02-24 08:20:22 +00:00
SquidDev
1fb3d16b89 Fix colours.*RGB methods working with 8 bit values
They should have been using 0-1s instead. I'm a moron for not noting
this earlier, and not testing this.
2019-02-23 23:20:46 +00:00
SquidDev
35645b3d93 Add back a couple of methods for CCEmuX compat 2019-02-23 12:46:09 +00:00
SquidDev
a4cd1fe77d Stop releasing betas by default
Things just got serious I guess??
2019-02-23 10:35:15 +00:00
Wilma456 (Jakob0815)
4145914024 Make Multishell Scrollable (#123)
You can now Scroll through the program list, if the list bigger than your
screen.
2019-02-21 16:00:13 +00:00
SquidDev
6bd11a5e4a Fix the other instance of the neighbour deprecation warning 2019-02-20 18:37:22 +00:00
SquidDev
46fa798797 Several minor improvements
- Restrict what items can be inserted into printers. They're now closer
   to brewing stands or furnaces: nothing can go in the output slot,
   only ink in the ink slot, and only paper in the paper slot.
 - Fix build.gradle using the wrong version
 - Trim the width of tables to fit when displaying on the client. Closes
   #45. Note, our solution isn't perfect, as it will wordwrap too, but
   it's adaquate for now.
2019-02-20 09:48:16 +00:00
SquidDev
70a226207e Update README and versioning (#121)
- Reword elements of the README, mostly changing the elements about
   vanilla ComputerCraft.
 - Change versioning scheme: we'll now do 1.x.y, with 1.81.0 being the
   next version.
 - Include MC version in the file name
 - Stop bundling javadoc with the jar. We'll look into hosting this on
   squiddev.cc if really needed.
 - Remove the LuaJ license from the root - we no longer bundle the
   sources, so it's not needed here.

I realise this change looks a little dodgey on its own, so see #113 for
the full rationale.
2019-02-19 14:49:13 +00:00
SquidDev
257a35f3ed Merge pull request #120 from SquidDev-CC/feature/palette-improvements
Minor palette improvements
2019-02-19 10:59:35 +00:00
Lignum
af01b9514b Split colours.rgb8 into colours.packRGB and colours.unpackRGB 2019-02-19 09:51:01 +00:00
Lignum
070fd1f2ff Add term.nativePaletteColo(u)r 2019-02-19 09:50:57 +00:00
SquidDev
fb59da2b06 Update GitHub templates, removing CC repo links
See #113
2019-02-18 23:35:50 +00:00
SquidDev
11e4d0de82 Fix turtle peripherals becoming desynced
When a turtle was unloaded but not actually disposed of, the
m_peripheral map hangs around. As a result, when creating a new
ServerComputer, the peripherals aren't considered changed and so they're
never attached.

Fixes #50.

Also fix that blumin' deprecated method which has been around for a wee
while now.
2019-02-18 23:28:51 +00:00
SquidDev
e46ab1e267 Revert some image optimisations 2019-02-18 22:58:39 +00:00
SquidDev
d6e0f368df Handle managing computer inputs/outputs separatly
The Computer class currently has several resposiblities such as storing
id/label, managing redstone/peirpherals, handling management of the
computer (on/off/events) and updating the output.

In order to simplify this a little bit, we move our IAPIEnvironment
implementation into a separate file, and store all "world state"
(redstone + peripherals) in there. While we still need to have some
level of updating them within the main Computer instance, it's
substantially simpler.
2019-02-17 19:48:52 +00:00
SquidDev
9f2884bc0f Several minor improvments to websockets
- Fire close events instead of failure when open websockets error.
 - Handle ping events. I thought I was doing this already, but this
   requires a WebsocketProtocolHandler. Fixes #118
2019-02-17 19:36:18 +00:00
SquidDev
18d468e887 Fix building from a fresh setup
We were attempting to resolve the Forge jars before they had been
generated, which meant the build failed.
2019-02-16 16:01:47 +00:00
SquidDev
63f6735bb8 Attempt to reduce jar size a little
- Run optipng on all our images. This has very little effect on most of
   them (as they're all so small anyway), but has resulted in a 50%
   reduction in some cases.
 - Run Proguard on our shadowed dependencies (Cobalt).
 - Minify our JSON files, stripping all whitespace. This is mostly
   useful for FML's annotation cache, as that's a massive file, but
   still a semi-useful optimisation to make.

This has helped reduce the jar by about 110kb, which isn't much but
still feels somewhat worth it.
2019-02-14 10:53:18 +00:00
SquidDev
ab6f0ccd16 Fix advanced modems not actually being advanced
We were constructing the peripheral before the advanced property had
been set, thus it was always false. Yay for Java.

Closes #111
2019-02-12 18:11:04 +00:00
SquidDev
ae0f093e73 Strip \r from .readLine on binary handles
Note, this is technically inconsistent with the spec. However, we'll use
this method for now in order to remain backwards compatible.

Fixes #109.
2019-02-11 16:58:43 +00:00
SquidDev
e5f988e3fe Fix missing advanced turtle model when rendering
I'm not even sure how I missed this when testing.
2019-02-11 16:38:33 +00:00
SquidDev
12e82afad2 Bump Cobalt version to enable single-threading
The latest version of Cobalt has several major changes, which I'm
looking forward to taking advantage of in the coming months:

 - The Lua interpreter has been split up from the actual LuaClosure
   instance. It now runs multiple functions within one loop, handling
   pushing/popping and resuming method calls correctly.

   This means we have a theoretically infinite call depth, as we're no
   longer bounded by Java's stack size. In reality, this is limited to
   32767 (Short.MAX_VALUE), as that's a mostly equivalent to the limits
   PUC Lua exposes.

 - The stack is no longer unwound in the event of errors. This both
   simplifies error handling (not that CC:T needs to care about that)
   but also means one can call debug.traceback on a now-dead coroutine
   (which is more useful for debugging than using xpcall).

 - Most significantly, coroutines are no longer each run on a dedicated
   thread. Instead, yielding or resuming throws an exception to unwind
   the Java stack and switches to a different coroutine.

   In order to preserve compatability with CC's assumption about LuaJ's
   threading model (namely that yielding blocks the thread), we also
   provide a yieldBlock method (which CC:T consumes). This suspends the
   current thread and switches execution to a new thread (see
   SquidDev/Cobalt@b5ddf164f1 for more
   details). While this does mean we need to use more than 1 thread,
   it's still /substantially/ less than would otherwise be needed.

We've been running these changes on SwitchCraft for a few days now and
haven't seen any issues. One nice thing to observe is that the number of
CC thread has gone down from ~1.9k to ~100 (of those, ~70 are dedicated
to running coroutines). Similarly, the server has gone from generating
~15k threads over its lifetime, to ~3k. While this is still a lot, it's
a substantial improvement.
2019-02-10 22:02:30 +00:00
SquidDev
6c2db93cbd Register item colour handlers on the event instead
Another step on my misguided quest to get rid of proxies
2019-02-10 09:55:06 +00:00
SquidDev
d5edbe700b Load turtle item models using a model loader
This is far more elegant than our weird method of baking things and
manually inserting them into the model map. Also means we no longer need
the whole turtle_dynamic thing.
2019-02-10 09:45:15 +00:00
SquidDev
86ad43c3ab Fix peripheral direction not being set
We moved the direction call within the if block, but never actally
updated the condition! I'm on a roll of stupid bug fixes today, which
really isn't a good sign.
2019-02-07 23:07:49 +00:00
SquidDev
f450c0156b Recomment out a global
It's actually rather worrying this was exposed, you could cause some
serious issues with it.
2019-02-07 20:22:00 +00:00
SquidDev
8abcfcb4ac Track turtle commands as server tasks
They're basically an alternative version of issueMainThreadTask anyway.
2019-01-30 20:43:08 +00:00
SquidDev
f3cace1d03 Allow building without a git repository
Closes #102
2019-01-28 14:05:53 +00:00
SquidDev
e1e5e898ab Make monitors use a concurrent map instead of a synchronized
We didn't lock when iterating on the main-thread, so it wasn't actually
thread-safe anyway!
2019-01-25 22:59:01 +00:00
SquidDev
3aa3852ff6 Some further improvements to BlockGeneric
- Only have computers implement custom block drop logic: everything
   else only drops in creative mode.
 - Fix redstone inputs not being received correctly. Introduced in
   8b86a954ee, yes I'm a silly billy.
 - Only update the neighbour which changed.
2019-01-25 22:03:44 +00:00
SquidDev
709a6329c7 Fix all wireless modem blocks being advanced 2019-01-25 00:12:49 +00:00
SquidDev
c9f05a2939 Make require a little more consistent with Lua 5.1
- Error messages are indented correctly
 - The module's name is passed as the first argument to modules
 - Make error messages match Lua's
2019-01-23 18:50:17 +00:00
Devilholk
e41377f862 Handle connection errors on websockets 2019-01-22 11:11:25 +00:00
SquidDev
d173787a94 Another backwards compat change
Plethora only implements getPos on older versions, so we need to stub
out both.
2019-01-21 17:36:25 +00:00
SquidDev
d5aea26f3a Bump version
It's pretty soon after the previous release (10 days!) but there's a
couple of important bug fixes and some nice improvements.
2019-01-21 11:02:29 +00:00
SquidDev
2681e578c4 Merge pull request #101 from SquidDev-CC/feature/no-ticking
Make several tile entities non-ticking, hopefully reducing
server load.
2019-01-21 08:29:42 +00:00
SquidDev
1f498dcc73 Backwards compat patch for Plethora
Ughghgghghr.
2019-01-20 16:16:02 +00:00
SquidDev
83b01d35eb Make monitors non-ticking
- Convert terminals from a polling-based system to a more event-driven
   one: they now accept an onChanged callback, which marks the parent as
   dirty.
 - Schedule ticks when monitors are marked as dirty.
 - Add several missing @Overrides. This has nothing to do with the rest
   of the changes, but I'm bad at good git practice.
2019-01-20 15:39:11 +00:00
SquidDev
8a7e651c99 Several miscellaneous changes
- Merge BlockPeripheralBase and BlockPeripheral, as no other classes
   extended the former.
 - Make BlockPeripheral use ITilePeripheral instead of
   TilePeripheralBase. This allows us to use other, non-ticking tiles
   instead.
 - Convert advanced and normal modems to extend from a generic
   TileWirelessModemBase class, and thus neither now tick.
2019-01-20 14:06:41 +00:00
SquidDev
80a5759bae Make advanced modems non-ticking
- Move getPeripheralType and getLabel from IPeripheralTile to
   TilePeripheralBase. These were mostly constant on all other tiles, so
   were rather redundant.
 - Make TileAdvancedModem extend TileGeneric, and be non-ticking (using
   similar logic to all other blocks).
2019-01-20 09:34:15 +00:00
SquidDev
e8a4fbb4e3 Make TileCable non-ticking
- Move updateTick onto BlockGeneric/TileGeneric instead of the full
   wired modem, as it is used by several tiles now.
 - Make *Cable extend from *Generic, and schedule ticks instead of
   running every tick.
2019-01-19 22:25:38 +00:00
SquidDev
0ce67afcc1 Be less strict in comparing upgrade crafting items
We currently generate the crafting item once when the upgrade is first
created, and cache it for the duration of the game. As the item never
changes throughout the game, and constructing a stack is a little
expensive (we need to fire an event, etc...), the caching is worth
having.

However, some mods may register capabilities after we've constructed our
ItemStack. This means the capability will be present on other items but
not ours, meaning they are not considered equivalent, and thus the item
cannot be equipped.

In order to avoid this, we use compare items using their share-tag, like
Forge's IngredientNBT. This means the items must still be "mostly" the
same (same enchantements, etc...), but allow differing capabilities.

See NillerMedDild/Enigmatica2Expert#655 for the original bug report -
in this case, Astral Sourcery was registering the capability in init,
but we construct upgrades just before then.
2019-01-19 21:57:21 +00:00
SquidDev
a8dad23fa3 Begin investigations into reducing ticking of TEs
- Move IDirectionalTile constraint from IPeripheralTile to
   TilePeripheralBase.
 - Make *WiredModemFull no longer inherit from *PeripheralBase. While
   there is still some shared logic (namely in the syncing of "anim"),
   it's largely fine as we don't store label or direction in NBT.
 - Add a TickScheduler. This is a thread-safe version of
   World.scheduleUpdate. We simply build a set of all TEs, and schedule
   them to be updated the next tick.
 - Make ModemState receive an "onChanged" listener, which is fired
   whenever the modem changes.
 - Make WiredModemFull no longer tick, instead scheduling updates when
   it is first loaded and whenever the modem changes.
2019-01-19 10:16:41 +00:00
SquidDev
443e0f8f76 Remove FileSystemMount and rewrite JarMount
FileSystemMount was originally added to allow using ReadableByteChannels
instead of InputStreams. However, as zip files do not allow seeking,
there is no benefit of using them over the original JarMount (which we
need to preserve for backwards compatibility).

Instead of maintaining two near-identical mounts, we remove the
FileSystemMount and rewrite the JarMount implementation with several
improvements:

 - Rewrite the jar scanning algorithm to be closer to 1.13+'s data pack
   mount. This means we no longer require the jar file to have
   directories before the file (though this was not a problem in
   practice).
 - Add all JarMounts to a ReferenceQueue, closing up the ZipFile when
   they have been garbage collected (fixes #100).
 - Cache the contents of all files for 60 seconds (with some constraints
   on size). This allows us to seek on ROM files too (assuming they are
   small), by reading the whole thing into memory.
   The cache is shared across all mounts, and has a 64MiB limit, and
   thus should not have an adverse impact on memory.
2019-01-16 17:25:46 +00:00
SquidDev
a838595e1e Derive upgrade adjectives from its ID
This is done in 1.13+ for items and blocks, so we might as well do it
for upgrades now. Note we can't do it for ender pocket modems, as the
upgrade ID is spelled incorrectly there.
2019-01-14 10:42:13 +00:00
SquidDev
61daab910e Simplify placement logic of various blocks
- For those where placement is stored in the metadata (computers),
   don't also set it in onBlockPlacedBy.
 - Remove .getDefaultState(int, EnumFacing) override, as this means we
   have more control over what is passed to us (namely, placer's
   direction too).
2019-01-14 10:27:19 +00:00
SquidDev
7fd19c43e9 Try to hide CommandCopy from most completions.
"/computercraf" auto-completes to "/computercraft_copy" instead of
"/computercraft", which is rather annoying, as the former is not meant
to be used normally.
2019-01-14 10:10:52 +00:00
SquidDev
ce0685c31f Move our message model to be closer to Forge's
It's rather embarassing that it's been restructured _again_, but I think
this is a nice middle-ground. The previous implementation was written
mostly for Fabric, which doesn't always map perfectly to Forge.

 - Move the message identifier into the registration phrase. It's not
   really a property of the message itself, rather a property of the
   registry, so better suited there.

 - Move message handling into the message itself. Honestly, it was just
   ending up being rather messy mixing the logic in two places.

   This also means we can drop some proxy methods, as it's easier to
   have conditionally loaded methods.

 - Move network registry into a dedicated class, as that's what we're
   doing for everything else.
2019-01-14 10:09:22 +00:00
SquidDev
e33f852baa Store references to the registered items
This means we can avoid several rather ugly instances of getItemBlock
and a cast. We also derive the ItemBlock's registered name from the
block's name, which makes the register a little less ugly.
2019-01-12 19:01:32 +00:00
SquidDev
227d5e9e69 Fix cables not rendering the breaking steps
The fact that it's taken this long for anyone to notice this didn't work
is rather embarassing.
2019-01-12 18:35:43 +00:00
SquidDev
1c648850ab Even more proxy pruning
- Move the "world directory" getter out of the proxy - we can just use
   Forge's code here.
 - Remove the server proxies, as both were empty. We don't tend to
   register any dedicated-server specific code, so I think we can leave
   them out.
2019-01-12 18:23:22 +00:00
SquidDev
63691707fc Move registration methods into a separate class
- All "named" entries (blocks, items, recipes, TEs and pocket/turtle
   upgrades) are registeredin one place.
 - Most client side models/textures are registered in ClientRegistry -
   we can't do item colours or TEs for now, as these aren't event based.
 - A little cleanup to how we handle ItemPocketComputer models.
2019-01-12 17:51:26 +00:00
SquidDev
5d97b9c8f3 Utilise @Mod.EventBusSubscriber a little more
This offers several advantages

 - Less registration code: the subscribers are reigstered automatically,
   and we don't need to worry about sided-proxies.
 - We no longer have so many .instance() calls.
2019-01-12 16:27:40 +00:00
SquidDev
77666d7399 Some more minor cleanups
- Move SpeakerPeripheral's TileSpeaker functionality to a sub-class.
 - Use Vec3d instead of BlockPos for speaker's positions.
 - Use WorldUtil.dropItemStack to spawn in items.
 - Remove redundant lock on ModemPeripheral.
2019-01-12 15:43:18 +00:00
1778 changed files with 61679 additions and 49038 deletions

View File

@@ -1,16 +1,15 @@
---
name: Bug report
about: Report some misbehaviour in the mod
labels: bug
---
<!--
## Before reporting
- Search for the bug both here and [on the ComputerCraft issues page](https://github.com/dan200/ComputerCraft/issues?utf8=%E2%9C%93&q=is%3Aissue+)
- If possible, try to reproduce on vanilla ComputerCraft. If it still occurs, [report on the ComputerCraft repo](https://github.com/dan200/ComputerCraft/issues/new) instead.
- Search for the bug on the issue tracker. Make sure to look at closed issues too!
-->
## Useful information to include:
- Minecraft version
- CC: Tweaked version
- Detailed reproduction steps!** Sometimes I can spot a bug pretty easily, but often it's much more obscure. Anything you can give which will help reproduce it means it'll get fixed quicker.
- CC: Restitched version
- 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

@@ -1,15 +1,14 @@
---
name: Feature request
about: Suggest an idea or improvement
labels: enhancement
---
<!--
## Before reporting
- Search for the suggestion both here and [on the ComputerCraft issues page](https://github.com/dan200/ComputerCraft/issues?utf8=%E2%9C%93&q=is%3Aissue+). It's possible someone's suggested it before!
- Unless something is specific to CC:Tweaked, try to [suggest them on the ComputerCraft repo](https://github.com/dan200/ComputerCraft/issues/new). There's a lot more people watching it, so it allows the wider community to contribute.
- Search for the suggestion here. It's possible someone's suggested it before!
-->
## Useful information to include:
- Explanation of how the feature/change chould work.
- Some rationale/use case for a feature. I'd like to keep CC:T as minimal
- Explanation of how the feature/change should work.
- Some rationale/use case for a feature. My general approach to designing new features is to ask yourself "what issue are we trying to solve" and _then_ "is this the best way to solve this issue?".

View File

@@ -0,0 +1,12 @@
---
name: Peripheral Shoutout
about: Made a Peripheral mod for CC:R? Let us know so we can give it a shoutout
labels: peripheralShoutout
---
## What to include?
- Link to the mod's Icon
- Link to the mod
- Mod Name
- Basic description of the mod
- Link to CC:R Peripheral Documentation for the mod

View File

@@ -1,9 +1,3 @@
<!--
Unless this feature is specific to CC:Tweaked, try to [target the original ComputerCraft repo](https://github.com/dan200/ComputerCraft/) instead. There's a lot more people watching it, so it allows the wider community to contribute.
-->
## Useful information to include:
- Brief explanation of the changes you've made.
- Rationale of why this change has been made/reasoning behind it.
The more information you can provide, the easier it is to review something now _and_ to see why a change was made, when the code needs updating in the future.
## A quick checklist
- If there's a existing issue, please link to it. If not, provide fill out the same information you would in a normal issue - reproduction steps for bugs, rationale for use-case.
- If you're working on CraftOS, try to write a few test cases so we can ensure everything continues to work in the future. Tests live in `src/test/resources/test-rom/spec` and can be run with `./gradlew check`.

35
.github/workflows/main-ci.yml vendored Normal file
View File

@@ -0,0 +1,35 @@
name: Build
on: [push, pull_request]
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Checkout submodules
run: git submodule update --init --recursive
- name: Set up Java 8
uses: actions/setup-java@v1
with:
java-version: 8
- name: Cache gradle dependencies
uses: actions/cache@v2
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('gradle.properties') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Build with Gradle
run: ./gradlew build --no-daemon || ./gradlew build --no-daemon
- name: Upload Jar
uses: actions/upload-artifact@v1
with:
name: cc-restiched
path: build/libs

6
.gitignore vendored
View File

@@ -9,9 +9,15 @@
/run-*
/test-files
# Autogenerated by IDE
/bin
/.settings
.classpath
*.ipr
*.iws
*.iml
.idea
.gradle
*.DS_Store
.project

3
.gitmodules vendored Normal file
View File

@@ -0,0 +1,3 @@
[submodule "src/main/resources/resourcepacks/overhaul"]
path = src/main/resources/resourcepacks/overhaul
url = https://github.com/3prm3/cc-pack

View File

@@ -1,14 +0,0 @@
language: java
script: ./gradlew build --no-daemon
before_cache:
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
- rm -fr $HOME/.gradle/caches/*/plugin-resolution/
cache:
directories:
- $HOME/.gradle/caches/
- $HOME/.gradle/wrapper/s
jdk:
- oraclejdk8

3
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,3 @@
{
"java.configuration.updateBuildConfiguration": "automatic"
}

View File

@@ -1,19 +0,0 @@
Copyright (c) 2007 LuaJ. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -1,49 +1,68 @@
# ![CC: Tweaked](logo.png)
[![Build Status](https://travis-ci.org/SquidDev-CC/CC-Tweaked.svg?branch=master)](https://travis-ci.org/SquidDev-CC/CC-Tweaked)
# CC:Restitched Patchwork
# CC:R Version VS CC:T Version
CC:R Strives to maintaim perfect pairity with CC:R, however in some cases this is not possible, or atleast, not yet, so just because you might be on CC:R 1.96.6, doesnt mean you are on CC:T 1.96.6.
CC: Tweaked is a fork of ComputerCraft which aims to provide earlier access to the more experimental and in-development
features of the mod. For a more stable experience, I recommend checking out the
[original mod](https://github.com/dan200/ComputerCraft).
<img src="logo.png" alt="CC: Restitched" width="100%"/>
*it works and runs-ish*
[![Current build status](https://github.com/Merith-TK/cc-restitched/workflows/Build/badge.svg)](https://github.com/Merith-TK/cc-restitched/actions "Current build status") [![Download CC: Restitched on CurseForge](http://cf.way2muchnoise.eu/title/cc-restitched.svg)](https://www.curseforge.com/minecraft/mc-mods/cc-restitched-updated "Download CC: Restitched on CurseForge")
## What?
CC: Tweaked (or CC:T for short) does not aim to create a competing fork of ComputerCraft, nor am I planning to take it
in in a vastly different direction to the original mod. In fact, CC:T aims to be a nurturing ground for various
features, with a pull request against the original mod being the end goal.
This is an fork of [Zundrel/cc-tweaked-fabric](https://github.com/Zundrel/cc-tweaked-fabric) who's goal was to port [SquidDev-CC/CC-Tweaked](https://github.com/SquidDev-CC/CC-Tweaked) to the [Fabric](https://fabricmc.net/) modloader. I picked up maintaining the mod because the team working on Zundrel's fork, admitted they had gotten lethargic so I picked it up to make it equal with CC:T
CC:T also includes many pull requests from the community which have not yet been merged, offering a large number
of additional bug fixes and features over the original mod.
## Resource Packs
This mod includes textures that are more in-line with the style of Mojang's new texture-artist, Jappa. If you prefer the original textures, enable the "Classic" resource pack provided by the mod.
## Features
CC: Tweaked contains all the features of the latest alpha, as well as numerous fixes, performance improvements and
several additional features. I'd recommend checking out [the releases page](https://github.com/SquidDev-CC/CC-Tweaked/releases)
to see the full changes, but here's a couple of the more interesting changes:
- Replace LuaJ with Cobalt.
- Allow running multiple computers at the same time.
- Websocket support in the HTTP library.
- Wired modems and cables act more like multiparts.
- Add map-like rendering for pocket computers and printed pages/books.
- Adds the `/computercraft` command, offering various diagnostic tools for server owners. This allows operators to
track which computers are hogging resources, turn on and shutdown multiple computers at once and interact with
computers remotely.
- Add full-block wired modems, allowing one to wrap non-solid peripherals (such as turtles, or chests if Plethora is
installed).
- Extended binary file handles. They support file seeking, and reading new lines, allowing full (and accurate)
emulation of the standard Lua `io` library.
## Relation to CCTweaks?
This mod has nothing to do with CCTweaks, though there is no denying the name is a throwback to it. That being said,
several features have been included, such as full block modems, the Cobalt runtime and map-like rendering for pocket
computers.
<img src="https://raw.githubusercontent.com/3prm3/cc-pack/main/pack.png" alt="CC: Restitched" width="16" height="16"/> [3prm3/cc-pack](https://github.com/3prm3/cc-pack/)
We also have a second resourcepack made by [3prm3](https://github.com/3prm3), it features a complete overhaul and can be enabled by enabling the `overhaul` resource pack, go check out his resource pack over here!
## Major Tasks Planned
* Rewrite the config system
* **Planned for 1.96.0 release**
* it currently sets the values that would normally be read from `config/computercraft.json` to the default values, because it does not read the file at all
* Fixing `/computercraft` commands,
* No clue why they broken, they just are
## Contributing
Any contribution is welcome, be that using the mod, reporting bugs or contributing code. If you do wish to contribute
code, do consider submitting it to the ComputerCraft repository first.
Any contribution is welcome, be that using the mod, reporting bugs or contributing code. In order to start helping develop CC:R there are a few rules
1) Any updates that port commits from CC:T, ***MUST*** follow the format defined in [patchwork.md](patchwork.md) otherwise they will not be accepted,
* Commit Message must be the same as it is in CC:T,
* patchwork.md must be updated in the following format
> Comments, optional but useful if you had to do something differently than in CC:T outside of [Fabric](https://fabricmc.net/)/[Forge](https://mcforge.readthedocs.io/en/1.16.x/) differences
>
> \`\`\`
>
>commitID
>
> commit title
>
> commit desc
>
> \`\`\`
2) Follow the [Fabric](https://fabricmc.net/) programming guidelines as close as possible. This means you have to use [`loom`](https://fabricmc.net/wiki/tutorial:mappings) mappings,
3) You cannot intentionally implement bugs and security vulnerabilities
4) Unless the commit is a ["patchwork"](https://github.com/Merith-TK/cc-restitched/blob/fabric/patchwork.md) compliant commit, (IE: taken from CC:T), the lua code is off limits
## Bleeding Edge Builds
Bleeding edge builds can be found [here](https://github.com/Merith-TK/cc-restitched/actions) at Github Actions.
That being said, in order to start helping develop CC:T, you'll need to follow these steps:
## Community
If you need help getting started with CC: Tweaked, want to show off your latest project, or just want to chat about ComputerCraft, here is the [Forum](https://forums.computercraft.cc/) and the [Discord](https://discord.gg/H2UyJXe)
- **Clone the repository:** `git clone https://github.com/SquidDev-CC/CC-Tweaked.git && cd CC-Tweaked`
- **Setup Forge:** `./gradlew setupDecompWorkspace`
- **Test your changes:** `./gradlew runClient` (or run the `GradleStart` class from your IDE).
## Known Issues
Main Known issue
* Mods that add blocks that can be used as peripherals for CC:T On forge, don't work with CC:R.
* This is because of the differences between forge and fabric, and that mod devs, to my knowledge have not agreed upon a standard method in which to implement cross compatibility between mods,
* [Fixed (d10f297c): please report if bug persists]</br> ~~Storage Peripherals throw a java "StackOverflowError" when using `pushItems()`,~~
* ~~Work around, you are probably using `pushItems(chest, 1)` or similar. please use `pushItems(chest, 1, nil, 1)`.~~
* Computers will not run built in commands, saying "File not found"
* This is a know bug, dont know what causes it, but just restart the computer (`ctrl+r` for one second) and it will work again
* Occurs when server runs `/reload` or a datapack is updated
## Perpherals
Unfortunately, unlike the original CC:Tweaked project, CC:Restitched, does not have any actual peripheral mods, currently the only one we have is an example for mod devs to get started with making/adding the peripheral API to their mods!
If you want to run CC:T in a normal Minecraft instance, run `./gradlew build` and copy the `.jar` from `build/libs`.
If your a mod dev made a mod with CC:R peripheral support, OR if your a player who found a mod with CC:R support, please open an [issue here](https://github.com/Merith-TK/cc-restitched/issues/new?assignees=&labels=peripheralShoutout&template=peripheral_shoutout.md) to let us know so we can add it to the list!
* ![icon](https://raw.githubusercontent.com/Toad-Dev/cc-peripheral-test/master/src/main/resources/assets/cc_test/textures/block/test_peripheral.png) [CC Peripheral Test](https://github.com/Toad-Dev/cc-peripheral-test)
* This is an example mod for how to make peripherals that work as a block, or as a turtle upgrade!

View File

@@ -1,198 +1,120 @@
// For those who want the bleeding edge
buildscript {
repositories {
jcenter()
maven {
name = "forge"
url = "http://files.minecraftforge.net/maven"
}
}
dependencies {
classpath 'net.minecraftforge.gradle:ForgeGradle:2.3-SNAPSHOT'
classpath 'org.ajoberstar:gradle-git:1.6.0'
}
}
plugins {
id 'com.matthewprenger.cursegradle' version '1.0.10'
id 'fabric-loom' version '0.6-SNAPSHOT'
id 'maven-publish'
}
apply plugin: 'net.minecraftforge.gradle.forge'
apply plugin: 'org.ajoberstar.grgit'
apply plugin: 'maven-publish'
apply plugin: 'maven'
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
version = "1.80pr1.13"
group = "org.squiddev"
archivesBaseName = "cc-tweaked"
version = mod_version
minecraft {
version = "1.12.2-14.23.4.2749"
runDir = "run"
replace '${version}', project.version
// the mappings can be changed at any time, and must be in the following format.
// snapshot_YYYYMMDD snapshot are built nightly.
// stable_# stables are built at the discretion of the MCP team.
// Use non-default mappings at your own risk. they may not allways work.
// simply re-run your setup task after changing the mappings to update your workspace.
mappings = "snapshot_20180724"
// makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable.
}
group = "dan200.computercraft"
archivesBaseName = "cc-restiched"
repositories {
mavenCentral()
jcenter()
maven {
name = "JEI"
url = "http://dvs1.progwml6.com/files/maven"
name "SquidDev"
url "https://squiddev.cc/maven"
}
maven {
name = "squiddev"
url = "https://dl.bintray.com/squiddev/maven"
}
ivy { artifactPattern "https://asie.pl/files/mods/Charset/LibOnly/[module]-[revision](-[classifier]).[ext]" }
}
configurations {
shade
compile.extendsFrom shade
deployerJars
}
dependencies {
deobfProvided "mezz.jei:jei_1.12.2:4.8.5.159:api"
deobfProvided "pl.asie:Charset-Lib:0.5.4.6"
minecraft "com.mojang:minecraft:${mc_version}"
mappings "net.fabricmc:yarn:${mc_version}+build.${mappings_version}:v2"
modImplementation "net.fabricmc:fabric-loader:${fabric_loader_version}"
modImplementation "net.fabricmc.fabric-api:fabric-api:${fabric_api_version}"
runtime "mezz.jei:jei_1.12.2:4.8.5.159"
compile 'com.electronwill.night-config:json:3.6.0'
shade 'org.squiddev:Cobalt:0.4.0'
modImplementation "me.shedaniel.cloth:config-2:${cloth_config_version}"
modImplementation "io.github.prospector:modmenu:${modmenu_version}"
testCompile 'junit:junit:4.11'
modApi "me.shedaniel.cloth.api:cloth-utils-v1:${project.cloth_api_version}"
include "me.shedaniel.cloth.api:cloth-utils-v1:${project.cloth_api_version}"
deployerJars "org.apache.maven.wagon:wagon-ssh:3.0.0"
implementation "blue.endless:jankson:${jankson_version}"
implementation 'com.google.code.findbugs:jsr305:3.0.2'
compileOnly 'com.google.auto.service:auto-service:1.0-rc7'
annotationProcessor 'com.google.auto.service:auto-service:1.0-rc7'
include "me.shedaniel.cloth:config-2:${cloth_config_version}"
include "blue.endless:jankson:${jankson_version}"
include 'javax.vecmath:vecmath:1.5.2'
compile 'javax.vecmath:vecmath:1.5.2'
shade 'org.squiddev:Cobalt:0.5.2-SNAPSHOT'
modRuntime "me.shedaniel:RoughlyEnoughItems-api:5.8.9"
modRuntime "me.shedaniel:RoughlyEnoughItems:5.8.9"
}
javadoc {
include "dan200/computercraft/api/**/*.java"
sourceSets {
main {
java {
exclude 'dan200/computercraft/shared/integration'
}
}
}
processResources {
inputs.property "version", project.version
from(sourceSets.main.resources.srcDirs) {
include "fabric.mod.json"
expand "version": project.version
}
from(sourceSets.main.resources.srcDirs) {
exclude "fabric.mod.json"
}
}
// ensure that the encoding is set to UTF-8, no matter what the system default is
// this fixes some edge cases with special characters not displaying correctly
// see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html
tasks.withType(JavaCompile) {
options.encoding = "UTF-8"
}
// Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
// if it is present.
// If you remove this task, sources will not be generated.
task sourcesJar(type: Jar, dependsOn: classes) {
classifier = "sources"
from sourceSets.main.allSource
}
jar {
dependsOn javadoc
manifest {
attributes('FMLAT': 'computercraft_at.cfg')
}
into("docs", { from (javadoc.destinationDir) })
into("api", { from (sourceSets.main.allSource) {
include "dan200/computercraft/api/**/*.java"
}})
from "LICENSE"
from configurations.shade.collect { it.isDirectory() ? it : zipTree(it) }
}
import org.ajoberstar.grgit.Grgit
processResources {
inputs.property "version", project.version
inputs.property "mcversion", project.minecraft.version
def grgit = Grgit.open(dir: '.')
inputs.property "commithash", grgit.head().id
def blacklist = ['GitHub', 'dan200', 'Daniel Ratcliffe']
Set<String> contributors = []
grgit.log().each {
if (!blacklist.contains(it.author.name)) contributors.add(it.author.name)
if (!blacklist.contains(it.committer.name)) contributors.add(it.committer.name)
}
from(sourceSets.main.resources.srcDirs) {
include 'mcmod.info'
include 'assets/computercraft/lua/rom/help/credits.txt'
expand 'version':project.version,
'mcversion':project.minecraft.version,
'gitcontributors':contributors.sort(false, String.CASE_INSENSITIVE_ORDER).join('\n')
}
from(sourceSets.main.resources.srcDirs) {
exclude 'mcmod.info'
exclude 'assets/computercraft/lua/rom/help/credits.txt'
}
}
curseforge {
apiKey = project.hasProperty('curseForgeApiKey') ? project.curseForgeApiKey : ''
project {
id = '282001'
releaseType = 'beta'
changelog = "Release notes can be found on the GitHub repository (https://github.com/SquidDev-CC/CC-Tweaked/releases/tag/v${project.version})."
}
}
// configure the maven publication
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
artifact sourceJar
}
}
}
uploadArchives {
repositories {
if(project.hasProperty('mavenUploadUrl')) {
mavenDeployer {
configuration = configurations.deployerJars
repository(url: project.property('mavenUploadUrl')) {
authentication(
userName: project.property('mavenUploadUser'),
privateKey: project.property('mavenUploadKey'))
}
pom.project {
name 'CC: Tweaked'
packaging 'jar'
description 'A fork of ComputerCraft which aims to provide earlier access to the more experimental and in-development features of the mod.'
url 'https://github.com/SquidDev-CC/CC-Tweaked'
scm {
url 'https://github.com/dan200/ComputerCraft.git'
}
issueManagement {
system 'github'
url 'https://github.com/dan200/ComputerCraft/issues'
}
licenses {
license {
name 'ComputerCraft Public License, Version 1.0'
url 'https://github.com/dan200/ComputerCraft/blob/master/LICENSE'
distribution 'repo'
}
}
}
pom.whenConfigured { pom ->
pom.dependencies.clear()
}
// add all the jars that should be included when publishing to maven
artifact(remapJar) {
builtBy remapJar
}
artifact(sourcesJar) {
builtBy remapSourcesJar
}
}
}
}
gradle.projectsEvaluated {
tasks.withType(JavaCompile) {
options.compilerArgs << "-Xlint"
// select the repositories you want to publish to
repositories {
// uncomment to publish to the local maven
// mavenLocal()
}
}
runClient.outputs.upToDateWhen { false }
runServer.outputs.upToDateWhen { false }

2491
codeInspectionSettings.xml Normal file

File diff suppressed because it is too large Load Diff

17
gradle.properties Normal file
View File

@@ -0,0 +1,17 @@
# Done to increase the memory available to gradle.
org.gradle.jvmargs=-Xmx1G
# Mod properties
mod_version=1.96.0
# Minecraft properties
mc_version=1.16.5
mappings_version=9
# Dependencies
cloth_config_version=4.8.1
fabric_loader_version=0.11.3
fabric_api_version=0.32.0+1.16
jankson_version=1.2.0
modmenu_version=1.14.6+
cloth_api_version=1.4.5

Binary file not shown.

View File

@@ -1,5 +1,6 @@
#Tue Jul 07 13:15:43 EDT 2020
distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-all.zip
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.3-bin.zip
zipStoreBase=GRADLE_USER_HOME

BIN
logo.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

627
patchwork.md Normal file
View File

@@ -0,0 +1,627 @@
# Just my list of things I have ported over
Format for the changelog of ported stuff
```
commit // Shows commit from CC:T
commit2 // Shows a commit that is the same thing, just a clean up, only if right after
Title // Commit Title
SubScript // Desc of commit
```
If a edit that is present in CC:T is not needed, I will skip over it.
Any and all references to an issue number, are to be found on CC:T's repo.
Any commit that starts with `[Patchwork]` are purely edits made by my hand, and not based on other commits from CC:T, this is to help differentiate my changes from the official changes
Lines that are found above a commit in this log like this one, (excluding this one) are comments about how i had to implement things that are not a simple 1:1 (excluding fabric/forge differences) conversion
```md
5155e18de279a193c558aa029963486fd1294769
Added translation for Vietnamese
Co-authored-by: Boom <boom@flyingpackets.net>
```
```
7e121ff72f2b1504cd6af47b57500876682bac45
ae6124d1f477487abab1858abde8c4ec49dfee3c
Translations for Vienamese
Co-authored-by: Boom <boom@flyingpackets.net>
```
```
59de21eae29849988e77fad6bc335f5ce78dfec7
Handle tabs when parsing JSON
Fixes #539
```
```
748ebbe66bf0a4239bde34f557e4b4b75d61d990
Bump to 1.92.0
A tiny release, but there's new features so it's technically a minor
bump.
```
Cherry Picked because this update was partially related to forge updates rather than mod updates
```
8b4a01df27ff7f6fa9ffd9c2188c6e3166edd515
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.
```
```
87393e8aef9ddfaca465d626ee7cff5ff499a7e8
Fix additional `-` in docs
Why isn't this automatically stripped! Bad squid.
```
```
275ca58a82c627128a145a8754cbe32568536bd9
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
```
The alterations in ColourUtils.java were not needed so they were not ported over
```
6f868849ab2f264508e12c184cc56f2632aaf5bc
Use tags to check if something is a dye
We half did this already, just needed to change a couple of checks.
Closes #541.
```
```
6cee4efcd3610536ee74330cd728f7371011e5a8
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
```
```
0832974725b2478c5227b81f82c35bbf03cf6aba
Translations for Swedish
Co-authored-by: David Isaksson <davidisaksson93@gmail.com>
```
```
84036d97d99efd8762e0170002060ae3471508bf
Fix io.open documentation
Well, that was silly.
```
I set the default properties for computers as `Block.GLASS` and then set their strength to `2F` and their soundgroup to stone
```
8472112fc1eaad18ed6ed2c6c62b040fe421e81a
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.
```
```
30d35883b83831900b34040f0131c7e06f5c3e52
Fix my docs
Thanks @plt-hokusai. Kinda embarrassing this slipped through - I
evidently need to lint examples too.
```
```
34a2c835d412c0d9e1fb20a42b7f2cd2738289c7
Add color table to docs (#553)
```
All API Documentation updates,
`Not Needed` for this repo.
```
93068402a2ffec00eedb8fe2d859ebdc005a1989
Document remaining OS functions (#554)
01d81cb91da938836f953b290ad6b8fc87cb7e35
Update illuaminate CSS for deprecation (#556)
```
```
Not Needed
4766833cf2d041ed179529eecb9402ad09b2b79b
Bump JEI/crafttweaker versions
In my defence, they weren't out when I started the 1.15 update.
```
```
bf6053906dc6a3c7b0d40d5b097e745dce1f33bc
Fix TBO norm issues on old GPUs
```
```
Not Needed
113b560a201dbdea9de2a2ef536bcce1d6e51978
Update configuration to match latest illuaminate
Ooooooh, it's all fancy now. Well, that or horrifically broken.
```
```
c334423d42ba3b653ac3a8c27bce7970457f8f96
Add function to get window visibility
Closes #562
Co-authored-by: devomaa <lmao@distruzione.org>
```
[WARN] Could not implement changes to the following files
* `src/main/java/dan200/computercraft/ComputerCraft.java` < Structure too different, cannot find equivalent to alter
* `src/main/java/dan200/computercraft/shared/Config.java` < Files Does not exist in this repo
```
84a6bb1cf3b0668ddc7d8c409a2477a42390e3f7
Make generic peripherals on by default
This is a long way away from "feature complete" as it were. However,
it's definitely at a point where it's suitable for general usage - I'm
happy with the API, and don't think I'm going to be breaking things any
time soon.
That said, things aren't exposed yet for Java-side public consumption. I
was kinda waiting until working on Plethora to actually do that, but not
sure if/when that'll happen.
If someone else wants to work on an integration mod (or just adding
integrations for their own mod), do get in touch and I can work out how
to expose this.
Closes #452
```
```
Not Needed
6aae4e576621090840724e094aa25e51696530fc
Remove superfluous imports
Hah, this is embarassing
```
[TODO] [M3R1-01] Code has been applied, players still dont get achievments
```
f6160bdc57b3d9850607c2c7c2ce9734b4963478
Fix players not getting advancements when they own turtles
When we construct a new ServerPlayerEntity (and thus TurtlePlayer), we
get the current (global) advancement state and call .setPlayer() on it.
As grantCriterion blocks FakePlayers from getting advancements, this
means a player will no longer receive any advancements, as the "wrong"
player object is being consulted.
As a temporary work around, we attempt to restore the previous player to
the advancement store. I'll try to upstream something into Forge to
resolve this properly.
Fixes #564
```
```
17a932920711a5c0361a5048c9e0a5e7a58e6364
Bump cct-javadoc version
Documentation will now be sorted (somewhat) correctly!
```
```
a6fcfb6af2fc1bef8ca3a19122c9267549202424
Draw in-hand pocket computers with blending
It might be worth switching to RenderTypes here, rather than a pure
Tesselator, but this'll do for now.
Fixes Zundrel/cc-tweaked-fabric#20.
```
```
c58441b29c3715f092e7f3747bb3ec65ae5a3d29
Various SNBT parsing improvements
Correctly handle:
- Typed arrays ([I; 1, 2, 3])
- All suffixed numbers (1.2d)
- Single-quoted strings
Fixes #559
```
```
e2a635b6e5f5942f999213434054e06833c5cb06
Dont fail when codecov is being finicky
```
```
666e83cf4fd0eb327f465d5b919a708790f99b00
Fix JSON objects failing to pass
Maybe I should run the whole test suite, not just the things I think
matter? Nah....
```
```
741adfa7bb2b950d2851c3f0072d6a4769f22773
Use blit to draw boxes, add colors.toBlit (#570)
```
```
d13bd2cce8d102ad7f61f557e707d6fe3731bc37
use arg[0] in all usage printouts (#571)
```
```
74ac5bb3d17e5bee30643a5d6702696600c06229
Bump to 1.94.0
```
[TODO] [M3R1-02] Zero Clue how to reimplement this in fabric.
```
c8aeddedd4ed430f9cb6428676ebb4fa39834182
Auto-generate monitor models
I didn't think it was worth it, and then I found myself needing to
update a dozen of them. The code isn't especially pretty, but it works,
so that's fine.
Also fixes several issues with us using the wrong texture (closes #572).
I've put together a wiki page[1] which describes each texture in a
little more detail.
[1] https://github.com/SquidDev-CC/CC-Tweaked/wiki/Monitor-texture-reference
```
```
7f90f2f7cadce0d5b9177b16626979591bce8137
Clean up some examples a little bit
Would be good if they didn't crash and burn on entry :).
```
```
f194f4fa3a17c48ff1a9088d50063f4a675a23b6
Fix epoch documentation to use milliseconds (#580)
```
```
d2a1a00dc43e5b65f6b64111ce76dd3db16c919f
Clear gets an option to reset the palette (#582)
Fixes #555.
```
```
aab0cd34cd64fdf837ff1c3b91a957a25c2cf7f9
Use term.blit on original paint render
This makes it super speedy, meaning an initial refresh doesn't take ages
to load.
```
```
b0651082f472baee8f0fa8ec7ba95f433e2637bb
Cleanup examples for the various modules
```
Ignored Documentation Changes, these are locate
```
9a749642d294506095e697a3a4345dfe260bd68c
Strict Globals (#583)
```
```
fff8353451451be5ae31e0f63d8e529b127fd186
Remove extra space (#586)
```
```
486f41f08286ddcfad91d72b83a9361bd9c215cb
Fixed length check on function name in `expect` (#589)
```
```
04f9644ae75dafc72da4c4790f334d2e90b03e6f
Allow strings or numbers in textutils.*tabulate
A little dubious, but apparently CC used to support it. This means we're
consistent with methods like io.write or string.len which accept strings
or numbers.
Fixes #591
```
```
d4199064ae5ae8023c589f80f12d94e1c6bbc2b5
Make fs.combine accept multiple arguments
Means we can now do fs.combine("a", "b", "c"). Of course, one may just
write "a/b/c" in this case, but it's definitely useful elsewhere.
This is /technically/ a breaking change as fs.combine(a, b:gsub(...))
will no longer function (as gsub returns multiple arguments). However,
I've done a quick search through GH and my Pastebin archives and can't
find any programs which would break. Fingers crossed.
```
```
24af36743d08fcdb58439c52bf587b33ed828263
Try to handle a turtle being broken while ticked
Hopefully fixes #585. Hopefully.
```
```
511eea39a11956c82e2c11a47b2e7cad27f9887e
Remove <!-- -->s in usages
```
```
826797cbd579e867f0f35f0be44b6a28c8c094a9
Added documentation for global functions (#592)
```
Didn't port the docs over.
```
d83a68f3ff6e3833278a38798d06215293656e85
Allow $private HTTP rule to block any private IP
```
The config still uses a `blacklist` and `whitelist` array.
```
24d3777722812f975d2bc4594437fbbb0431d910
Added improved help viewer (#595)
```
Didn't port the lua tests over.
```
737b3cb57696fb5517252e7db38bc88ce960b4d8
Don't use capabilities for generic peripherals
```
Not ported, related to forges capability system which is not used in the port.
```
ea3a16036794357c3a44edffc90fdb652e03881e
Remove a couple of todos
```
```
bb8f4c624bf87169b73fb631d8250cfc38181e15
Some sanity checks for get{Direction,Orientation}
```
Use `getCachedState` instead of forge's `getBlockState` and `contains` instead of `has`.
```
05c3c8ad3269c9025757f9261e7f609889fb6bdc
Generate docs for generic peripherals
```
Skipped everything except some removed whitespace.
```
85cf2d5ff1b63010de4661301801aa504e5b9015
Docs for energy and inventory methods
```
and
```
5865e9c41a0140b9f1acdd2fb095353c467fbb45
Not sure what irritates me more
```
both skipped because the changes where already ported.
```
4ae370b9dbaf1de0ed32a5f32340b1448136c9cc
Merge pull request #606 from TheWireLord/numpadenter-support
```
Just lua changes.
```
f5eb6ce03e0d9bbbf77130452afd4b49e758f7bd
Fix copy-paste error in inventory docs
```
Skipped because it was already ported.
```
663859d2e5a97edefebf9ac36206903d7dd33a3e
Fix double URL decode
```
```
abf425dfb5553483cdc51c50a6b7d8b5e44814f4
Fix overflow in os.epoch
```
```
e3a672099c1b5d2c06f9fe4d8ccd024fef0873a2
Fix JEI integration with turtle/pocket upgrades
```
Skipped because there seems to be no REI integration.
```
2f0cae0bc1b038ac092bafa7f65a317537203cd8
Make upgrade recipe requirements a little more lax
```
[TODO] [JUMT-01] Crafting is still messed up, but this port didn't change the behavior.
[TODO] [JUMT-02] Tag comparison code doesn't need to be that verbose, a simple `isEqual` check would suffice.
```
7f9a707f75636d5816f752dc93d7b6b998c61a03
Bump version to 1.95.0
```
Changed the name from CC: Tweaked to CC: Restitched in the changelog and whatsnew files. New version is 1.95.0-beta.
```
4af5bcc0b0ff464e7e7428c389d47140580ea7a7
Fix serveral 1.15 -> 1.16 issues
```
Skipped, changes where already made.
```
b8d5a89446ac02fc5b38cc5c0b4805de9d11a7d5
Add explicit @module annotation
```
Tiny lua change.
```
8b17ec76a8e94251803e6f4ba4e65970c6a70b7f
Fixed missing argument names in file handle docs (#632)
```
A java doc change.
```
e4b0a5b3ce035eb23feb4191432fc49af5772c5b
2020 -> 2021
```
A huge amount of changes.
```
542b66c79a9b08e080c39c9a73d74ffe71c0106a
Add back command computer block drops
```
Didn't port some forge-related changes, but it works.
```
dd6f97622e6c18ce0d8988da6a5bede45c94ca5d
Prevent reflection errors crashing the game
```
```
92be0126df63927d07fc695945f8b98e328f945a
Fix disk recipes
```
Dye recipes actually work now.
```
1edb7288b974aec3764b0a820edce7e9eee38e66
Merge branch 'mc-1.15.x' into mc-1.16.x
```
New version: 1.95.1.
```
41226371f3b5fd35f48b6d39c2e8e0c277125b21
Add isReadOnly to fs.attributes (#639)
```
Also changed some lua test files, but made the changes anyway.
```
b2e54014869fac4b819b01b6c24e550ca113ce8a
Added Numpad Enter Support in rom lua programs. (#657)
```
Just lua changes.
```
247c05305d106af430fcdaee41371a152bf7c38c
Fix problem with RepeatArgumentType
```
```
c864576619751077a0d8ac1a18123e14b095ec03
Fix impostor recipes for disks
```
[TODO] [JUMT-03] REI still shows white disks, probably because it doesn' show nbt items.
```
c5694ea9661c7a40021ebd280c378bd7bdc56988
Merge branch 'mc-1.15.x' into mc-1.16.x
```
Update to 1.16.4.
```
1f84480a80677cfaaf19d319290f5b44635eba47
Make rightAlt only close menu, never open it. (#672)
```
Lua changes.
```
1255bd00fd21247a50046020d7d9a396f66bc6bd
Fix mounts being usable after a disk is ejected
```
Reverted a lot of code style changes made by Zundrel, so the diffs are huge.
```
b90611b4b4c176ec1c80df002cc4ac36aa0c4dc8
Preserve registration order of upgrades
```
Again, a huge diff because of code style changes.
```
8494ba8ce29cd8d7b9105eef497fe3fe3f89d350
Improve UX when a resource mount cannot be found
```

View File

@@ -1 +1,12 @@
rootProject.name = 'cc-tweaked'
pluginManagement {
repositories {
jcenter()
maven {
name = 'Fabric'
url = 'https://maven.fabricmc.net/'
}
gradlePluginPortal()
}
}
rootProject.name = "cc-restiched"

View File

@@ -1,723 +1,139 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft;
import dan200.computercraft.api.filesystem.IMount;
import dan200.computercraft.api.filesystem.IWritableMount;
import dan200.computercraft.api.lua.ILuaAPIFactory;
import dan200.computercraft.api.media.IMedia;
import dan200.computercraft.api.media.IMediaProvider;
import dan200.computercraft.api.network.IPacketNetwork;
import dan200.computercraft.api.network.wired.IWiredElement;
import dan200.computercraft.api.network.wired.IWiredNode;
import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.api.peripheral.IPeripheralProvider;
import dan200.computercraft.api.permissions.ITurtlePermissionProvider;
import dan200.computercraft.api.pocket.IPocketUpgrade;
import dan200.computercraft.api.redstone.IBundledRedstoneProvider;
import dan200.computercraft.api.turtle.ITurtleUpgrade;
import dan200.computercraft.api.turtle.event.TurtleAction;
import dan200.computercraft.core.apis.AddressPredicate;
import dan200.computercraft.core.apis.ApiFactories;
import dan200.computercraft.core.apis.http.websocket.Websocket;
import dan200.computercraft.core.filesystem.ComboMount;
import dan200.computercraft.core.filesystem.FileMount;
import dan200.computercraft.core.filesystem.FileSystemMount;
import dan200.computercraft.core.terminal.Terminal;
import dan200.computercraft.core.tracking.Tracking;
import dan200.computercraft.shared.*;
import dan200.computercraft.shared.computer.blocks.BlockCommandComputer;
import dan200.computercraft.shared.computer.blocks.BlockComputer;
import dan200.computercraft.shared.computer.blocks.TileComputer;
import dan200.computercraft.shared.computer.core.ClientComputerRegistry;
import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.computer.core.ServerComputer;
import dan200.computercraft.shared.computer.core.ServerComputerRegistry;
import dan200.computercraft.shared.media.items.ItemDiskExpanded;
import dan200.computercraft.shared.media.items.ItemDiskLegacy;
import dan200.computercraft.shared.media.items.ItemPrintout;
import dan200.computercraft.shared.media.items.ItemTreasureDisk;
import dan200.computercraft.shared.peripheral.common.BlockPeripheral;
import dan200.computercraft.shared.peripheral.diskdrive.TileDiskDrive;
import dan200.computercraft.shared.peripheral.modem.wired.BlockCable;
import dan200.computercraft.shared.peripheral.modem.wired.BlockWiredModemFull;
import dan200.computercraft.shared.peripheral.modem.wireless.BlockAdvancedModem;
import dan200.computercraft.shared.peripheral.modem.wireless.WirelessNetwork;
import dan200.computercraft.shared.peripheral.printer.TilePrinter;
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.proxy.ICCTurtleProxy;
import dan200.computercraft.shared.proxy.IComputerCraftProxy;
import dan200.computercraft.shared.turtle.blocks.BlockTurtle;
import dan200.computercraft.shared.turtle.blocks.TileTurtle;
import dan200.computercraft.shared.turtle.upgrades.*;
import dan200.computercraft.shared.util.CreativeTabMain;
import dan200.computercraft.shared.util.IDAssigner;
import dan200.computercraft.shared.util.IoUtil;
import dan200.computercraft.shared.wired.CapabilityWiredElement;
import dan200.computercraft.shared.wired.WiredNode;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.ItemStack;
import net.minecraft.server.MinecraftServer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.SidedProxy;
import net.minecraftforge.fml.common.event.*;
import net.minecraftforge.fml.common.network.NetworkRegistry;
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
import net.minecraftforge.fml.common.network.simpleimpl.SimpleNetworkWrapper;
import net.minecraftforge.fml.relauncher.Side;
import org.apache.logging.log4j.Logger;
import static dan200.computercraft.shared.ComputerCraftRegistry.ModBlocks;
import static dan200.computercraft.shared.ComputerCraftRegistry.init;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.util.ArrayList;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.ServiceConfigurationError;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.concurrent.TimeUnit;
@Mod(
modid = ComputerCraft.MOD_ID, name = "CC: Tweaked", version = "${version}",
guiFactory = "dan200.computercraft.client.gui.GuiConfigCC$Factory",
dependencies = "required:forge@[14.23.4.2746,)"
)
public class 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.apis.http.websocket.Websocket;
import dan200.computercraft.shared.common.ColourableRecipe;
import dan200.computercraft.shared.computer.core.ClientComputerRegistry;
import dan200.computercraft.shared.computer.core.ServerComputerRegistry;
import dan200.computercraft.shared.computer.recipe.ComputerUpgradeRecipe;
import dan200.computercraft.shared.data.BlockNamedEntityLootCondition;
import dan200.computercraft.shared.data.HasComputerIdLootCondition;
import dan200.computercraft.shared.data.PlayerCreativeLootCondition;
import dan200.computercraft.shared.media.recipes.DiskRecipe;
import dan200.computercraft.shared.media.recipes.PrintoutRecipe;
import dan200.computercraft.shared.peripheral.monitor.MonitorRenderer;
import dan200.computercraft.shared.pocket.recipes.PocketComputerUpgradeRecipe;
import dan200.computercraft.shared.proxy.ComputerCraftProxyCommon;
import dan200.computercraft.shared.turtle.recipes.TurtleRecipe;
import dan200.computercraft.shared.turtle.recipes.TurtleUpgradeRecipe;
import dan200.computercraft.shared.util.Config;
import dan200.computercraft.shared.util.ImpostorRecipe;
import dan200.computercraft.shared.util.ImpostorShapelessRecipe;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.Registry;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.client.itemgroup.FabricItemGroupBuilder;
import net.fabricmc.fabric.api.resource.ResourceManagerHelper;
import net.fabricmc.fabric.api.resource.ResourcePackActivationType;
import net.fabricmc.loader.api.FabricLoader;
public final class ComputerCraft implements ModInitializer {
public static final String MOD_ID = "computercraft";
// GUI IDs
public static final int diskDriveGUIID = 100;
public static final int computerGUIID = 101;
public static final int printerGUIID = 102;
public static final int turtleGUIID = 103;
// ComputerCraftEdu uses ID 104
public static final int printoutGUIID = 105;
public static final int pocketComputerGUIID = 106;
public static final int viewComputerGUIID = 110;
// Configuration options
public static final String[] DEFAULT_HTTP_WHITELIST = new String[] { "*" };
public static final String[] DEFAULT_HTTP_BLACKLIST = new String[] {
"127.0.0.0/8",
"10.0.0.0/8",
"172.16.0.0/12",
"192.168.0.0/16",
"fd00::/8",
};
public static final int terminalWidth_computer = 51;
public static final int terminalHeight_computer = 19;
public static final int terminalWidth_turtle = 39;
public static final int terminalHeight_turtle = 13;
public static final int terminalWidth_pocketComputer = 26;
public static final int terminalHeight_pocketComputer = 20;
// Registries
public static final ClientComputerRegistry clientComputerRegistry = new ClientComputerRegistry();
public static final ServerComputerRegistry serverComputerRegistry = new ServerComputerRegistry();
// Logging
public static final Logger log = LogManager.getLogger(MOD_ID);
public static ItemGroup MAIN_GROUP = FabricItemGroupBuilder.build(new Identifier(MOD_ID, "main"), () -> new ItemStack(ModBlocks.COMPUTER_NORMAL));
public static boolean commandRequireCreative = false;
public static MonitorRenderer monitorRenderer = MonitorRenderer.BEST;
public static int computerSpaceLimit = 1000 * 1000;
public static int floppySpaceLimit = 125 * 1000;
public static int maximumFilesOpen = 128;
public static boolean disable_lua51_features = false;
public static String default_computer_settings = "";
public static boolean debug_enable = true;
public static int computer_threads = 1;
public static boolean logPeripheralErrors = false;
public static int computer_threads = 1;
public static long maxMainGlobalTime = TimeUnit.MILLISECONDS.toNanos(10);
public static long maxMainComputerTime = TimeUnit.MILLISECONDS.toNanos(5);
public static boolean http_enable = true;
public static boolean http_websocket_enable = true;
public static AddressPredicate http_whitelist = new AddressPredicate( DEFAULT_HTTP_WHITELIST );
public static AddressPredicate http_blacklist = new AddressPredicate( DEFAULT_HTTP_BLACKLIST );
public static int httpTimeout = 30000;
public static int httpMaxRequests = 16;
public static long httpMaxDownload = 16 * 1024 * 1024;
public static long httpMaxUpload = 4 * 1024 * 1024;
public static int httpMaxWebsockets = 4;
public static int httpMaxWebsocketMessage = Websocket.MAX_MESSAGE_SIZE;
public static boolean enableCommandBlock = false;
public static int modem_range = 64;
public static int modem_highAltitudeRange = 384;
public static int modem_rangeDuringStorm = 64;
public static int modem_highAltitudeRangeDuringStorm = 384;
public static int maxNotesPerTick = 8;
public static boolean turtlesNeedFuel = true;
public static int turtleFuelLimit = 20000;
public static int advancedTurtleFuelLimit = 100000;
public static boolean turtlesObeyBlockProtection = true;
public static boolean turtlesCanPush = true;
public static EnumSet<TurtleAction> turtleDisabledActions = EnumSet.noneOf( TurtleAction.class );
public static EnumSet<TurtleAction> turtleDisabledActions = EnumSet.noneOf(TurtleAction.class);
public static int monitorWidth = 8;
public static int monitorHeight = 6;
public static double monitorDistanceSq = 4096;
public static final int terminalWidth_computer = 51;
public static final int terminalHeight_computer = 19;
public static List<AddressRule> httpRules = Collections.unmodifiableList( Arrays.asList(
AddressRule.parse( "$private", null, Action.DENY.toPartial() ),
AddressRule.parse( "*", null, Action.ALLOW.toPartial() )
) );
public static final int terminalWidth_turtle = 39;
public static final int terminalHeight_turtle = 13;
public static final int terminalWidth_pocketComputer = 26;
public static final int terminalHeight_pocketComputer = 20;
// Blocks and Items
public static class Blocks
{
public static BlockComputer computer;
public static BlockPeripheral peripheral;
public static BlockCable cable;
public static BlockTurtle turtle;
public static BlockTurtle turtleExpanded;
public static BlockTurtle turtleAdvanced;
public static BlockCommandComputer commandComputer;
public static BlockAdvancedModem advancedModem;
public static BlockWiredModemFull wiredModemFull;
@Override
public void onInitialize() {
Config.load(Paths.get(FabricLoader.getInstance()
.getConfigDir()
.toFile()
.getPath(), MOD_ID + ".json5"));
ComputerCraftProxyCommon.init();
Registry.register(Registry.RECIPE_SERIALIZER, new Identifier(ComputerCraft.MOD_ID, "colour"), ColourableRecipe.SERIALIZER);
Registry.register(Registry.RECIPE_SERIALIZER, new Identifier(ComputerCraft.MOD_ID, "computer_upgrade"), ComputerUpgradeRecipe.SERIALIZER);
Registry.register(Registry.RECIPE_SERIALIZER,
new Identifier(ComputerCraft.MOD_ID, "pocket_computer_upgrade"),
PocketComputerUpgradeRecipe.SERIALIZER);
Registry.register(Registry.RECIPE_SERIALIZER, new Identifier(ComputerCraft.MOD_ID, "disk"), DiskRecipe.SERIALIZER);
Registry.register(Registry.RECIPE_SERIALIZER, new Identifier(ComputerCraft.MOD_ID, "printout"), PrintoutRecipe.SERIALIZER);
Registry.register(Registry.RECIPE_SERIALIZER, new Identifier(ComputerCraft.MOD_ID, "turtle"), TurtleRecipe.SERIALIZER);
Registry.register(Registry.RECIPE_SERIALIZER, new Identifier(ComputerCraft.MOD_ID, "turtle_upgrade"), TurtleUpgradeRecipe.SERIALIZER);
Registry.register(Registry.RECIPE_SERIALIZER, new Identifier(ComputerCraft.MOD_ID, "impostor_shaped"), ImpostorRecipe.SERIALIZER);
Registry.register(Registry.RECIPE_SERIALIZER, new Identifier(ComputerCraft.MOD_ID, "impostor_shapeless"), ImpostorShapelessRecipe.SERIALIZER);
Registry.register(Registry.LOOT_CONDITION_TYPE, new Identifier(ComputerCraft.MOD_ID, "block_named"), BlockNamedEntityLootCondition.TYPE);
Registry.register(Registry.LOOT_CONDITION_TYPE, new Identifier(ComputerCraft.MOD_ID, "player_creative"), PlayerCreativeLootCondition.TYPE);
Registry.register(Registry.LOOT_CONDITION_TYPE, new Identifier(ComputerCraft.MOD_ID, "has_id"), HasComputerIdLootCondition.TYPE);
init();
FabricLoader.getInstance().getModContainer(MOD_ID).ifPresent(modContainer -> {
ResourceManagerHelper.registerBuiltinResourcePack(new Identifier(MOD_ID, "classic"), modContainer, ResourcePackActivationType.NORMAL);
ResourceManagerHelper.registerBuiltinResourcePack(new Identifier(MOD_ID, "overhaul"), modContainer, ResourcePackActivationType.NORMAL);
});
}
public static class Items
{
public static ItemDiskLegacy disk;
public static ItemDiskExpanded diskExpanded;
public static ItemPrintout printout;
public static ItemTreasureDisk treasureDisk;
public static ItemPocketComputer pocketComputer;
}
public static class Upgrades
{
public static TurtleModem wirelessModem;
public static TurtleCraftingTable craftingTable;
public static TurtleSword diamondSword;
public static TurtleShovel diamondShovel;
public static TurtleTool diamondPickaxe;
public static TurtleAxe diamondAxe;
public static TurtleHoe diamondHoe;
public static TurtleModem advancedModem;
public static TurtleSpeaker turtleSpeaker;
}
public static class PocketUpgrades
{
public static PocketModem wirelessModem;
public static PocketModem advancedModem;
public static PocketSpeaker pocketSpeaker;
}
// Registries
public static ClientComputerRegistry clientComputerRegistry = new ClientComputerRegistry();
public static ServerComputerRegistry serverComputerRegistry = new ServerComputerRegistry();
// Networking
public static SimpleNetworkWrapper networkWrapper;
// Creative
public static CreativeTabMain mainCreativeTab;
// Logging
public static Logger log;
// Peripheral providers. This is still here to ensure compatibility with Plethora and Computronics
public static List<IPeripheralProvider> peripheralProviders = new ArrayList<>();
// Implementation
@Mod.Instance( value = ComputerCraft.MOD_ID )
public static ComputerCraft instance;
@SidedProxy( clientSide = "dan200.computercraft.client.proxy.ComputerCraftProxyClient", serverSide = "dan200.computercraft.server.proxy.ComputerCraftProxyServer" )
public static IComputerCraftProxy proxy;
@SidedProxy( clientSide = "dan200.computercraft.client.proxy.CCTurtleProxyClient", serverSide = "dan200.computercraft.server.proxy.CCTurtleProxyServer" )
public static ICCTurtleProxy turtleProxy;
@Mod.EventHandler
public void preInit( FMLPreInitializationEvent event )
{
log = event.getModLog();
// Load config
Config.load( event.getSuggestedConfigurationFile() );
// Setup network
networkWrapper = NetworkRegistry.INSTANCE.newSimpleChannel( ComputerCraft.MOD_ID );
proxy.preInit();
turtleProxy.preInit();
}
@Mod.EventHandler
public void init( FMLInitializationEvent event )
{
proxy.init();
turtleProxy.init();
}
@Mod.EventHandler
public void onServerStarting( FMLServerStartingEvent event )
{
proxy.initServer( event.getServer() );
}
@Mod.EventHandler
public void onServerStart( FMLServerStartedEvent event )
{
if( FMLCommonHandler.instance().getEffectiveSide() == Side.SERVER )
{
ComputerCraft.serverComputerRegistry.reset();
WirelessNetwork.resetNetworks();
Tracking.reset();
}
}
@Mod.EventHandler
public void onServerStopped( FMLServerStoppedEvent event )
{
if( FMLCommonHandler.instance().getEffectiveSide() == Side.SERVER )
{
ComputerCraft.serverComputerRegistry.reset();
WirelessNetwork.resetNetworks();
Tracking.reset();
}
}
public static String getVersion()
{
return "${version}";
}
public static void openDiskDriveGUI( EntityPlayer player, TileDiskDrive drive )
{
BlockPos pos = drive.getPos();
player.openGui( ComputerCraft.instance, ComputerCraft.diskDriveGUIID, player.getEntityWorld(), pos.getX(), pos.getY(), pos.getZ() );
}
public static void openComputerGUI( EntityPlayer player, TileComputer computer )
{
BlockPos pos = computer.getPos();
player.openGui( ComputerCraft.instance, ComputerCraft.computerGUIID, player.getEntityWorld(), pos.getX(), pos.getY(), pos.getZ() );
}
public static void openPrinterGUI( EntityPlayer player, TilePrinter printer )
{
BlockPos pos = printer.getPos();
player.openGui( ComputerCraft.instance, ComputerCraft.printerGUIID, player.getEntityWorld(), pos.getX(), pos.getY(), pos.getZ() );
}
public static void openTurtleGUI( EntityPlayer player, TileTurtle turtle )
{
BlockPos pos = turtle.getPos();
player.openGui( instance, ComputerCraft.turtleGUIID, player.getEntityWorld(), pos.getX(), pos.getY(), pos.getZ() );
}
public static void openPrintoutGUI( EntityPlayer player, EnumHand hand )
{
player.openGui( ComputerCraft.instance, ComputerCraft.printoutGUIID, player.getEntityWorld(), hand.ordinal(), 0, 0 );
}
public static void openPocketComputerGUI( EntityPlayer player, EnumHand hand )
{
player.openGui( ComputerCraft.instance, ComputerCraft.pocketComputerGUIID, player.getEntityWorld(), hand.ordinal(), 0, 0 );
}
public static void openComputerGUI( EntityPlayer player, ServerComputer computer )
{
ComputerFamily family = computer.getFamily();
int width = 0, height = 0;
Terminal terminal = computer.getTerminal();
if( terminal != null )
{
width = terminal.getWidth();
height = terminal.getHeight();
}
// Pack useful terminal information into the various coordinate bits.
// These are extracted in ComputerCraftProxyCommon.getClientGuiElement
player.openGui( ComputerCraft.instance, ComputerCraft.viewComputerGUIID, player.getEntityWorld(),
computer.getInstanceID(), family.ordinal(), (width & 0xFFFF) << 16 | (height & 0xFFFF)
);
}
private static File getBaseDir()
{
return FMLCommonHandler.instance().getMinecraftServerInstance().getDataDirectory();
}
private static File getResourcePackDir()
{
return new File( getBaseDir(), "resourcepacks" );
}
public static File getWorldDir( World world )
{
return proxy.getWorldDir( world );
}
public static void sendToPlayer( EntityPlayer player, IMessage packet )
{
networkWrapper.sendTo( packet, (EntityPlayerMP) player );
}
public static void sendToAllPlayers( IMessage packet )
{
networkWrapper.sendToAll( packet );
}
public static void sendToServer( IMessage packet )
{
networkWrapper.sendToServer( packet );
}
public static void sendToAllAround( IMessage packet, NetworkRegistry.TargetPoint point )
{
networkWrapper.sendToAllAround( packet, point );
}
public static boolean canPlayerUseCommands( EntityPlayer player )
{
MinecraftServer server = player.getServer();
if( server != null )
{
return server.getPlayerList().canSendCommands( player.getGameProfile() );
}
return false;
}
@Deprecated
public static void registerPermissionProvider( ITurtlePermissionProvider provider )
{
TurtlePermissions.register( provider );
}
@Deprecated
public static void registerPocketUpgrade( IPocketUpgrade upgrade )
{
dan200.computercraft.shared.PocketUpgrades.register( upgrade );
}
@Deprecated
public static void registerPeripheralProvider( IPeripheralProvider provider )
{
Peripherals.register( provider );
}
@Deprecated
public static void registerBundledRedstoneProvider( IBundledRedstoneProvider provider )
{
BundledRedstone.register( provider );
}
@Deprecated
public static void registerMediaProvider( IMediaProvider provider )
{
MediaProviders.register( provider );
}
@Deprecated
public static void registerAPIFactory( ILuaAPIFactory factory )
{
ApiFactories.register( factory );
}
@Deprecated
public static IWiredNode createWiredNodeForElement( IWiredElement element )
{
return new WiredNode( element );
}
@Deprecated
public static IWiredElement getWiredElementAt( IBlockAccess world, BlockPos pos, EnumFacing side )
{
TileEntity tile = world.getTileEntity( pos );
return tile != null && tile.hasCapability( CapabilityWiredElement.CAPABILITY, side )
? tile.getCapability( CapabilityWiredElement.CAPABILITY, side )
: null;
}
@Deprecated
public static int getDefaultBundledRedstoneOutput( World world, BlockPos pos, EnumFacing side )
{
return BundledRedstone.getDefaultOutput( world, pos, side );
}
@Deprecated
public static IPacketNetwork getWirelessNetwork()
{
return WirelessNetwork.getUniversal();
}
@Deprecated
public static int createUniqueNumberedSaveDir( World world, String parentSubPath )
{
return IDAssigner.getNextIDFromDirectory( new File( getWorldDir( world ), parentSubPath ) );
}
@Deprecated
public static IWritableMount createSaveDirMount( World world, String subPath, long capacity )
{
try
{
return new FileMount( new File( getWorldDir( world ), subPath ), capacity );
}
catch( Exception e )
{
return null;
}
}
@Deprecated
public static IMount createResourceMount( Class<?> modClass, String domain, String subPath )
{
// Start building list of mounts
List<IMount> mounts = new ArrayList<>();
subPath = "assets/" + domain + "/" + subPath;
// Mount from debug dir
File codeDir = getDebugCodeDir( modClass );
if( codeDir != null )
{
File subResource = new File( codeDir, subPath );
if( subResource.exists() )
{
IMount resourcePackMount = new FileMount( subResource, 0 );
mounts.add( resourcePackMount );
}
}
// Mount from mod jar
File modJar = getContainingJar( modClass );
if( modJar != null )
{
try
{
FileSystem fs = FileSystems.newFileSystem( modJar.toPath(), ComputerCraft.class.getClassLoader() );
mounts.add( new FileSystemMount( fs, subPath ) );
}
catch( IOException | RuntimeException | ServiceConfigurationError e )
{
ComputerCraft.log.error( "Could not load mount from mod jar", e );
// Ignore
}
}
// Mount from resource packs
File resourcePackDir = getResourcePackDir();
if( resourcePackDir.exists() && resourcePackDir.isDirectory() )
{
String[] resourcePacks = resourcePackDir.list();
for( String resourcePackName : resourcePacks )
{
try
{
File resourcePack = new File( resourcePackDir, resourcePackName );
if( !resourcePack.isDirectory() )
{
// Mount a resource pack from a jar
FileSystem fs = FileSystems.newFileSystem( resourcePack.toPath(), ComputerCraft.class.getClassLoader() );
if( Files.exists( fs.getPath( subPath ) ) ) mounts.add( new FileSystemMount( fs, subPath ) );
}
else
{
// Mount a resource pack from a folder
File subResource = new File( resourcePack, subPath );
if( subResource.exists() )
{
IMount resourcePackMount = new FileMount( subResource, 0 );
mounts.add( resourcePackMount );
}
}
}
catch( IOException | RuntimeException | ServiceConfigurationError e )
{
ComputerCraft.log.error( "Could not load resource pack '" + resourcePackName + "'", e );
}
}
}
// Return the combination of all the mounts found
if( mounts.size() >= 2 )
{
IMount[] mountArray = new IMount[mounts.size()];
mounts.toArray( mountArray );
return new ComboMount( mountArray );
}
else if( mounts.size() == 1 )
{
return mounts.get( 0 );
}
else
{
return null;
}
}
public static InputStream getResourceFile( Class<?> modClass, String domain, String subPath )
{
// Start searching in possible locations
subPath = "assets/" + domain + "/" + subPath;
// Look in resource packs
File resourcePackDir = getResourcePackDir();
if( resourcePackDir.exists() && resourcePackDir.isDirectory() )
{
String[] resourcePacks = resourcePackDir.list();
for( String resourcePackPath : resourcePacks )
{
File resourcePack = new File( resourcePackDir, resourcePackPath );
if( resourcePack.isDirectory() )
{
// Mount a resource pack from a folder
File subResource = new File( resourcePack, subPath );
if( subResource.exists() && subResource.isFile() )
{
try
{
return new FileInputStream( subResource );
}
catch( FileNotFoundException ignored )
{
}
}
}
else
{
ZipFile zipFile = null;
try
{
final ZipFile zip = zipFile = new ZipFile( resourcePack );
ZipEntry entry = zipFile.getEntry( subPath );
if( entry != null )
{
// Return a custom InputStream which will close the original zip when finished.
return new FilterInputStream( zipFile.getInputStream( entry ) )
{
@Override
public void close() throws IOException
{
super.close();
zip.close();
}
};
}
else
{
IoUtil.closeQuietly( zipFile );
}
}
catch( IOException e )
{
if( zipFile != null ) IoUtil.closeQuietly( zipFile );
}
}
}
}
// Look in debug dir
File codeDir = getDebugCodeDir( modClass );
if( codeDir != null )
{
File subResource = new File( codeDir, subPath );
if( subResource.exists() && subResource.isFile() )
{
try
{
return new FileInputStream( subResource );
}
catch( FileNotFoundException ignored )
{
}
}
}
// Look in class loader
return modClass.getClassLoader().getResourceAsStream( subPath );
}
private static File getContainingJar( Class<?> modClass )
{
String path = modClass.getProtectionDomain().getCodeSource().getLocation().getPath();
int bangIndex = path.indexOf( "!" );
if( bangIndex >= 0 )
{
path = path.substring( 0, bangIndex );
}
URL url;
try
{
url = new URL( path );
}
catch( MalformedURLException e1 )
{
return null;
}
File file;
try
{
file = new File( url.toURI() );
}
catch( URISyntaxException e )
{
file = new File( url.getPath() );
}
return file;
}
private static File getDebugCodeDir( Class<?> modClass )
{
String path = modClass.getProtectionDomain().getCodeSource().getLocation().getPath();
int bangIndex = path.indexOf( "!" );
return bangIndex >= 0 ? null : new File( new File( path ).getParentFile(), "../.." );
}
@Deprecated
public static void registerTurtleUpgrade( ITurtleUpgrade upgrade )
{
TurtleUpgrades.register( upgrade );
}
//region Compatibility
@Deprecated
public static IMedia getMedia( ItemStack stack )
{
return MediaProviders.get( stack );
}
@Deprecated
public static IPocketUpgrade getPocketUpgrade( ItemStack stack )
{
return dan200.computercraft.shared.PocketUpgrades.get( stack );
}
@Deprecated
public static ITurtleUpgrade getTurtleUpgrade( ItemStack stack )
{
return TurtleUpgrades.get( stack );
}
@Deprecated
public static IPocketUpgrade getPocketUpgrade( String id )
{
return dan200.computercraft.shared.PocketUpgrades.get( id );
}
@Deprecated
public static ITurtleUpgrade getTurtleUpgrade( String id )
{
return TurtleUpgrades.get( id );
}
@Deprecated
public static IPeripheral getPeripheralAt( World world, BlockPos pos, EnumFacing side )
{
return Peripherals.getPeripheral( world, pos, side );
}
//endregion
}

View File

@@ -0,0 +1,182 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import dan200.computercraft.api.ComputerCraftAPI.IComputerCraftAPI;
import dan200.computercraft.api.filesystem.IMount;
import dan200.computercraft.api.filesystem.IWritableMount;
import dan200.computercraft.api.lua.GenericSource;
import dan200.computercraft.api.lua.ILuaAPIFactory;
import dan200.computercraft.api.media.IMediaProvider;
import dan200.computercraft.api.network.IPacketNetwork;
import dan200.computercraft.api.network.wired.IWiredElement;
import dan200.computercraft.api.network.wired.IWiredNode;
import dan200.computercraft.api.peripheral.IPeripheralProvider;
import dan200.computercraft.api.pocket.IPocketUpgrade;
import dan200.computercraft.api.redstone.IBundledRedstoneProvider;
import dan200.computercraft.api.turtle.ITurtleUpgrade;
import dan200.computercraft.core.apis.ApiFactories;
import dan200.computercraft.core.asm.GenericMethod;
import dan200.computercraft.core.filesystem.FileMount;
import dan200.computercraft.core.filesystem.ResourceMount;
import dan200.computercraft.fabric.mixin.MinecraftServerAccess;
import dan200.computercraft.shared.BundledRedstone;
import dan200.computercraft.shared.MediaProviders;
import dan200.computercraft.shared.Peripherals;
import dan200.computercraft.shared.PocketUpgrades;
import dan200.computercraft.shared.TurtleUpgrades;
import dan200.computercraft.shared.peripheral.modem.wired.TileCable;
import dan200.computercraft.shared.peripheral.modem.wired.TileWiredModemFull;
import dan200.computercraft.shared.peripheral.modem.wireless.WirelessNetwork;
import dan200.computercraft.shared.util.IDAssigner;
import dan200.computercraft.shared.wired.WiredNode;
import me.shedaniel.cloth.api.utils.v1.GameInstanceUtils;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.resource.ReloadableResourceManager;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import net.fabricmc.loader.api.FabricLoader;
public final class ComputerCraftAPIImpl implements IComputerCraftAPI {
public static final ComputerCraftAPIImpl INSTANCE = new ComputerCraftAPIImpl();
private String version;
private ComputerCraftAPIImpl() {
}
public static InputStream getResourceFile(String domain, String subPath) {
MinecraftServer server = GameInstanceUtils.getServer();
if (server != null) {
ReloadableResourceManager manager = (ReloadableResourceManager) ((MinecraftServerAccess)server).getServerResourceManager().getResourceManager();
try {
return manager.getResource(new Identifier(domain, subPath))
.getInputStream();
} catch (IOException ignored) {
return null;
}
}
return null;
}
@Nonnull
@Override
public String getInstalledVersion() {
if (this.version != null) {
return this.version;
}
return this.version = FabricLoader.getInstance()
.getModContainer(ComputerCraft.MOD_ID)
.map(x -> x.getMetadata()
.getVersion()
.toString())
.orElse("unknown");
}
@Override
public int createUniqueNumberedSaveDir(@Nonnull World world, @Nonnull String parentSubPath) {
return IDAssigner.getNextId(parentSubPath);
}
@Override
public IWritableMount createSaveDirMount(@Nonnull World world, @Nonnull String subPath, long capacity) {
try {
return new FileMount(new File(IDAssigner.getDir(), subPath), capacity);
} catch (Exception e) {
return null;
}
}
@Override
public IMount createResourceMount(@Nonnull String domain, @Nonnull String subPath) {
MinecraftServer server = GameInstanceUtils.getServer();
if (server != null) {
ReloadableResourceManager manager = (ReloadableResourceManager) ((MinecraftServerAccess)server).getServerResourceManager().getResourceManager();
ResourceMount mount = ResourceMount.get(domain, subPath, manager);
return mount.exists("") ? mount : null;
}
return null;
}
@Override
public void registerPeripheralProvider(@Nonnull IPeripheralProvider provider) {
Peripherals.register(provider);
}
@Override
public void registerTurtleUpgrade(@Nonnull ITurtleUpgrade upgrade) {
TurtleUpgrades.register(upgrade);
}
@Override
public void registerBundledRedstoneProvider(@Nonnull IBundledRedstoneProvider provider) {
BundledRedstone.register(provider);
}
@Override
public int getBundledRedstoneOutput(@Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side) {
return BundledRedstone.getDefaultOutput(world, pos, side);
}
@Override
public void registerMediaProvider(@Nonnull IMediaProvider provider) {
MediaProviders.register(provider);
}
@Override
public void registerPocketUpgrade(@Nonnull IPocketUpgrade upgrade) {
PocketUpgrades.register(upgrade);
}
@Override
public void registerGenericSource( @Nonnull GenericSource source )
{
GenericMethod.register( source );
}
@Nonnull
@Override
public IPacketNetwork getWirelessNetwork() {
return WirelessNetwork.getUniversal();
}
@Override
public void registerAPIFactory(@Nonnull ILuaAPIFactory factory) {
ApiFactories.register(factory);
}
@Nonnull
@Override
public IWiredNode createWiredNodeForElement(@Nonnull IWiredElement element) {
return new WiredNode(element);
}
@Nullable
@Override
public IWiredElement getWiredElementAt(@Nonnull BlockView world, @Nonnull BlockPos pos, @Nonnull Direction side) {
BlockEntity tile = world.getBlockEntity(pos);
if (tile instanceof TileCable) {
return ((TileCable) tile).getElement(side);
} else if (tile instanceof TileWiredModemFull) {
return ((TileWiredModemFull) tile).getElement();
}
return null;
}
}

View File

@@ -1,13 +1,17 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import dan200.computercraft.api.filesystem.IMount;
import dan200.computercraft.api.filesystem.IWritableMount;
import dan200.computercraft.api.lua.GenericSource;
import dan200.computercraft.api.lua.ILuaAPIFactory;
import dan200.computercraft.api.media.IMedia;
import dan200.computercraft.api.media.IMediaProvider;
@@ -17,54 +21,47 @@ import dan200.computercraft.api.network.wired.IWiredNode;
import dan200.computercraft.api.peripheral.IComputerAccess;
import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.api.peripheral.IPeripheralProvider;
import dan200.computercraft.api.permissions.ITurtlePermissionProvider;
import dan200.computercraft.api.pocket.IPocketUpgrade;
import dan200.computercraft.api.redstone.IBundledRedstoneProvider;
import dan200.computercraft.api.turtle.ITurtleUpgrade;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.lang.reflect.Method;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
/**
* The static entry point to the ComputerCraft API.
* Members in this class must be called after mod_ComputerCraft has been initialised,
* but may be called before it is fully loaded.
*
* Members in this class must be called after mod_ComputerCraft has been initialised, but may be called before it is fully loaded.
*/
public final class ComputerCraftAPI
{
public static boolean isInstalled()
{
findCC();
return computerCraft != null;
public final class ComputerCraftAPI {
private static IComputerCraftAPI instance;
@Nonnull
@Deprecated
public static String getAPIVersion() {
return getInstalledVersion();
}
@Nonnull
public static String getInstalledVersion()
{
findCC();
if( computerCraft_getVersion != null )
{
try
{
return (String) computerCraft_getVersion.invoke( null );
}
catch( Exception e )
{
// It failed
}
public static String getInstalledVersion() {
return getInstance().getInstalledVersion();
}
@Nonnull
private static IComputerCraftAPI getInstance() {
if (instance != null) {
return instance;
}
return "";
}
@Nonnull
public static String getAPIVersion()
{
return "${version}";
try {
return instance = (IComputerCraftAPI) Class.forName("dan200.computercraft.ComputerCraftAPIImpl")
.getField("INSTANCE")
.get(null);
} catch (ReflectiveOperationException e) {
throw new IllegalStateException("Cannot find ComputerCraft API", e);
}
}
/**
@@ -72,43 +69,29 @@ public final class ComputerCraftAPI
*
* Use in conjunction with createSaveDirMount() to create a unique place for your peripherals or media items to store files.
*
* @param world The world for which the save dir should be created. This should be the server side world object.
* @param world The world for which the save dir should be created. This should be the server side world object.
* @param parentSubPath The folder path within the save directory where the new directory should be created. eg: "computercraft/disk"
* @return The numerical value of the name of the new folder, or -1 if the folder could not be created for some reason.
*
* eg: if createUniqueNumberedSaveDir( world, "computer/disk" ) was called returns 42, then "computer/disk/42" is now
* available for writing.
* eg: if createUniqueNumberedSaveDir( world, "computer/disk" ) was called returns 42, then "computer/disk/42" is now available for writing.
* @see #createSaveDirMount(World, String, long)
*/
public static int createUniqueNumberedSaveDir( @Nonnull World world, @Nonnull String parentSubPath )
{
findCC();
if( computerCraft_createUniqueNumberedSaveDir != null )
{
try
{
return (Integer) computerCraft_createUniqueNumberedSaveDir.invoke( null, world, parentSubPath );
}
catch( Exception e )
{
// It failed
}
}
return -1;
public static int createUniqueNumberedSaveDir(@Nonnull World world, @Nonnull String parentSubPath) {
return getInstance().createUniqueNumberedSaveDir(world, parentSubPath);
}
/**
* Creates a file system mount that maps to a subfolder of the save directory for a given world, and returns it.
*
* Use in conjunction with IComputerAccess.mount() or IComputerAccess.mountWritable() to mount a folder from the
* users save directory onto a computers file system.
* Use in conjunction with IComputerAccess.mount() or IComputerAccess.mountWritable() to mount a folder from the users save directory onto a computers
* file system.
*
* @param world The world for which the save dir can be found. This should be the server side world object.
* @param subPath The folder path within the save directory that the mount should map to. eg: "computer/disk/42".
* Use createUniqueNumberedSaveDir() to create a new numbered folder to use.
* @param world The world for which the save dir can be found. This should be the server side world object.
* @param subPath The folder path within the save directory that the mount should map to. eg: "computer/disk/42". Use createUniqueNumberedSaveDir()
* to create a new numbered folder to use.
* @param capacity The amount of data that can be stored in the directory before it fills up, in bytes.
* @return The mount, or null if it could be created for some reason. Use IComputerAccess.mount() or IComputerAccess.mountWritable()
* to mount this on a Computers' file system.
* @return The mount, or null if it could be created for some reason. Use IComputerAccess.mount() or IComputerAccess.mountWritable() to mount this on a
* Computers' file system.
* @see #createUniqueNumberedSaveDir(World, String)
* @see IComputerAccess#mount(String, IMount)
* @see IComputerAccess#mountWritable(String, IWritableMount)
@@ -116,218 +99,102 @@ public final class ComputerCraftAPI
* @see IWritableMount
*/
@Nullable
public static IWritableMount createSaveDirMount( @Nonnull World world, @Nonnull String subPath, long capacity )
{
findCC();
if( computerCraft_createSaveDirMount != null )
{
try
{
return (IWritableMount) computerCraft_createSaveDirMount.invoke( null, world, subPath, capacity );
}
catch( Exception e )
{
// It failed
}
}
return null;
public static IWritableMount createSaveDirMount(@Nonnull World world, @Nonnull String subPath, long capacity) {
return getInstance().createSaveDirMount(world, subPath, capacity);
}
/**
* Creates a file system mount to a resource folder, and returns it.
*
* Use in conjunction with IComputerAccess.mount() or IComputerAccess.mountWritable() to mount a resource folder
* onto a computer's file system.
* Use in conjunction with {@link IComputerAccess#mount} or {@link IComputerAccess#mountWritable} to mount a resource folder onto a computer's file
* system.
*
* The files in this mount will be a combination of files in the specified mod jar, and resource packs that contain
* resources with the same domain and path.
* The files in this mount will be a combination of files in all mod jar, and data packs that contain
* resources with the same domain and path. For instance, ComputerCraft's resources are stored in
* "/data/computercraft/lua/rom". We construct a mount for that with
* {@code createResourceMount("computercraft", "lua/rom")}.
*
* @param modClass A class in whose jar to look first for the resources to mount. Using your main mod class is recommended. eg: MyMod.class
* @param domain The domain under which to look for resources. eg: "mymod".
* @param subPath The domain under which to look for resources. eg: "mymod/lua/myfiles".
* @return The mount, or {@code null} if it could be created for some reason. Use IComputerAccess.mount() or
* IComputerAccess.mountWritable() to mount this on a Computers' file system.
* @param domain The domain under which to look for resources. eg: "mymod".
* @param subPath The subPath under which to look for resources. eg: "lua/myfiles".
* @return The mount, or {@code null} if it could be created for some reason.
* @see IComputerAccess#mount(String, IMount)
* @see IComputerAccess#mountWritable(String, IWritableMount)
* @see IMount
*/
@Nullable
public static IMount createResourceMount( @Nonnull Class<?> modClass, @Nonnull String domain, @Nonnull String subPath )
{
findCC();
if( computerCraft_createResourceMount != null )
{
try
{
return (IMount) computerCraft_createResourceMount.invoke( null, modClass, domain, subPath );
}
catch( Exception e )
{
// It failed
}
}
return null;
public static IMount createResourceMount(@Nonnull String domain, @Nonnull String subPath) {
return getInstance().createResourceMount(domain, subPath);
}
/**
* Registers a peripheral provider to convert blocks into {@link IPeripheral} implementations.
*
* @param provider The peripheral provider to register.
* @see dan200.computercraft.api.peripheral.IPeripheral
* @see dan200.computercraft.api.peripheral.IPeripheralProvider
* @see IPeripheral
* @see IPeripheralProvider
*/
public static void registerPeripheralProvider( @Nonnull IPeripheralProvider provider )
{
findCC();
if( computerCraft_registerPeripheralProvider != null )
{
try
{
computerCraft_registerPeripheralProvider.invoke( null, provider );
}
catch( Exception e )
{
// It failed
}
}
public static void registerPeripheralProvider(@Nonnull IPeripheralProvider provider) {
getInstance().registerPeripheralProvider(provider);
}
/**
* Registers a new turtle turtle for use in ComputerCraft. After calling this,
* users should be able to craft Turtles with your new turtle. It is recommended to call
* this during the load() method of your mod.
* Registers a method source for generic peripherals.
*
* @param source The method source to register.
* @see GenericSource
*/
public static void registerGenericSource( @Nonnull GenericSource source )
{
getInstance().registerGenericSource( source );
}
/**
* Registers a new turtle turtle for use in ComputerCraft. After calling this, users should be able to craft Turtles with your new turtle. It is
* recommended to call this during the load() method of your mod.
*
* @param upgrade The turtle upgrade to register.
* @see dan200.computercraft.api.turtle.ITurtleUpgrade
* @see ITurtleUpgrade
*/
public static void registerTurtleUpgrade( @Nonnull ITurtleUpgrade upgrade )
{
if( upgrade != null )
{
findCC();
if( computerCraft_registerTurtleUpgrade != null )
{
try
{
computerCraft_registerTurtleUpgrade.invoke( null, upgrade );
}
catch( Exception e )
{
// It failed
}
}
}
public static void registerTurtleUpgrade(@Nonnull ITurtleUpgrade upgrade) {
getInstance().registerTurtleUpgrade(upgrade);
}
/**
* Registers a bundled redstone provider to provide bundled redstone output for blocks.
*
* @param provider The bundled redstone provider to register.
* @see dan200.computercraft.api.redstone.IBundledRedstoneProvider
* @see IBundledRedstoneProvider
*/
public static void registerBundledRedstoneProvider( @Nonnull IBundledRedstoneProvider provider )
{
findCC();
if( computerCraft_registerBundledRedstoneProvider != null )
{
try
{
computerCraft_registerBundledRedstoneProvider.invoke( null, provider );
}
catch( Exception e )
{
// It failed
}
}
public static void registerBundledRedstoneProvider(@Nonnull IBundledRedstoneProvider provider) {
getInstance().registerBundledRedstoneProvider(provider);
}
/**
* If there is a Computer or Turtle at a certain position in the world, get it's bundled redstone output.
*
* @param world The world this block is in.
* @param pos The position this block is at.
* @param side The side to extract the bundled redstone output from.
* @return If there is a block capable of emitting bundled redstone at the location, it's signal (0-65535) will be returned.
* If there is no block capable of emitting bundled redstone at the location, -1 will be returned.
* @see dan200.computercraft.api.redstone.IBundledRedstoneProvider
* @param pos The position this block is at.
* @param side The side to extract the bundled redstone output from.
* @return If there is a block capable of emitting bundled redstone at the location, it's signal (0-65535) will be returned. If there is no block
* capable of emitting bundled redstone at the location, -1 will be returned.
* @see IBundledRedstoneProvider
*/
public static int getBundledRedstoneOutput( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull EnumFacing side )
{
findCC();
if( computerCraft_getDefaultBundledRedstoneOutput != null )
{
try
{
return (Integer) computerCraft_getDefaultBundledRedstoneOutput.invoke( null, world, pos, side );
}
catch( Exception e )
{
// It failed
}
}
return -1;
public static int getBundledRedstoneOutput(@Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side) {
return getInstance().getBundledRedstoneOutput(world, pos, side);
}
/**
* Registers a media provider to provide {@link IMedia} implementations for Items
* Registers a media provider to provide {@link IMedia} implementations for Items.
*
* @param provider The media provider to register.
* @see dan200.computercraft.api.media.IMediaProvider
* @see IMediaProvider
*/
public static void registerMediaProvider( @Nonnull IMediaProvider provider )
{
findCC();
if( computerCraft_registerMediaProvider != null )
{
try
{
computerCraft_registerMediaProvider.invoke( null, provider );
}
catch( Exception e )
{
// It failed
}
}
public static void registerMediaProvider(@Nonnull IMediaProvider provider) {
getInstance().registerMediaProvider(provider);
}
/**
* Registers a permission provider to restrict where turtles can move or build.
*
* @param provider The turtle permission provider to register.
* @see dan200.computercraft.api.permissions.ITurtlePermissionProvider
* @deprecated Prefer using {@link dan200.computercraft.api.turtle.event.TurtleBlockEvent} or the standard Forge events.
*/
@Deprecated
public static void registerPermissionProvider( @Nonnull ITurtlePermissionProvider provider )
{
findCC();
if( computerCraft_registerPermissionProvider != null )
{
try
{
computerCraft_registerPermissionProvider.invoke( null, provider );
}
catch( Exception e )
{
// It failed
}
}
}
public static void registerPocketUpgrade( @Nonnull IPocketUpgrade upgrade )
{
findCC();
if( computerCraft_registerPocketUpgrade != null )
{
try
{
computerCraft_registerPocketUpgrade.invoke( null, upgrade );
}
catch( Exception e )
{
// It failed
}
}
public static void registerPocketUpgrade(@Nonnull IPocketUpgrade upgrade) {
getInstance().registerPocketUpgrade(upgrade);
}
/**
@@ -335,189 +202,75 @@ public final class ComputerCraftAPI
*
* @return The global wireless network, or {@code null} if it could not be fetched.
*/
public static IPacketNetwork getWirelessNetwork()
{
findCC();
if( computerCraft_getWirelessNetwork != null )
{
try
{
return (IPacketNetwork) computerCraft_getWirelessNetwork.invoke( null );
}
catch( Exception e )
{
// It failed;
}
}
return null;
public static IPacketNetwork getWirelessNetwork() {
return getInstance().getWirelessNetwork();
}
public static void registerAPIFactory( @Nonnull ILuaAPIFactory upgrade )
{
findCC();
if( computerCraft_registerAPIFactory != null )
{
try
{
computerCraft_registerAPIFactory.invoke( null, upgrade );
}
catch( Exception e )
{
// It failed
}
}
public static void registerAPIFactory(@Nonnull ILuaAPIFactory factory) {
getInstance().registerAPIFactory(factory);
}
/**
* Construct a new wired node for a given wired element
* Construct a new wired node for a given wired element.
*
* @param element The element to construct it for
* @return The element's node
* @see IWiredElement#getNode()
*/
@Nonnull
public static IWiredNode createWiredNodeForElement( @Nonnull IWiredElement element )
{
findCC();
if( computerCraft_createWiredNodeForElement != null )
{
try
{
return (IWiredNode) computerCraft_createWiredNodeForElement.invoke( null, element );
}
catch( ReflectiveOperationException e )
{
throw new IllegalStateException( "Error creating wired node", e );
}
}
else
{
throw new IllegalStateException( "ComputerCraft cannot be found" );
}
public static IWiredNode createWiredNodeForElement(@Nonnull IWiredElement element) {
return getInstance().createWiredNodeForElement(element);
}
/**
* Get the wired network element for a block in world
* Get the wired network element for a block in world.
*
* @param world The world the block exists in
* @param pos The position the block exists in
* @param side The side to extract the network element from
* @param pos The position the block exists in
* @param side The side to extract the network element from
* @return The element's node
* @see IWiredElement#getNode()
*/
@Nullable
public static IWiredElement getWiredElementAt( @Nonnull IBlockAccess world, @Nonnull BlockPos pos, @Nonnull EnumFacing side )
{
findCC();
if( computerCraft_getWiredElementAt != null )
{
try
{
return (IWiredElement) computerCraft_getWiredElementAt.invoke( null, world, pos, side );
}
catch( ReflectiveOperationException ignored )
{
}
}
return null;
public static IWiredElement getWiredElementAt(@Nonnull BlockView world, @Nonnull BlockPos pos, @Nonnull Direction side) {
return getInstance().getWiredElementAt(world, pos, side);
}
// The functions below here are private, and are used to interface with the non-API ComputerCraft classes.
// Reflection is used here so you can develop your mod without decompiling ComputerCraft and including
// it in your solution, and so your mod won't crash if ComputerCraft is installed.
public interface IComputerCraftAPI {
@Nonnull
String getInstalledVersion();
private static void findCC()
{
if( !ccSearched )
{
try
{
computerCraft = Class.forName( "dan200.computercraft.ComputerCraft" );
computerCraft_getVersion = findCCMethod( "getVersion", new Class<?>[] {
} );
computerCraft_createUniqueNumberedSaveDir = findCCMethod( "createUniqueNumberedSaveDir", new Class<?>[] {
World.class, String.class
} );
computerCraft_createSaveDirMount = findCCMethod( "createSaveDirMount", new Class<?>[] {
World.class, String.class, Long.TYPE
} );
computerCraft_createResourceMount = findCCMethod( "createResourceMount", new Class<?>[] {
Class.class, String.class, String.class
} );
computerCraft_registerPeripheralProvider = findCCMethod( "registerPeripheralProvider", new Class<?>[] {
IPeripheralProvider.class
} );
computerCraft_registerTurtleUpgrade = findCCMethod( "registerTurtleUpgrade", new Class<?>[] {
ITurtleUpgrade.class
} );
computerCraft_registerBundledRedstoneProvider = findCCMethod( "registerBundledRedstoneProvider", new Class<?>[] {
IBundledRedstoneProvider.class
} );
computerCraft_getDefaultBundledRedstoneOutput = findCCMethod( "getDefaultBundledRedstoneOutput", new Class<?>[] {
World.class, BlockPos.class, EnumFacing.class
} );
computerCraft_registerMediaProvider = findCCMethod( "registerMediaProvider", new Class<?>[] {
IMediaProvider.class
} );
computerCraft_registerPermissionProvider = findCCMethod( "registerPermissionProvider", new Class<?>[] {
ITurtlePermissionProvider.class
} );
computerCraft_registerPocketUpgrade = findCCMethod( "registerPocketUpgrade", new Class<?>[] {
IPocketUpgrade.class
} );
computerCraft_getWirelessNetwork = findCCMethod( "getWirelessNetwork", new Class<?>[] {
} );
computerCraft_registerAPIFactory = findCCMethod( "registerAPIFactory", new Class<?>[] {
ILuaAPIFactory.class
} );
computerCraft_createWiredNodeForElement = findCCMethod( "createWiredNodeForElement", new Class<?>[] {
IWiredElement.class
} );
computerCraft_getWiredElementAt = findCCMethod( "getWiredElementAt", new Class<?>[] {
IBlockAccess.class, BlockPos.class, EnumFacing.class
} );
}
catch( Exception e )
{
System.out.println( "ComputerCraftAPI: ComputerCraft not found." );
}
finally
{
ccSearched = true;
}
}
int createUniqueNumberedSaveDir(@Nonnull World world, @Nonnull String parentSubPath);
@Nullable
IWritableMount createSaveDirMount(@Nonnull World world, @Nonnull String subPath, long capacity);
@Nullable
IMount createResourceMount(@Nonnull String domain, @Nonnull String subPath);
void registerPeripheralProvider(@Nonnull IPeripheralProvider provider);
void registerGenericSource( @Nonnull GenericSource source );
void registerTurtleUpgrade(@Nonnull ITurtleUpgrade upgrade);
void registerBundledRedstoneProvider(@Nonnull IBundledRedstoneProvider provider);
int getBundledRedstoneOutput(@Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side);
void registerMediaProvider(@Nonnull IMediaProvider provider);
void registerPocketUpgrade(@Nonnull IPocketUpgrade upgrade);
@Nonnull
IPacketNetwork getWirelessNetwork();
void registerAPIFactory(@Nonnull ILuaAPIFactory factory);
@Nonnull
IWiredNode createWiredNodeForElement(@Nonnull IWiredElement element);
@Nullable
IWiredElement getWiredElementAt(@Nonnull BlockView world, @Nonnull BlockPos pos, @Nonnull Direction side);
}
private static Method findCCMethod( String name, Class<?>[] args )
{
try
{
return computerCraft != null ? computerCraft.getMethod( name, args ) : null;
}
catch( NoSuchMethodException e )
{
System.out.println( "ComputerCraftAPI: ComputerCraft method " + name + " not found." );
return null;
}
}
private static boolean ccSearched = false;
private static Class<?> computerCraft = null;
private static Method computerCraft_getVersion = null;
private static Method computerCraft_createUniqueNumberedSaveDir = null;
private static Method computerCraft_createSaveDirMount = null;
private static Method computerCraft_createResourceMount = null;
private static Method computerCraft_registerPeripheralProvider = null;
private static Method computerCraft_registerTurtleUpgrade = null;
private static Method computerCraft_registerBundledRedstoneProvider = null;
private static Method computerCraft_getDefaultBundledRedstoneOutput = null;
private static Method computerCraft_registerMediaProvider = null;
private static Method computerCraft_registerPermissionProvider = null;
private static Method computerCraft_registerPocketUpgrade = null;
private static Method computerCraft_getWirelessNetwork = null;
private static Method computerCraft_registerAPIFactory = null;
private static Method computerCraft_createWiredNodeForElement = null;
private static Method computerCraft_getWiredElementAt = null;
}

View File

@@ -0,0 +1,86 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api;
import dan200.computercraft.api.pocket.IPocketUpgrade;
import dan200.computercraft.api.turtle.ITurtleUpgrade;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.util.Identifier;
import javax.annotation.Nonnull;
/**
* Common functionality between {@link ITurtleUpgrade} and {@link IPocketUpgrade}.
*/
public interface IUpgradeBase
{
/**
* Gets a unique identifier representing this type of turtle upgrade. eg: "computercraft:wireless_modem"
* or "my_mod:my_upgrade".
*
* You should use a unique resource domain to ensure this upgrade is uniquely identified.
* The upgrade will fail registration if an already used ID is specified.
*
* @return The unique ID for this upgrade.
*/
@Nonnull
Identifier getUpgradeID();
/**
* Return an unlocalised string to describe this type of computer in item names.
*
* Examples of built-in adjectives are "Wireless", "Mining" and "Crafty".
*
* @return The localisation key for this upgrade's adjective.
*/
@Nonnull
String getUnlocalisedAdjective();
/**
* Return an item stack representing the type of item that a computer must be crafted
* with to create a version which holds this upgrade. This item stack is also used
* to determine the upgrade given by {@code turtle.equipLeft()} or {@code pocket.equipBack()}
*
* This should be constant over a session (or at least a datapack reload). It is recommended
* that you cache the stack too, in order to prevent constructing it every time the method
* is called.
*
* @return The item stack to craft with, or {@link ItemStack#EMPTY} if it cannot be crafted.
*/
@Nonnull
ItemStack getCraftingItem();
/**
* Determine if an item is suitable for being used for this upgrade.
*
* When un-equipping an upgrade, we return {@link #getCraftingItem()} rather than
* the original stack. In order to prevent people losing items with enchantments (or
* repairing items with non-0 damage), we impose additional checks on the item.
*
* The default check requires that any non-capability NBT is exactly the same as the
* crafting item, but this may be relaxed for your upgrade.
*
* @param stack The stack to check. This is guaranteed to be non-empty and have the same item as
* {@link #getCraftingItem()}.
* @return If this stack may be used to equip this upgrade.
* @see net.minecraftforge.common.crafting.NBTIngredient#test(ItemStack) For the implementation of the default
* check.
*/
default boolean isItemSuitable( @Nonnull ItemStack stack )
{
ItemStack crafting = getCraftingItem();
// A more expanded form of ItemStack.areShareTagsEqual, but allowing an empty tag to be equal to a
// null one.
CompoundTag shareTag = stack.getTag();
CompoundTag craftingShareTag = crafting.getTag();
if( shareTag == craftingShareTag ) return true;
if( shareTag == null ) return craftingShareTag.isEmpty();
if( craftingShareTag == null ) return shareTag.isEmpty();
return shareTag.equals( craftingShareTag );
}
}

View File

@@ -0,0 +1,83 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.client;
import java.util.Objects;
import javax.annotation.Nonnull;
import dan200.computercraft.fabric.mixin.AffineTransformationAccess;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.BakedModelManager;
import net.minecraft.client.util.ModelIdentifier;
import net.minecraft.client.util.math.AffineTransformation;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.item.ItemStack;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
/**
* A model to render, combined with a transformation matrix to apply.
*/
@Environment (EnvType.CLIENT)
public final class TransformedModel {
private final BakedModel model;
private final AffineTransformation matrix;
public TransformedModel(@Nonnull BakedModel model, @Nonnull AffineTransformation matrix) {
this.model = Objects.requireNonNull(model);
this.matrix = Objects.requireNonNull(matrix);
}
public TransformedModel(@Nonnull BakedModel model) {
this.model = Objects.requireNonNull(model);
this.matrix = AffineTransformation.identity();
}
public static TransformedModel of(@Nonnull ModelIdentifier location) {
BakedModelManager modelManager = MinecraftClient.getInstance()
.getBakedModelManager();
return new TransformedModel(modelManager.getModel(location));
}
public static TransformedModel of(@Nonnull ItemStack item, @Nonnull AffineTransformation transform) {
BakedModel model = MinecraftClient.getInstance()
.getItemRenderer()
.getModels()
.getModel(item);
return new TransformedModel(model, transform);
}
@Nonnull
public BakedModel getModel() {
return this.model;
}
@Nonnull
public AffineTransformation getMatrix() {
return this.matrix;
}
public void push(MatrixStack matrixStack) {
matrixStack.push();
AffineTransformationAccess access = (AffineTransformationAccess) (Object) this.matrix;
if (access.getTranslation() != null)
matrixStack.translate(access.getTranslation().getX(), access.getTranslation().getY(), access.getTranslation().getZ());
matrixStack.multiply(this.matrix.getRotation2());
if (access.getScale() != null)
matrixStack.scale(access.getScale().getX(), access.getScale().getY(), access.getScale().getZ());
if (access.getRotation1() != null)
matrixStack.multiply(access.getRotation1());
}
}

View File

@@ -0,0 +1,71 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.filesystem;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;
import java.time.Instant;
/**
* A simple version of {@link BasicFileAttributes}, which provides what information a {@link IMount} already exposes.
*/
final class FileAttributes implements BasicFileAttributes {
private static final FileTime EPOCH = FileTime.from(Instant.EPOCH);
private final boolean isDirectory;
private final long size;
FileAttributes(boolean isDirectory, long size) {
this.isDirectory = isDirectory;
this.size = size;
}
@Override
public FileTime lastModifiedTime() {
return EPOCH;
}
@Override
public FileTime lastAccessTime() {
return EPOCH;
}
@Override
public FileTime creationTime() {
return EPOCH;
}
@Override
public boolean isRegularFile() {
return !this.isDirectory;
}
@Override
public boolean isDirectory() {
return this.isDirectory;
}
@Override
public boolean isSymbolicLink() {
return false;
}
@Override
public boolean isOther() {
return false;
}
@Override
public long size() {
return this.size;
}
@Override
public Object fileKey() {
return null;
}
}

View File

@@ -0,0 +1,39 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.filesystem;
import java.io.IOException;
import java.util.Objects;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* An {@link IOException} which occurred on a specific file.
*
* This may be thrown from a {@link IMount} or {@link IWritableMount} to give more information about a failure.
*/
public class FileOperationException extends IOException {
private static final long serialVersionUID = -8809108200853029849L;
private final String filename;
public FileOperationException(@Nullable String filename, @Nonnull String message) {
super(Objects.requireNonNull(message, "message cannot be null"));
this.filename = filename;
}
public FileOperationException(@Nonnull String message) {
super(Objects.requireNonNull(message, "message cannot be null"));
this.filename = null;
}
@Nullable
public String getFilename() {
return this.filename;
}
}

View File

@@ -1,6 +1,6 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
@@ -13,32 +13,31 @@ import java.io.IOException;
*
* This exists for use by various APIs - one should not attempt to mount it.
*/
public interface IFileSystem extends IWritableMount
{
public interface IFileSystem extends IWritableMount {
/**
* Combine two paths together, reducing them into a normalised form.
*
* @param path The main path.
* @param path The main path.
* @param child The path to append.
* @return The combined, normalised path.
*/
String combine( String path, String child );
String combine(String path, String child);
/**
* Copy files from one location to another.
*
* @param from The location to copy from.
* @param to The location to copy to. This should not exist.
* @param to The location to copy to. This should not exist.
* @throws IOException If the copy failed.
*/
void copy( String from, String to ) throws IOException;
void copy(String from, String to) throws IOException;
/**
* Move files from one location to another.
*
* @param from The location to move from.
* @param to The location to move to. This should not exist.
* @param to The location to move to. This should not exist.
* @throws IOException If the move failed.
*/
void move( String from, String to ) throws IOException;
void move(String from, String to) throws IOException;
}

View File

@@ -1,37 +1,70 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.filesystem;
import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.peripheral.IComputerAccess;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
import java.io.IOException;
import java.io.InputStream;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.List;
import javax.annotation.Nonnull;
import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.peripheral.IComputerAccess;
import net.minecraft.world.World;
/**
* Represents a read only part of a virtual filesystem that can be mounted onto a computer using
* {@link IComputerAccess#mount(String, IMount)}
* Represents a read only part of a virtual filesystem that can be mounted onto a computer using {@link IComputerAccess#mount(String, IMount)}.
*
* Ready made implementations of this interface can be created using
* {@link ComputerCraftAPI#createSaveDirMount(World, String, long)} or
* {@link ComputerCraftAPI#createResourceMount(Class, String, String)}, or you're free to implement it yourselves!
* Ready made implementations of this interface can be created using {@link ComputerCraftAPI#createSaveDirMount(World, String, long)} or {@link
* ComputerCraftAPI#createResourceMount(String, String)}, or you're free to implement it yourselves!
*
* @see ComputerCraftAPI#createSaveDirMount(World, String, long)
* @see ComputerCraftAPI#createResourceMount(Class, String, String)
* @see ComputerCraftAPI#createResourceMount(String, String)
* @see IComputerAccess#mount(String, IMount)
* @see IWritableMount
*/
public interface IMount
{
public interface IMount {
/**
* Returns the file names of all the files in a directory.
*
* @param path A file path in normalised format, relative to the mount location. ie: "programs/myprograms".
* @param contents A list of strings. Add all the file names to this list.
* @throws IOException If the file was not a directory, or could not be listed.
*/
void list(@Nonnull String path, @Nonnull List<String> contents) throws IOException;
/**
* Opens a file with a given path, and returns an {@link ReadableByteChannel} representing its contents.
*
* @param path A file path in normalised format, relative to the mount location. ie: "programs/myprogram".
* @return A channel representing the contents of the file. If the channel implements {@link java.nio.channels.SeekableByteChannel}, one will be able to
* seek to arbitrary positions when using binary mode.
* @throws IOException If the file does not exist, or could not be opened.
*/
@Nonnull
ReadableByteChannel openForRead(@Nonnull String path) throws IOException;
/**
* Get attributes about the given file.
*
* @param path The path to query.
* @return File attributes for the given file.
* @throws IOException If the file does not exist, or attributes could not be fetched.
*/
@Nonnull
default BasicFileAttributes getAttributes(@Nonnull String path) throws IOException {
if (!this.exists(path)) {
throw new FileOperationException(path, "No such file");
}
return new FileAttributes(this.isDirectory(path), this.getSize(path));
}
/**
* Returns whether a file with a given path exists or not.
*
@@ -39,7 +72,7 @@ public interface IMount
* @return If the file exists.
* @throws IOException If an error occurs when checking the existence of the file.
*/
boolean exists( @Nonnull String path ) throws IOException;
boolean exists(@Nonnull String path) throws IOException;
/**
* Returns whether a file with a given path is a directory or not.
@@ -48,51 +81,14 @@ public interface IMount
* @return If the file exists and is a directory
* @throws IOException If an error occurs when checking whether the file is a directory.
*/
boolean isDirectory( @Nonnull String path ) throws IOException;
boolean isDirectory(@Nonnull String path) throws IOException;
/**
* Returns the file names of all the files in a directory.
*
* @param path A file path in normalised format, relative to the mount location. ie: "programs/myprograms".
* @param contents A list of strings. Add all the file names to this list.
* @throws IOException If the file was not a directory, or could not be listed.
*/
void list( @Nonnull String path, @Nonnull List<String> contents ) throws IOException;
/**
* Returns the size of a file with a given path, in bytes
* Returns the size of a file with a given path, in bytes.
*
* @param path A file path in normalised format, relative to the mount location. ie: "programs/myprogram".
* @return The size of the file, in bytes.
* @throws IOException If the file does not exist, or its size could not be determined.
*/
long getSize( @Nonnull String path ) throws IOException;
/**
* Opens a file with a given path, and returns an {@link InputStream} representing its contents.
*
* @param path A file path in normalised format, relative to the mount location. ie: "programs/myprogram".
* @return A stream representing the contents of the file.
* @throws IOException If the file does not exist, or could not be opened.
* @deprecated Use {@link #openChannelForRead(String)} instead
*/
@Nonnull
@Deprecated
InputStream openForRead( @Nonnull String path ) throws IOException;
/**
* Opens a file with a given path, and returns an {@link ReadableByteChannel} representing its contents.
*
* @param path A file path in normalised format, relative to the mount location. ie: "programs/myprogram".
* @return A channel representing the contents of the file. If the channel implements
* {@link java.nio.channels.SeekableByteChannel}, one will be able to seek to arbitrary positions when using binary
* mode.
* @throws IOException If the file does not exist, or could not be opened.
*/
@Nonnull
@SuppressWarnings( "deprecation" )
default ReadableByteChannel openChannelForRead( @Nonnull String path ) throws IOException
{
return Channels.newChannel( openForRead( path ) );
}
long getSize(@Nonnull String path) throws IOException;
}

View File

@@ -1,42 +1,43 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.filesystem;
import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.peripheral.IComputerAccess;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.channels.Channels;
import java.nio.channels.WritableByteChannel;
import java.util.OptionalLong;
import javax.annotation.Nonnull;
import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.peripheral.IComputerAccess;
import net.minecraft.world.World;
/**
* Represents a part of a virtual filesystem that can be mounted onto a computer using {@link IComputerAccess#mount(String, IMount)}
* or {@link IComputerAccess#mountWritable(String, IWritableMount)}, that can also be written to.
* Represents a part of a virtual filesystem that can be mounted onto a computer using {@link IComputerAccess#mount(String, IMount)} or {@link
* IComputerAccess#mountWritable(String, IWritableMount)}, that can also be written to.
*
* Ready made implementations of this interface can be created using
* {@link ComputerCraftAPI#createSaveDirMount(World, String, long)}, or you're free to implement it yourselves!
* Ready made implementations of this interface can be created using {@link ComputerCraftAPI#createSaveDirMount(World, String, long)}, or you're free to
* implement it yourselves!
*
* @see ComputerCraftAPI#createSaveDirMount(World, String, long)
* @see IComputerAccess#mount(String, IMount)
* @see IComputerAccess#mountWritable(String, IWritableMount)
* @see IMount
*/
public interface IWritableMount extends IMount
{
public interface IWritableMount extends IMount {
/**
* Creates a directory at a given path inside the virtual file system.
*
* @param path A file path in normalised format, relative to the mount location. ie: "programs/mynewprograms".
* @throws IOException If the directory already exists or could not be created.
*/
void makeDirectory( @Nonnull String path ) throws IOException;
void makeDirectory(@Nonnull String path) throws IOException;
/**
* Deletes a directory at a given path inside the virtual file system.
@@ -44,68 +45,46 @@ public interface IWritableMount extends IMount
* @param path A file path in normalised format, relative to the mount location. ie: "programs/myoldprograms".
* @throws IOException If the file does not exist or could not be deleted.
*/
void delete( @Nonnull String path ) throws IOException;
void delete(@Nonnull String path) throws IOException;
/**
* Opens a file with a given path, and returns an {@link OutputStream} for writing to it.
*
* @param path A file path in normalised format, relative to the mount location. ie: "programs/myprogram".
* @return A stream for writing to
* @throws IOException If the file could not be opened for writing.
* @deprecated Use {@link #openChannelForWrite(String)} instead.
*/
@Nonnull
@Deprecated
OutputStream openForWrite( @Nonnull String path ) throws IOException;
/**
* Opens a file with a given path, and returns an {@link OutputStream} for writing to it.
*
* @param path A file path in normalised format, relative to the mount location. ie: "programs/myprogram".
* @return A stream for writing to. If the channel implements {@link java.nio.channels.SeekableByteChannel}, one
* will be able to seek to arbitrary positions when using binary mode.
* @return A stream for writing to. If the channel implements {@link java.nio.channels.SeekableByteChannel}, one will be able to seek to arbitrary
* positions when using binary mode.
* @throws IOException If the file could not be opened for writing.
*/
@Nonnull
@SuppressWarnings( "deprecation" )
default WritableByteChannel openChannelForWrite( @Nonnull String path ) throws IOException
{
return Channels.newChannel( openForWrite( path ) );
}
WritableByteChannel openForWrite(@Nonnull String path) throws IOException;
/**
* Opens a file with a given path, and returns an {@link OutputStream} for appending to it.
*
* @param path A file path in normalised format, relative to the mount location. ie: "programs/myprogram".
* @return A stream for writing to.
* @throws IOException If the file could not be opened for writing.
* @deprecated Use {@link #openChannelForAppend(String)} instead.
*/
@Nonnull
@Deprecated
OutputStream openForAppend( @Nonnull String path ) throws IOException;
/**
* Opens a file with a given path, and returns an {@link OutputStream} for appending to it.
*
* @param path A file path in normalised format, relative to the mount location. ie: "programs/myprogram".
* @return A stream for writing to. If the channel implements {@link java.nio.channels.SeekableByteChannel}, one
* will be able to seek to arbitrary positions when using binary mode.
* @return A stream for writing to. If the channel implements {@link java.nio.channels.SeekableByteChannel}, one will be able to seek to arbitrary
* positions when using binary mode.
* @throws IOException If the file could not be opened for writing.
*/
@Nonnull
@SuppressWarnings( "deprecation" )
default WritableByteChannel openChannelForAppend( @Nonnull String path ) throws IOException
{
return Channels.newChannel( openForAppend( path ) );
}
WritableByteChannel openForAppend(@Nonnull String path) throws IOException;
/**
* Get the amount of free space on the mount, in bytes. You should decrease this value as the user writes to the
* mount, and write operations should fail once it reaches zero.
* Get the amount of free space on the mount, in bytes. You should decrease this value as the user writes to the mount, and write operations should fail
* once it reaches zero.
*
* @return The amount of free space, in bytes.
* @throws IOException If the remaining space could not be computed.
*/
long getRemainingSpace() throws IOException;
/**
* Get the capacity of this mount. This should be equal to the size of all files/directories on this mount, minus the {@link #getRemainingSpace()}.
*
* @return The capacity of this mount, in bytes.
*/
@Nonnull
default OptionalLong getCapacity() {
return OptionalLong.empty();
}
}

View File

@@ -1,10 +0,0 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
@API( owner = "ComputerCraft", provides = "ComputerCraft|API|FileSystem", apiVersion = "${version}" )
package dan200.computercraft.api.filesystem;
import net.minecraftforge.fml.common.API;

View File

@@ -0,0 +1,58 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.lua;
import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.api.peripheral.IPeripheralProvider;
import dan200.computercraft.core.asm.LuaMethod;
import net.minecraft.util.Identifier;
import javax.annotation.Nonnull;
/**
* A generic source of {@link LuaMethod} functions.
*
* Unlike normal objects ({@link IDynamicLuaObject} or {@link IPeripheral}), methods do not target this object but
* instead are defined as {@code static} and accept their target as the first parameter. This allows you to inject
* methods onto objects you do not own, as well as declaring methods for a specific "trait" (for instance, a
* {@link Capability}).
*
* Currently the "generic peripheral" system is incompatible with normal peripherals. Normal {@link IPeripheralProvider}
* or {@link IPeripheral} implementations take priority. Tile entities which use this system are given a peripheral name
* determined by their id, rather than any peripheral provider. This will hopefully change in the future, once a suitable
* design has been established.
*
* For example, the main CC: Tweaked mod defines a generic source for inventories, which works on {@link IItemHandler}s:
*
* <pre>{@code
* public class InventoryMethods implements GenericSource {
* \@LuaFunction( mainThread = true )
* public static int size(IItemHandler inventory) {
* return inventory.getSlots();
* }
*
* // ...
* }
* }</pre>
*
* @see ComputerCraftAPI#registerGenericSource(GenericSource)
* @see ComputerCraftAPI#registerGenericCapability(Capability) New capabilities (those not built into Forge) must be
* explicitly given to the generic peripheral system, as there is no way to enumerate all capabilities.
*/
public interface GenericSource
{
/**
* A unique identifier for this generic source.
*
* This is currently unused, but may be used in the future to allow disabling specific sources. It is recommended
* to return an identifier using your mod's ID.
*
* @return This source's identifier.
*/
@Nonnull
Identifier id();
}

View File

@@ -0,0 +1,418 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.lua;
import static dan200.computercraft.api.lua.LuaValues.checkFinite;
import java.nio.ByteBuffer;
import java.util.Map;
import java.util.Optional;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* The arguments passed to a function.
*/
public interface IArguments {
/**
* Drop a number of arguments. The returned arguments instance will access arguments at position {@code i + count}, rather than {@code i}. However,
* errors will still use the given argument index.
*
* @param count The number of arguments to drop.
* @return The new {@link IArguments} instance.
*/
IArguments drop(int count);
default Object[] getAll() {
Object[] result = new Object[this.count()];
for (int i = 0; i < result.length; i++) {
result[i] = this.get(i);
}
return result;
}
/**
* Get the number of arguments passed to this function.
*
* @return The number of passed arguments.
*/
int count();
/**
* Get the argument at the specific index. The returned value must obey the following conversion rules:
*
* <ul>
* <li>Lua values of type "string" will be represented by a {@link String}.</li>
* <li>Lua values of type "number" will be represented by a {@link Number}.</li>
* <li>Lua values of type "boolean" will be represented by a {@link Boolean}.</li>
* <li>Lua values of type "table" will be represented by a {@link Map}.</li>
* <li>Lua values of any other type will be represented by a {@code null} value.</li>
* </ul>
*
* @param index The argument number.
* @return The argument's value, or {@code null} if not present.
*/
@Nullable
Object get(int index);
/**
* Get an argument as an integer.
*
* @param index The argument number.
* @return The argument's value.
* @throws LuaException If the value is not an integer.
*/
default int getInt(int index) throws LuaException {
return (int) this.getLong(index);
}
/**
* Get an argument as a long.
*
* @param index The argument number.
* @return The argument's value.
* @throws LuaException If the value is not a long.
*/
default long getLong(int index) throws LuaException {
Object value = this.get(index);
if (!(value instanceof Number)) {
throw LuaValues.badArgumentOf(index, "number", value);
}
return LuaValues.checkFiniteNum(index, (Number) value)
.longValue();
}
/**
* Get an argument as a finite number (not infinite or NaN).
*
* @param index The argument number.
* @return The argument's value.
* @throws LuaException If the value is not finite.
*/
default double getFiniteDouble(int index) throws LuaException {
return checkFinite(index, this.getDouble(index));
}
/**
* Get an argument as a double.
*
* @param index The argument number.
* @return The argument's value.
* @throws LuaException If the value is not a number.
* @see #getFiniteDouble(int) if you require this to be finite (i.e. not infinite or NaN).
*/
default double getDouble(int index) throws LuaException {
Object value = this.get(index);
if (!(value instanceof Number)) {
throw LuaValues.badArgumentOf(index, "number", value);
}
return ((Number) value).doubleValue();
}
/**
* Get an argument as a boolean.
*
* @param index The argument number.
* @return The argument's value.
* @throws LuaException If the value is not a boolean.
*/
default boolean getBoolean(int index) throws LuaException {
Object value = this.get(index);
if (!(value instanceof Boolean)) {
throw LuaValues.badArgumentOf(index, "boolean", value);
}
return (Boolean) value;
}
/**
* Get a string argument as a byte array.
*
* @param index The argument number.
* @return The argument's value. This is a <em>read only</em> buffer.
* @throws LuaException If the value is not a string.
*/
@Nonnull
default ByteBuffer getBytes(int index) throws LuaException {
return LuaValues.encode(this.getString(index));
}
/**
* Get an argument as a string.
*
* @param index The argument number.
* @return The argument's value.
* @throws LuaException If the value is not a string.
*/
@Nonnull
default String getString(int index) throws LuaException {
Object value = this.get(index);
if (!(value instanceof String)) {
throw LuaValues.badArgumentOf(index, "string", value);
}
return (String) value;
}
/**
* Get a string argument as an enum value.
*
* @param index The argument number.
* @param klass The type of enum to parse.
* @param <T> The type of enum to parse.
* @return The argument's value.
* @throws LuaException If the value is not a string or not a valid option for this enum.
*/
@Nonnull
default <T extends Enum<T>> T getEnum(int index, Class<T> klass) throws LuaException {
return LuaValues.checkEnum(index, klass, this.getString(index));
}
/**
* Get an argument as a table.
*
* @param index The argument number.
* @return The argument's value.
* @throws LuaException If the value is not a table.
*/
@Nonnull
default Map<?, ?> getTable(int index) throws LuaException {
Object value = this.get(index);
if (!(value instanceof Map)) {
throw LuaValues.badArgumentOf(index, "table", value);
}
return (Map<?, ?>) value;
}
/**
* Get a string argument as a byte array.
*
* @param index The argument number.
* @return The argument's value, or {@link Optional#empty()} if not present. This is a <em>read only</em> buffer.
* @throws LuaException If the value is not a string.
*/
default Optional<ByteBuffer> optBytes(int index) throws LuaException {
return this.optString(index).map(LuaValues::encode);
}
/**
* Get an argument as a string.
*
* @param index The argument number.
* @return The argument's value, or {@link Optional#empty()} if not present.
* @throws LuaException If the value is not a string.
*/
default Optional<String> optString(int index) throws LuaException {
Object value = this.get(index);
if (value == null) {
return Optional.empty();
}
if (!(value instanceof String)) {
throw LuaValues.badArgumentOf(index, "string", value);
}
return Optional.of((String) value);
}
/**
* Get a string argument as an enum value.
*
* @param index The argument number.
* @param klass The type of enum to parse.
* @param <T> The type of enum to parse.
* @return The argument's value.
* @throws LuaException If the value is not a string or not a valid option for this enum.
*/
@Nonnull
default <T extends Enum<T>> Optional<T> optEnum(int index, Class<T> klass) throws LuaException {
Optional<String> str = this.optString(index);
return str.isPresent() ? Optional.of(LuaValues.checkEnum(index, klass, str.get())) : Optional.empty();
}
/**
* Get an argument as a double.
*
* @param index The argument number.
* @param def The default value, if this argument is not given.
* @return The argument's value, or {@code def} if none was provided.
* @throws LuaException If the value is not a number.
*/
default double optDouble(int index, double def) throws LuaException {
return this.optDouble(index).orElse(def);
}
/**
* Get an argument as a double.
*
* @param index The argument number.
* @return The argument's value, or {@link Optional#empty()} if not present.
* @throws LuaException If the value is not a number.
*/
@Nonnull
default Optional<Double> optDouble(int index) throws LuaException {
Object value = this.get(index);
if (value == null) {
return Optional.empty();
}
if (!(value instanceof Number)) {
throw LuaValues.badArgumentOf(index, "number", value);
}
return Optional.of(((Number) value).doubleValue());
}
/**
* Get an argument as an int.
*
* @param index The argument number.
* @param def The default value, if this argument is not given.
* @return The argument's value, or {@code def} if none was provided.
* @throws LuaException If the value is not a number.
*/
default int optInt(int index, int def) throws LuaException {
return this.optInt(index).orElse(def);
}
/**
* Get an argument as an int.
*
* @param index The argument number.
* @return The argument's value, or {@link Optional#empty()} if not present.
* @throws LuaException If the value is not a number.
*/
@Nonnull
default Optional<Integer> optInt(int index) throws LuaException {
return this.optLong(index).map(Long::intValue);
}
/**
* Get an argument as a long.
*
* @param index The argument number.
* @return The argument's value, or {@link Optional#empty()} if not present.
* @throws LuaException If the value is not a number.
*/
default Optional<Long> optLong(int index) throws LuaException {
Object value = this.get(index);
if (value == null) {
return Optional.empty();
}
if (!(value instanceof Number)) {
throw LuaValues.badArgumentOf(index, "number", value);
}
return Optional.of(LuaValues.checkFiniteNum(index, (Number) value)
.longValue());
}
/**
* Get an argument as a long.
*
* @param index The argument number.
* @param def The default value, if this argument is not given.
* @return The argument's value, or {@code def} if none was provided.
* @throws LuaException If the value is not a number.
*/
default long optLong(int index, long def) throws LuaException {
return this.optLong(index).orElse(def);
}
/**
* Get an argument as a finite number (not infinite or NaN).
*
* @param index The argument number.
* @param def The default value, if this argument is not given.
* @return The argument's value, or {@code def} if none was provided.
* @throws LuaException If the value is not finite.
*/
default double optFiniteDouble(int index, double def) throws LuaException {
return this.optFiniteDouble(index).orElse(def);
}
/**
* Get an argument as a finite number (not infinite or NaN).
*
* @param index The argument number.
* @return The argument's value, or {@link Optional#empty()} if not present.
* @throws LuaException If the value is not finite.
*/
default Optional<Double> optFiniteDouble(int index) throws LuaException {
Optional<Double> value = this.optDouble(index);
if (value.isPresent()) {
LuaValues.checkFiniteNum(index, value.get());
}
return value;
}
/**
* Get an argument as a boolean.
*
* @param index The argument number.
* @param def The default value, if this argument is not given.
* @return The argument's value, or {@code def} if none was provided.
* @throws LuaException If the value is not a boolean.
*/
default boolean optBoolean(int index, boolean def) throws LuaException {
return this.optBoolean(index).orElse(def);
}
/**
* Get an argument as a boolean.
*
* @param index The argument number.
* @return The argument's value, or {@link Optional#empty()} if not present.
* @throws LuaException If the value is not a boolean.
*/
default Optional<Boolean> optBoolean(int index) throws LuaException {
Object value = this.get(index);
if (value == null) {
return Optional.empty();
}
if (!(value instanceof Boolean)) {
throw LuaValues.badArgumentOf(index, "boolean", value);
}
return Optional.of((Boolean) value);
}
/**
* Get an argument as a string.
*
* @param index The argument number.
* @param def The default value, if this argument is not given.
* @return The argument's value, or {@code def} if none was provided.
* @throws LuaException If the value is not a string.
*/
default String optString(int index, String def) throws LuaException {
return this.optString(index).orElse(def);
}
/**
* Get an argument as a table.
*
* @param index The argument number.
* @param def The default value, if this argument is not given.
* @return The argument's value, or {@code def} if none was provided.
* @throws LuaException If the value is not a table.
*/
default Map<?, ?> optTable(int index, Map<Object, Object> def) throws LuaException {
return this.optTable(index).orElse(def);
}
/**
* Get an argument as a table.
*
* @param index The argument number.
* @return The argument's value, or {@link Optional#empty()} if not present.
* @throws LuaException If the value is not a table.
*/
default Optional<Map<?, ?>> optTable(int index) throws LuaException {
Object value = this.get(index);
if (value == null) {
return Optional.empty();
}
if (!(value instanceof Map)) {
throw LuaValues.badArgumentOf(index, "map", value);
}
return Optional.of((Map<?, ?>) value);
}
}

View File

@@ -1,22 +1,20 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.lua;
import javax.annotation.Nullable;
import dan200.computercraft.api.filesystem.IFileSystem;
import dan200.computercraft.api.peripheral.IComputerAccess;
import javax.annotation.Nullable;
/**
* An interface passed to {@link ILuaAPIFactory} in order to provide additional information
* about a computer.
* An interface passed to {@link ILuaAPIFactory} in order to provide additional information about a computer.
*/
public interface IComputerSystem extends IComputerAccess
{
public interface IComputerSystem extends IComputerAccess {
/**
* Get the file system for this computer.
*
@@ -26,7 +24,7 @@ public interface IComputerSystem extends IComputerAccess
IFileSystem getFileSystem();
/**
* Get the label for this computer
* Get the label for this computer.
*
* @return This computer's label, or {@code null} if it is not set.
*/

View File

@@ -0,0 +1,40 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.lua;
import javax.annotation.Nonnull;
import dan200.computercraft.api.peripheral.IDynamicPeripheral;
/**
* An interface for representing custom objects returned by peripherals or other Lua objects.
*
* Generally, one does not need to implement this type - it is sufficient to return an object with some methods annotated with {@link LuaFunction}. {@link
* IDynamicLuaObject} is useful when you wish your available methods to change at runtime.
*/
public interface IDynamicLuaObject {
/**
* Get the names of the methods that this object implements. This should not change over the course of the object's lifetime.
*
* @return The method names this object provides.
* @see IDynamicPeripheral#getMethodNames()
*/
@Nonnull
String[] getMethodNames();
/**
* Called when a user calls one of the methods that this object implements.
*
* @param context The context of the currently running lua thread. This can be used to wait for events or otherwise yield.
* @param method An integer identifying which method index from {@link #getMethodNames()} the computer wishes to call.
* @param arguments The arguments for this method.
* @return The result of this function. Either an immediate value ({@link MethodResult#of(Object...)} or an instruction to yield.
* @throws LuaException If the function threw an exception.
*/
@Nonnull
MethodResult callMethod(@Nonnull ILuaContext context, int method, @Nonnull IArguments arguments) throws LuaException;
}

View File

@@ -1,6 +1,6 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
@@ -9,16 +9,16 @@ package dan200.computercraft.api.lua;
import dan200.computercraft.api.ComputerCraftAPI;
/**
* Represents a {@link ILuaObject} which is stored as a global variable on computer startup.
* Represents a Lua object which is stored as a global variable on computer startup. This must either provide {@link LuaFunction} annotated functions or
* implement {@link IDynamicLuaObject}.
*
* Before implementing this interface, consider alternative methods of providing methods. It is generally preferred
* to use peripherals to provide functionality to users.
* Before implementing this interface, consider alternative methods of providing methods. It is generally preferred to use peripherals to provide
* functionality to users.
*
* @see ILuaAPIFactory
* @see ComputerCraftAPI#registerAPIFactory(ILuaAPIFactory)
*/
public interface ILuaAPI extends ILuaObject
{
public interface ILuaAPI {
/**
* Get the globals this API will be assigned to. This will override any other global, so you should
*
@@ -31,15 +31,13 @@ public interface ILuaAPI extends ILuaObject
*
* One should only interact with the file system.
*/
default void startup()
{
default void startup() {
}
/**
* Called every time the computer is ticked. This can be used to process various.
*/
default void update()
{
default void update() {
}
/**
@@ -47,7 +45,6 @@ public interface ILuaAPI extends ILuaObject
*
* This should reset the state of the object, disposing any remaining file handles, or other resources.
*/
default void shutdown()
{
default void shutdown() {
}
}

View File

@@ -1,24 +1,24 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.lua;
import dan200.computercraft.api.ComputerCraftAPI;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import dan200.computercraft.api.ComputerCraftAPI;
/**
* Construct an {@link ILuaAPI} for a specific computer.
*
* @see ILuaAPI
* @see ComputerCraftAPI#registerAPIFactory(ILuaAPIFactory)
*/
public interface ILuaAPIFactory
{
@FunctionalInterface
public interface ILuaAPIFactory {
/**
* Create a new API instance for a given computer.
*
@@ -26,5 +26,5 @@ public interface ILuaAPIFactory
* @return The created API, or {@code null} if one should not be injected.
*/
@Nullable
ILuaAPI create( @Nonnull IComputerSystem computer );
ILuaAPI create(@Nonnull IComputerSystem computer);
}

View File

@@ -0,0 +1,26 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.lua;
import javax.annotation.Nonnull;
/**
* A continuation which is called when this coroutine is resumed.
*
* @see MethodResult#yield(Object[], ILuaCallback)
*/
public interface ILuaCallback {
/**
* Resume this coroutine.
*
* @param args The result of resuming this coroutine. These will have the same form as described in {@link LuaFunction}.
* @return The result of this continuation. Either the result to return to the callee, or another yield.
* @throws LuaException On an error.
*/
@Nonnull
MethodResult resume(Object[] args) throws LuaException;
}

View File

@@ -1,97 +1,29 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.lua;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* An interface passed to peripherals and {@link ILuaObject}s by computers or turtles, providing methods
* that allow the peripheral call to wait for events before returning, just like in lua. This is very useful if you need
* to signal work to be performed on the main thread, and don't want to return until the work has been completed.
* An interface passed to peripherals and {@link IDynamicLuaObject}s by computers or turtles, providing methods that allow the peripheral call to interface
* with the computer.
*/
public interface ILuaContext
{
public interface ILuaContext {
/**
* Wait for an event to occur on the computer, suspending the thread until it arises. This method is exactly
* equivalent to {@code os.pullEvent()} in lua.
* Queue a task to be executed on the main server thread at the beginning of next tick, but do not wait for it to complete. This should be used when you
* need to interact with the world in a thread-safe manner but do not care about the result or you wish to run asynchronously.
*
* @param filter A specific event to wait for, or null to wait for any event.
* @return An object array containing the name of the event that occurred, and any event parameters.
* @throws LuaException If the user presses CTRL+T to terminate the current program while pullEvent() is
* waiting for an event, a "Terminated" exception will be thrown here.
*
* Do not attempt to catch this exception. You should use {@link #pullEventRaw(String)}
* should you wish to disable termination.
* @throws InterruptedException If the user shuts down or reboots the computer while pullEvent() is waiting for an
* event, InterruptedException will be thrown. This exception must not be caught or
* intercepted, or the computer will leak memory and end up in a broken state.
*/
@Nonnull
Object[] pullEvent( @Nullable String filter ) throws LuaException, InterruptedException;
/**
* The same as {@link #pullEvent(String)}, except "terminated" events are ignored. Only use this if you want to
* prevent program termination, which is not recommended. This method is exactly equivalent to
* {@code os.pullEventRaw()} in lua.
*
* @param filter A specific event to wait for, or null to wait for any event.
* @return An object array containing the name of the event that occurred, and any event parameters.
* @throws InterruptedException If the user shuts down or reboots the computer while pullEventRaw() is waiting for
* an event, InterruptedException will be thrown. This exception must not be caught or
* intercepted, or the computer will leak memory and end up in a broken state.
* @see #pullEvent(String)
*/
@Nonnull
Object[] pullEventRaw( @Nullable String filter ) throws InterruptedException;
/**
* Yield the current coroutine with some arguments until it is resumed. This method is exactly equivalent to
* {@code coroutine.yield()} in lua. Use {@code pullEvent()} if you wish to wait for events.
*
* @param arguments An object array containing the arguments to pass to coroutine.yield()
* @return An object array containing the return values from coroutine.yield()
* @throws InterruptedException If the user shuts down or reboots the computer the coroutine is suspended,
* InterruptedException will be thrown. This exception must not be caught or
* intercepted, or the computer will leak memory and end up in a broken state.
* @see #pullEvent(String)
*/
@Nonnull
Object[] yield( @Nullable Object[] arguments ) throws InterruptedException;
/**
* Queue a task to be executed on the main server thread at the beginning of next tick, waiting for it to complete.
* This should be used when you need to interact with the world in a thread-safe manner.
*
* Note that the return values of your task are handled as events, meaning more complex objects such as maps or
* {@link ILuaObject} will not preserve their identities.
*
* @param task The task to execute on the main thread.
* @return The objects returned by {@code task}.
* @throws LuaException If the task could not be queued, or if the task threw an exception.
* @throws InterruptedException If the user shuts down or reboots the computer the coroutine is suspended,
* InterruptedException will be thrown. This exception must not be caught or
* intercepted, or the computer will leak memory and end up in a broken state.
*/
@Nullable
Object[] executeMainThreadTask( @Nonnull ILuaTask task ) throws LuaException, InterruptedException;
/**
* Queue a task to be executed on the main server thread at the beginning of next tick, but do not wait for it to
* complete. This should be used when you need to interact with the world in a thread-safe manner but do not care
* about the result or you wish to run asynchronously.
*
* When the task has finished, it will enqueue a {@code task_completed} event, which takes the task id, a success
* value and the return values, or an error message if it failed. If you need to wait on this event, it may be
* better to use {@link #executeMainThreadTask(ILuaTask)}.
* When the task has finished, it will enqueue a {@code task_completed} event, which takes the task id, a success value and the return values, or an
* error message if it failed.
*
* @param task The task to execute on the main thread.
* @return The "id" of the task. This will be the first argument to the {@code task_completed} event.
* @throws LuaException If the task could not be queued.
* @see LuaFunction#mainThread() To run functions on the main thread and return their results synchronously.
*/
long issueMainThreadTask( @Nonnull ILuaTask task ) throws LuaException;
long issueMainThreadTask(@Nonnull ILuaTask task) throws LuaException;
}

View File

@@ -0,0 +1,29 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.lua;
import javax.annotation.Nonnull;
/**
* A function, which can be called from Lua. If you need to return a table of functions, it is recommended to use an object with {@link LuaFunction}
* methods, or implement {@link IDynamicLuaObject}.
*
* @see MethodResult#of(Object)
*/
@FunctionalInterface
public interface ILuaFunction {
/**
* Call this function with a series of arguments. Note, this will <em>always</em> be called on the computer thread, and so its implementation must be
* thread-safe.
*
* @param arguments The arguments for this function
* @return The result of calling this function.
* @throws LuaException Upon Lua errors.
*/
@Nonnull
MethodResult call(@Nonnull IArguments arguments) throws LuaException;
}

View File

@@ -6,51 +6,13 @@
package dan200.computercraft.api.lua;
import dan200.computercraft.api.peripheral.IComputerAccess;
import dan200.computercraft.api.peripheral.IPeripheral;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* An interface for representing custom objects returned by {@link IPeripheral#callMethod(IComputerAccess, ILuaContext, int, Object[])}
* calls.
*
* Return objects implementing this interface to expose objects with methods to lua.
*/
public interface ILuaObject
{
/**
* Get the names of the methods that this object implements. This works the same as {@link IPeripheral#getMethodNames()}.
* See that method for detailed documentation.
*
* @return The method names this object provides.
* @see IPeripheral#getMethodNames()
*/
public interface ILuaObject {
@Nonnull
String[] getMethodNames();
/**
* Called when a user calls one of the methods that this object implements. This works the same as
* {@link IPeripheral#callMethod(IComputerAccess, ILuaContext, int, Object[])}}. See that method for detailed
* documentation.
*
* @param context The context of the currently running lua thread. This can be used to wait for events
* or otherwise yield.
* @param method An integer identifying which of the methods from getMethodNames() the computercraft
* wishes to call. The integer indicates the index into the getMethodNames() table
* that corresponds to the string passed into peripheral.call()
* @param arguments The arguments for this method. See {@link IPeripheral#callMethod(IComputerAccess, ILuaContext, int, Object[])}
* the possible values and conversion rules.
* @return An array of objects, representing the values you wish to return to the Lua program.
* See {@link IPeripheral#callMethod(IComputerAccess, ILuaContext, int, Object[])} for the valid values and
* conversion rules.
* @throws LuaException If the task could not be queued, or if the task threw an exception.
* @throws InterruptedException If the user shuts down or reboots the computer the coroutine is suspended,
* InterruptedException will be thrown. This exception must not be caught or
* intercepted, or the computer will leak memory and end up in a broken state.w
* @see IPeripheral#callMethod(IComputerAccess, ILuaContext, int, Object[])
*/
@Nullable
Object[] callMethod( @Nonnull ILuaContext context, int method, @Nonnull Object[] arguments ) throws LuaException, InterruptedException;
Object[] callMethod(@Nonnull ILuaContext context, int method, @Nonnull Object[] arguments) throws LuaException, InterruptedException;
}

View File

@@ -1,6 +1,6 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
@@ -9,24 +9,19 @@ package dan200.computercraft.api.lua;
import javax.annotation.Nullable;
/**
* A task which can be executed via {@link ILuaContext#executeMainThreadTask(ILuaTask)} or
* {@link ILuaContext#issueMainThreadTask(ILuaTask)}. This will be run on the main thread, at the beginning of the
* next tick.
* A task which can be executed via {@link ILuaContext#issueMainThreadTask(ILuaTask)} This will be run on the main thread, at the beginning of the next
* tick.
*
* @see ILuaContext#executeMainThreadTask(ILuaTask)
* @see ILuaContext#issueMainThreadTask(ILuaTask)
*/
@FunctionalInterface
public interface ILuaTask
{
public interface ILuaTask {
/**
* Execute this task.
*
* @return The arguments to add to the {@code task_completed} event. These will be returned by
* {@link ILuaContext#executeMainThreadTask(ILuaTask)}.
* @throws LuaException If you throw any exception from this function, a lua error will be raised with the
* same message as your exception. Use this to throw appropriate errors if the wrong
* arguments are supplied to your method.
* @return The arguments to add to the {@code task_completed} event.
* @throws LuaException If you throw any exception from this function, a lua error will be raised with the same message as your exception. Use this
* to throw appropriate errors if the wrong arguments are supplied to your method.
*/
@Nullable
Object[] execute() throws LuaException;

View File

@@ -1,6 +1,6 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
@@ -11,35 +11,38 @@ import javax.annotation.Nullable;
/**
* An exception representing an error in Lua, like that raised by the {@code error()} function.
*/
public class LuaException extends Exception
{
public class LuaException extends Exception {
private static final long serialVersionUID = -6136063076818512651L;
private final boolean hasLevel;
private final int level;
public LuaException()
{
this( "error", 1 );
public LuaException(@Nullable String message) {
super(message);
this.hasLevel = false;
this.level = 1;
}
public LuaException( @Nullable String message )
{
this( message, 1 );
}
public LuaException( @Nullable String message, int level )
{
super( message );
public LuaException(@Nullable String message, int level) {
super(message);
this.hasLevel = true;
this.level = level;
}
/**
* The level this error is raised at. Level 1 is the function's caller, level 2 is that function's caller, and so
* on.
* Whether a level was explicitly specified when constructing. This is used to determine
*
* @return Whether this has an explicit level.
*/
public boolean hasLevel() {
return this.hasLevel;
}
/**
* The level this error is raised at. Level 1 is the function's caller, level 2 is that function's caller, and so on.
*
* @return The level to raise the error at.
*/
public int getLevel()
{
return level;
public int getLevel() {
return this.level;
}
}

View File

@@ -0,0 +1,61 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.lua;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Map;
import java.util.Optional;
import dan200.computercraft.api.peripheral.IComputerAccess;
import dan200.computercraft.api.peripheral.IPeripheral;
/**
* Used to mark a Java function which is callable from Lua.
*
* Methods annotated with {@link LuaFunction} must be public final instance methods. They can have any number of parameters, but they must be of the
* following types:
*
* <ul>
* <li>{@link ILuaContext} (and {@link IComputerAccess} if on a {@link IPeripheral})</li>
* <li>{@link IArguments}: The arguments supplied to this function.</li>
* <li>
* Alternatively, one may specify the desired arguments as normal parameters and the argument parsing code will
* be generated automatically.
*
* Each parameter must be one of the given types supported by {@link IArguments} (for instance, {@link int} or
* {@link Map}). Optional values are supported by accepting a parameter of type {@link Optional}.
* </li>
* </ul>
*
* This function may return {@link MethodResult}. However, if you simply return a value (rather than having to yield),
* you may return {@code void}, a single value (either an object or a primitive like {@code int}) or array of objects.
* These will be treated the same as {@link MethodResult#of()}, {@link MethodResult#of(Object)} and
* {@link MethodResult#of(Object...)}.
*/
@Documented
@Retention (RetentionPolicy.RUNTIME)
@Target (ElementType.METHOD)
public @interface LuaFunction {
/**
* Explicitly specify the method names of this function. If not given, it uses the name of the annotated method.
*
* @return This function's name(s).
*/
String[] value() default {};
/**
* Run this function on the main server thread. This should be specified for any method which interacts with Minecraft in a thread-unsafe manner.
*
* @return Whether this functi
* @see ILuaContext#issueMainThreadTask(ILuaTask)
*/
boolean mainThread() default false;
}

View File

@@ -0,0 +1,163 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.lua;
import java.nio.ByteBuffer;
import java.util.Map;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* Various utility functions for operating with Lua values.
*
* @see IArguments
*/
public final class LuaValues {
private LuaValues() {
}
/**
* Encode a Lua string into a read-only {@link ByteBuffer}.
*
* @param string The string to encode.
* @return The encoded string.
*/
@Nonnull
public static ByteBuffer encode(@Nonnull String string) {
byte[] chars = new byte[string.length()];
for (int i = 0; i < chars.length; i++) {
char c = string.charAt(i);
chars[i] = c < 256 ? (byte) c : 63;
}
return ByteBuffer.wrap(chars)
.asReadOnlyBuffer();
}
/**
* Construct a "bad argument" exception, from an expected type and the actual value provided.
*
* @param index The argument number, starting from 0.
* @param expected The expected type for this argument.
* @param actual The actual value provided for this argument.
* @return The constructed exception, which should be thrown immediately.
*/
@Nonnull
public static LuaException badArgumentOf(int index, @Nonnull String expected, @Nullable Object actual) {
return badArgument(index, expected, getType(actual));
}
/**
* Construct a "bad argument" exception, from an expected and actual type.
*
* @param index The argument number, starting from 0.
* @param expected The expected type for this argument.
* @param actual The provided type for this argument.
* @return The constructed exception, which should be thrown immediately.
*/
@Nonnull
public static LuaException badArgument(int index, @Nonnull String expected, @Nonnull String actual) {
return new LuaException("bad argument #" + (index + 1) + " (" + expected + " expected, got " + actual + ")");
}
/**
* Get a string representation of the given value's type.
*
* @param value The value whose type we are trying to compute.
* @return A string representation of the given value's type, in a similar format to that provided by Lua's {@code type} function.
*/
@Nonnull
public static String getType(@Nullable Object value) {
if (value == null) {
return "nil";
}
if (value instanceof String) {
return "string";
}
if (value instanceof Boolean) {
return "boolean";
}
if (value instanceof Number) {
return "number";
}
if (value instanceof Map) {
return "table";
}
return "userdata";
}
/**
* Ensure a numeric argument is finite (i.e. not infinite or {@link Double#NaN}.
*
* @param index The argument index to check.
* @param value The value to check.
* @return The input {@code value}.
* @throws LuaException If this is not a finite number.
*/
public static Number checkFiniteNum(int index, Number value) throws LuaException {
checkFinite(index, value.doubleValue());
return value;
}
/**
* Ensure a numeric argument is finite (i.e. not infinite or {@link Double#NaN}.
*
* @param index The argument index to check.
* @param value The value to check.
* @return The input {@code value}.
* @throws LuaException If this is not a finite number.
*/
public static double checkFinite(int index, double value) throws LuaException {
if (!Double.isFinite(value)) {
throw badArgument(index, "number", getNumericType(value));
}
return value;
}
/**
* Returns a more detailed representation of this number's type. If this is finite, it will just return "number", otherwise it returns whether it is
* infinite or NaN.
*
* @param value The value to extract the type for.
* @return This value's numeric type.
*/
@Nonnull
public static String getNumericType(double value) {
if (Double.isNaN(value)) {
return "nan";
}
if (value == Double.POSITIVE_INFINITY) {
return "inf";
}
if (value == Double.NEGATIVE_INFINITY) {
return "-inf";
}
return "number";
}
/**
* Ensure a string is a valid enum value.
*
* @param index The argument index to check.
* @param klass The class of the enum instance.
* @param value The value to extract.
* @param <T> The type of enum we are extracting.
* @return The parsed enum value.
* @throws LuaException If this is not a known enum value.
*/
public static <T extends Enum<T>> T checkEnum(int index, Class<T> klass, String value) throws LuaException {
for (T possibility : klass.getEnumConstants()) {
if (possibility.name()
.equalsIgnoreCase(value)) {
return possibility;
}
}
throw new LuaException("bad argument #" + (index + 1) + " (unknown option " + value + ")");
}
}

View File

@@ -0,0 +1,162 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.lua;
import java.nio.ByteBuffer;
import java.util.Collection;
import java.util.Map;
import java.util.Objects;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import dan200.computercraft.api.peripheral.IComputerAccess;
/**
* The result of invoking a Lua method.
*
* Method results either return a value immediately ({@link #of(Object...)} or yield control to the parent coroutine. When the current coroutine is resumed,
* we invoke the provided {@link ILuaCallback#resume(Object[])} callback.
*/
public final class MethodResult {
private static final MethodResult empty = new MethodResult(null, null);
private final Object[] result;
private final ILuaCallback callback;
private final int adjust;
private MethodResult(Object[] arguments, ILuaCallback callback) {
this.result = arguments;
this.callback = callback;
this.adjust = 0;
}
private MethodResult(Object[] arguments, ILuaCallback callback, int adjust) {
this.result = arguments;
this.callback = callback;
this.adjust = adjust;
}
/**
* Return no values immediately.
*
* @return A method result which returns immediately with no values.
*/
@Nonnull
public static MethodResult of() {
return empty;
}
/**
* Return a single value immediately.
*
* Integers, doubles, floats, strings, booleans, {@link Map}, {@link Collection}s, arrays and {@code null} will be converted to their corresponding Lua
* type. {@code byte[]} and {@link ByteBuffer} will be treated as binary strings. {@link ILuaFunction} will be treated as a function.
*
* In order to provide a custom object with methods, one may return a {@link IDynamicLuaObject}, or an arbitrary class with {@link LuaFunction}
* annotations. Anything else will be converted to {@code nil}.
*
* @param value The value to return to the calling Lua function.
* @return A method result which returns immediately with the given value.
*/
@Nonnull
public static MethodResult of(@Nullable Object value) {
return new MethodResult(new Object[] {value}, null);
}
/**
* Return any number of values immediately.
*
* @param values The values to return. See {@link #of(Object)} for acceptable values.
* @return A method result which returns immediately with the given values.
*/
@Nonnull
public static MethodResult of(@Nullable Object... values) {
return values == null || values.length == 0 ? empty : new MethodResult(values, null);
}
/**
* Wait for an event to occur on the computer, suspending the thread until it arises. This method is exactly equivalent to {@code os.pullEvent()} in
* lua.
*
* @param filter A specific event to wait for, or null to wait for any event.
* @param callback The callback to resume with the name of the event that occurred, and any event parameters.
* @return The method result which represents this yield.
* @see IComputerAccess#queueEvent(String, Object[])
*/
@Nonnull
public static MethodResult pullEvent(@Nullable String filter, @Nonnull ILuaCallback callback) {
Objects.requireNonNull(callback, "callback cannot be null");
return new MethodResult(new Object[] {filter}, results -> {
if (results.length >= 1 && results[0].equals("terminate")) {
throw new LuaException("Terminated", 0);
}
return callback.resume(results);
});
}
/**
* The same as {@link #pullEvent(String, ILuaCallback)}, except "terminated" events are ignored. Only use this if you want to prevent program
* termination, which is not recommended. This method is exactly equivalent to {@code os.pullEventRaw()} in Lua.
*
* @param filter A specific event to wait for, or null to wait for any event.
* @param callback The callback to resume with the name of the event that occurred, and any event parameters.
* @return The method result which represents this yield.
* @see #pullEvent(String, ILuaCallback)
*/
@Nonnull
public static MethodResult pullEventRaw(@Nullable String filter, @Nonnull ILuaCallback callback) {
Objects.requireNonNull(callback, "callback cannot be null");
return new MethodResult(new Object[] {filter}, callback);
}
/**
* Yield the current coroutine with some arguments until it is resumed. This method is exactly equivalent to {@code coroutine.yield()} in lua. Use
* {@code pullEvent()} if you wish to wait for events.
*
* @param arguments An object array containing the arguments to pass to coroutine.yield()
* @param callback The callback to resume with an array containing the return values from coroutine.yield()
* @return The method result which represents this yield.
* @see #pullEvent(String, ILuaCallback)
*/
@Nonnull
public static MethodResult yield(@Nullable Object[] arguments, @Nonnull ILuaCallback callback) {
Objects.requireNonNull(callback, "callback cannot be null");
return new MethodResult(arguments, callback);
}
@Nullable
public Object[] getResult() {
return this.result;
}
@Nullable
public ILuaCallback getCallback() {
return this.callback;
}
public int getErrorAdjust() {
return this.adjust;
}
/**
* Increase the Lua error by a specific amount. One should never need to use this function - it largely exists for some CC internal code.
*
* @param adjust The amount to increase the level by.
* @return The new {@link MethodResult} with an adjusted error. This has no effect on immediate results.
*/
@Nonnull
public MethodResult adjustError(int adjust) {
if (adjust < 0) {
throw new IllegalArgumentException("cannot adjust by a negative amount");
}
if (adjust == 0 || this.callback == null) {
return this;
}
return new MethodResult(this.result, this.callback, this.adjust + adjust);
}
}

View File

@@ -0,0 +1,66 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.lua;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import javax.annotation.Nullable;
/**
* An implementation of {@link IArguments} which wraps an array of {@link Object}.
*/
public final class ObjectArguments implements IArguments {
private static final IArguments EMPTY = new ObjectArguments();
private final List<Object> args;
@Deprecated
@SuppressWarnings ("unused")
public ObjectArguments(IArguments arguments) {
throw new IllegalStateException();
}
public ObjectArguments(Object... args) {
this.args = Arrays.asList(args);
}
public ObjectArguments(List<Object> args) {
this.args = Objects.requireNonNull(args);
}
@Override
public IArguments drop(int count) {
if (count < 0) {
throw new IllegalStateException("count cannot be negative");
}
if (count == 0) {
return this;
}
if (count >= this.args.size()) {
return EMPTY;
}
return new ObjectArguments(this.args.subList(count, this.args.size()));
}
@Override
public Object[] getAll() {
return this.args.toArray();
}
@Override
public int count() {
return this.args.size();
}
@Nullable
@Override
public Object get(int index) {
return index >= this.args.size() ? null : this.args.get(index);
}
}

View File

@@ -1,10 +0,0 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
@API( owner = "ComputerCraft", provides = "ComputerCraft|API|Lua", apiVersion = "${version}" )
package dan200.computercraft.api.lua;
import net.minecraftforge.fml.common.API;

View File

@@ -1,25 +1,27 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.media;
import dan200.computercraft.api.filesystem.IMount;
import net.minecraft.item.ItemStack;
import net.minecraft.util.SoundEvent;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import dan200.computercraft.api.filesystem.IMount;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.sound.SoundEvent;
import net.minecraft.world.World;
/**
* Represents an item that can be placed in a disk drive and used by a Computer.
* Implement this interface on your Item class to allow it to be used in the drive.
*
* Implement this interface on your {@link Item} class to allow it to be used in the drive. Alternatively, register a {@link IMediaProvider}.
*/
public interface IMedia
{
public interface IMedia {
/**
* Get a string representing the label of this item. Will be called via {@code disk.getLabel()} in lua.
*
@@ -27,7 +29,7 @@ public interface IMedia
* @return The label. ie: "Dan's Programs".
*/
@Nullable
String getLabel( @Nonnull ItemStack stack );
String getLabel(@Nonnull ItemStack stack);
/**
* Set a string representing the label of this item. Will be called vi {@code disk.setLabel()} in lua.
@@ -36,21 +38,18 @@ public interface IMedia
* @param label The string to set the label to.
* @return true if the label was updated, false if the label may not be modified.
*/
default boolean setLabel( @Nonnull ItemStack stack, @Nullable String label )
{
default boolean setLabel(@Nonnull ItemStack stack, @Nullable String label) {
return false;
}
/**
* If this disk represents an item with audio (like a record), get the readable name of the audio track. ie:
* "Jonathon Coulton - Still Alive"
* If this disk represents an item with audio (like a record), get the readable name of the audio track. ie: "Jonathan Coulton - Still Alive"
*
* @param stack The {@link ItemStack} to modify.
* @return The name, or null if this item does not represent an item with audio.
*/
@Nullable
default String getAudioTitle( @Nonnull ItemStack stack )
{
default String getAudioTitle(@Nonnull ItemStack stack) {
return null;
}
@@ -61,27 +60,25 @@ public interface IMedia
* @return The name, or null if this item does not represent an item with audio.
*/
@Nullable
default SoundEvent getAudio( @Nonnull ItemStack stack )
{
default SoundEvent getAudio(@Nonnull ItemStack stack) {
return null;
}
/**
* If this disk represents an item with data (like a floppy disk), get a mount representing it's contents. This will
* be mounted onto the filesystem of the computer while the media is in the disk drive.
* If this disk represents an item with data (like a floppy disk), get a mount representing it's contents. This will be mounted onto the filesystem of
* the computer while the media is in the disk drive.
*
* @param stack The {@link ItemStack} to modify.
* @param world The world in which the item and disk drive reside.
* @return The mount, or null if this item does not represent an item with data. If the mount returned also
* implements {@link dan200.computercraft.api.filesystem.IWritableMount}, it will mounted using mountWritable()
* @see dan200.computercraft.api.filesystem.IMount
* @return The mount, or null if this item does not represent an item with data. If the mount returned also implements {@link
* dan200.computercraft.api.filesystem.IWritableMount}, it will mounted using mountWritable()
* @see IMount
* @see dan200.computercraft.api.filesystem.IWritableMount
* @see dan200.computercraft.api.ComputerCraftAPI#createSaveDirMount(World, String, long)
* @see dan200.computercraft.api.ComputerCraftAPI#createResourceMount(Class, String, String)
* @see dan200.computercraft.api.ComputerCraftAPI#createResourceMount(String, String)
*/
@Nullable
default IMount createDataMount( @Nonnull ItemStack stack, @Nonnull World world )
{
default IMount createDataMount(@Nonnull ItemStack stack, @Nonnull World world) {
return null;
}
}

View File

@@ -1,31 +1,30 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.media;
import net.minecraft.item.ItemStack;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import net.minecraft.item.ItemStack;
/**
* This interface is used to provide {@link IMedia} implementations for {@link ItemStack}.
*
* @see dan200.computercraft.api.ComputerCraftAPI#registerMediaProvider(IMediaProvider)
*/
@FunctionalInterface
public interface IMediaProvider
{
public interface IMediaProvider {
/**
* Produce an IMedia implementation from an ItemStack.
*
* @param stack The stack from which to extract the media information.
* @return An IMedia implementation, or null if the item is not something you wish to handle
* @return An {@link IMedia} implementation, or {@code null} if the item is not something you wish to handle
* @see dan200.computercraft.api.ComputerCraftAPI#registerMediaProvider(IMediaProvider)
*/
@Nullable
IMedia getMedia( @Nonnull ItemStack stack );
IMedia getMedia(@Nonnull ItemStack stack);
}

View File

@@ -1,10 +0,0 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
@API( owner = "ComputerCraft", provides = "ComputerCraft|API|Media", apiVersion = "${version}" )
package dan200.computercraft.api.media;
import net.minecraftforge.fml.common.API;

View File

@@ -1,8 +1,9 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.network;
import javax.annotation.Nonnull;
@@ -13,21 +14,20 @@ import javax.annotation.Nonnull;
* @see Packet
* @see IPacketReceiver
*/
public interface IPacketNetwork
{
public interface IPacketNetwork {
/**
* Add a receiver to the network.
*
* @param receiver The receiver to register to the network.
*/
void addReceiver( @Nonnull IPacketReceiver receiver );
void addReceiver(@Nonnull IPacketReceiver receiver);
/**
* Remove a receiver from the network.
*
* @param receiver The device to remove from the network.
*/
void removeReceiver( @Nonnull IPacketReceiver receiver );
void removeReceiver(@Nonnull IPacketReceiver receiver);
/**
* Determine whether this network is wireless.
@@ -37,23 +37,23 @@ public interface IPacketNetwork
boolean isWireless();
/**
* Submit a packet for transmitting across the network. This will route the packet through the network, sending it
* to all receivers within range (or any interdimensional ones).
* Submit a packet for transmitting across the network. This will route the packet through the network, sending it to all receivers within range (or any
* interdimensional ones).
*
* @param packet The packet to send.
* @param range The maximum distance this packet will be sent.
* @param range The maximum distance this packet will be sent.
* @see #transmitInterdimensional(Packet)
* @see IPacketReceiver#receiveSameDimension(Packet, double)
*/
void transmitSameDimension( @Nonnull Packet packet, double range );
void transmitSameDimension(@Nonnull Packet packet, double range);
/**
* Submit a packet for transmitting across the network. This will route the packet through the network, sending it
* to all receivers across all dimensions.
* Submit a packet for transmitting across the network. This will route the packet through the network, sending it to all receivers across all
* dimensions.
*
* @param packet The packet to send.
* @see #transmitSameDimension(Packet, double)
* @see IPacketReceiver#receiveDifferentDimension(Packet)
*/
void transmitInterdimensional( @Nonnull Packet packet );
void transmitInterdimensional(@Nonnull Packet packet);
}

View File

@@ -1,20 +1,20 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.network;
import javax.annotation.Nonnull;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
/**
* An object on an {@link IPacketNetwork}, capable of receiving packets.
*/
public interface IPacketReceiver
{
public interface IPacketReceiver {
/**
* Get the world in which this packet receiver exists.
*
@@ -34,9 +34,8 @@ public interface IPacketReceiver
/**
* Get the maximum distance this receiver can send and receive messages.
*
* When determining whether a receiver can receive a message, the largest distance of the packet and receiver is
* used - ensuring it is within range. If the packet or receiver is inter-dimensional, then the packet will always
* be received.
* When determining whether a receiver can receive a message, the largest distance of the packet and receiver is used - ensuring it is within range. If
* the packet or receiver is inter-dimensional, then the packet will always be received.
*
* @return The maximum distance this device can send and receive messages.
* @see #isInterdimensional()
@@ -60,25 +59,25 @@ public interface IPacketReceiver
/**
* Receive a network packet from the same dimension.
*
* @param packet The packet to receive. Generally you should check that you are listening on the given channel and,
* if so, queue the appropriate modem event.
* @param packet The packet to receive. Generally you should check that you are listening on the given channel and, if so, queue the appropriate
* modem event.
* @param distance The distance this packet has travelled from the source.
* @see Packet
* @see #getRange()
* @see IPacketNetwork#transmitSameDimension(Packet, double)
* @see IPacketNetwork#transmitInterdimensional(Packet)
*/
void receiveSameDimension( @Nonnull Packet packet, double distance );
void receiveSameDimension(@Nonnull Packet packet, double distance);
/**
* Receive a network packet from a different dimension.
*
* @param packet The packet to receive. Generally you should check that you are listening on the given channel and,
* if so, queue the appropriate modem event.
* @param packet The packet to receive. Generally you should check that you are listening on the given channel and, if so, queue the appropriate
* modem event.
* @see Packet
* @see IPacketNetwork#transmitInterdimensional(Packet)
* @see IPacketNetwork#transmitSameDimension(Packet, double)
* @see #isInterdimensional()
*/
void receiveDifferentDimension( @Nonnull Packet packet );
void receiveDifferentDimension(@Nonnull Packet packet);
}

View File

@@ -1,20 +1,20 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.network;
import javax.annotation.Nonnull;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
/**
* An object on a {@link IPacketNetwork}, capable of sending packets.
*/
public interface IPacketSender
{
public interface IPacketSender {
/**
* Get the world in which this packet sender exists.
*
@@ -32,8 +32,8 @@ public interface IPacketSender
Vec3d getPosition();
/**
* Get some sort of identification string for this sender. This does not strictly need to be unique, but you
* should be able to extract some identifiable information from it.
* Get some sort of identification string for this sender. This does not strictly need to be unique, but you should be able to extract some identifiable
* information from it.
*
* @return This device's id.
*/

View File

@@ -1,13 +1,15 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.network;
import java.util.Objects;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Objects;
/**
* Represents a packet which may be sent across a {@link IPacketNetwork}.
@@ -18,8 +20,7 @@ import java.util.Objects;
* @see IPacketReceiver#receiveDifferentDimension(Packet)
* @see IPacketReceiver#receiveSameDimension(Packet, double)
*/
public class Packet
{
public class Packet {
private final int channel;
private final int replyChannel;
private final Object payload;
@@ -29,16 +30,14 @@ public class Packet
/**
* Create a new packet, ready for transmitting across the network.
*
* @param channel The channel to send the packet along. Receiving devices should only process packets from on
* channels they are listening to.
* @param channel The channel to send the packet along. Receiving devices should only process packets from on channels they are listening to.
* @param replyChannel The channel to reply on.
* @param payload The contents of this packet. This should be a "valid" Lua object, safe for queuing as an
* event or returning from a peripheral call.
* @param sender The object which sent this packet.
* @param payload The contents of this packet. This should be a "valid" Lua object, safe for queuing as an event or returning from a peripheral
* call.
* @param sender The object which sent this packet.
*/
public Packet( int channel, int replyChannel, @Nullable Object payload, @Nonnull IPacketSender sender )
{
Objects.requireNonNull( sender, "sender cannot be null" );
public Packet(int channel, int replyChannel, @Nullable Object payload, @Nonnull IPacketSender sender) {
Objects.requireNonNull(sender, "sender cannot be null");
this.channel = channel;
this.replyChannel = replyChannel;
@@ -47,14 +46,12 @@ public class Packet
}
/**
* Get the channel this packet is sent along. Receivers should generally only process packets from on channels they
* are listening to.
* Get the channel this packet is sent along. Receivers should generally only process packets from on channels they are listening to.
*
* @return This packet's channel.
*/
public int getChannel()
{
return channel;
public int getChannel() {
return this.channel;
}
/**
@@ -62,21 +59,18 @@ public class Packet
*
* @return This channel to reply on.
*/
public int getReplyChannel()
{
return replyChannel;
public int getReplyChannel() {
return this.replyChannel;
}
/**
* The actual data of this packet. This should be a "valid" Lua object, safe for queuing as an
* event or returning from a peripheral call.
* The actual data of this packet. This should be a "valid" Lua object, safe for queuing as an event or returning from a peripheral call.
*
* @return The packet's payload
*/
@Nullable
public Object getPayload()
{
return payload;
public Object getPayload() {
return this.payload;
}
/**
@@ -85,33 +79,40 @@ public class Packet
* @return The sending object.
*/
@Nonnull
public IPacketSender getSender()
{
return sender;
public IPacketSender getSender() {
return this.sender;
}
@Override
public boolean equals( Object o )
{
if( this == o ) return true;
if( o == null || getClass() != o.getClass() ) return false;
public int hashCode() {
int result;
result = this.channel;
result = 31 * result + this.replyChannel;
result = 31 * result + (this.payload != null ? this.payload.hashCode() : 0);
result = 31 * result + this.sender.hashCode();
return result;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || this.getClass() != o.getClass()) {
return false;
}
Packet packet = (Packet) o;
if( channel != packet.channel ) return false;
if( replyChannel != packet.replyChannel ) return false;
if( !Objects.equals( payload, packet.payload ) ) return false;
return sender.equals( packet.sender );
}
@Override
public int hashCode()
{
int result;
result = channel;
result = 31 * result + replyChannel;
result = 31 * result + (payload != null ? payload.hashCode() : 0);
result = 31 * result + sender.hashCode();
return result;
if (this.channel != packet.channel) {
return false;
}
if (this.replyChannel != packet.replyChannel) {
return false;
}
if (!Objects.equals(this.payload, packet.payload)) {
return false;
}
return this.sender.equals(packet.sender);
}
}

View File

@@ -1,10 +0,0 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
@API( owner = "ComputerCraft", provides = "ComputerCraft|API|Network", apiVersion = "${version}" )
package dan200.computercraft.api.network;
import net.minecraftforge.fml.common.API;

View File

@@ -1,35 +1,31 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.network.wired;
import dan200.computercraft.api.ComputerCraftAPI;
import javax.annotation.Nonnull;
import dan200.computercraft.api.ComputerCraftAPI;
/**
* An object which may be part of a wired network.
*
* Elements should construct a node using {@link ComputerCraftAPI#createWiredNodeForElement(IWiredElement)}. This acts
* as a proxy for all network objects. Whilst the node may change networks, an element's node should remain constant
* for its lifespan.
* Elements should construct a node using {@link ComputerCraftAPI#createWiredNodeForElement(IWiredElement)}. This acts as a proxy for all network objects.
* Whilst the node may change networks, an element's node should remain constant for its lifespan.
*
* Elements are generally tied to a block or tile entity in world. In such as case, one should provide the
* {@link IWiredElement} capability for the appropriate sides.
* Elements are generally tied to a block or tile entity in world. In such as case, one should provide the {@link IWiredElement} capability for the
* appropriate sides.
*/
public interface IWiredElement extends IWiredSender
{
public interface IWiredElement extends IWiredSender {
/**
* Called when objects on the network change. This may occur when network nodes are added or removed, or when
* peripherals change.
* Called when objects on the network change. This may occur when network nodes are added or removed, or when peripherals change.
*
* @param change The change which occurred.
* @see IWiredNetworkChange
*/
default void networkChanged( @Nonnull IWiredNetworkChange change )
{
default void networkChanged(@Nonnull IWiredNetworkChange change) {
}
}

View File

@@ -1,53 +1,51 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.network.wired;
import dan200.computercraft.api.peripheral.IPeripheral;
import javax.annotation.Nonnull;
import java.util.Map;
import javax.annotation.Nonnull;
import dan200.computercraft.api.peripheral.IPeripheral;
/**
* A wired network is composed of one of more {@link IWiredNode}s, a set of connections between them, and a series
* of peripherals.
* A wired network is composed of one of more {@link IWiredNode}s, a set of connections between them, and a series of peripherals.
*
* Networks from a connected graph. This means there is some path between all nodes on the network. Further more, if
* there is some path between two nodes then they must be on the same network. {@link IWiredNetwork} will automatically
* handle the merging and splitting of networks (and thus changing of available nodes and peripherals) as connections
* change.
* Networks from a connected graph. This means there is some path between all nodes on the network. Further more, if there is some path between two nodes
* then they must be on the same network. {@link IWiredNetwork} will automatically handle the merging and splitting of networks (and thus changing of
* available nodes and peripherals) as connections change.
*
* This does mean one can not rely on the network remaining consistent between subsequent operations. Consequently,
* it is generally preferred to use the methods provided by {@link IWiredNode}.
* This does mean one can not rely on the network remaining consistent between subsequent operations. Consequently, it is generally preferred to use the
* methods provided by {@link IWiredNode}.
*
* @see IWiredNode#getNetwork()
*/
public interface IWiredNetwork
{
public interface IWiredNetwork {
/**
* Create a connection between two nodes.
*
* This should only be used on the server thread.
*
* @param left The first node to connect
* @param left The first node to connect
* @param right The second node to connect
* @return {@code true} if a connection was created or {@code false} if the connection already exists.
* @throws IllegalStateException If neither node is on the network.
* @throws IllegalStateException If neither node is on the network.
* @throws IllegalArgumentException If {@code left} and {@code right} are equal.
* @see IWiredNode#connectTo(IWiredNode)
* @see IWiredNetwork#connect(IWiredNode, IWiredNode)
*/
boolean connect( @Nonnull IWiredNode left, @Nonnull IWiredNode right );
boolean connect(@Nonnull IWiredNode left, @Nonnull IWiredNode right);
/**
* Destroy a connection between this node and another.
*
* This should only be used on the server thread.
*
* @param left The first node in the connection.
* @param left The first node in the connection.
* @param right The second node in the connection.
* @return {@code true} if a connection was destroyed or {@code false} if no connection exists.
* @throws IllegalArgumentException If either node is not on the network.
@@ -55,32 +53,29 @@ public interface IWiredNetwork
* @see IWiredNode#disconnectFrom(IWiredNode)
* @see IWiredNetwork#connect(IWiredNode, IWiredNode)
*/
boolean disconnect( @Nonnull IWiredNode left, @Nonnull IWiredNode right );
boolean disconnect(@Nonnull IWiredNode left, @Nonnull IWiredNode right);
/**
* Sever all connections this node has, removing it from this network.
*
* This should only be used on the server thread. You should only call this on nodes
* that your network element owns.
* This should only be used on the server thread. You should only call this on nodes that your network element owns.
*
* @param node The node to remove
* @return Whether this node was removed from the network. One cannot remove a node from a network where it is the
* only element.
* @return Whether this node was removed from the network. One cannot remove a node from a network where it is the only element.
* @throws IllegalArgumentException If the node is not in the network.
* @see IWiredNode#remove()
*/
boolean remove( @Nonnull IWiredNode node );
boolean remove(@Nonnull IWiredNode node);
/**
* Update the peripherals a node provides.
*
* This should only be used on the server thread. You should only call this on nodes
* that your network element owns.
* This should only be used on the server thread. You should only call this on nodes that your network element owns.
*
* @param node The node to attach peripherals for.
* @param node The node to attach peripherals for.
* @param peripherals The new peripherals for this node.
* @throws IllegalArgumentException If the node is not in the network.
* @see IWiredNode#updatePeripherals(Map)
*/
void updatePeripherals( @Nonnull IWiredNode node, @Nonnull Map<String, IPeripheral> peripherals );
void updatePeripherals(@Nonnull IWiredNode node, @Nonnull Map<String, IPeripheral> peripherals);
}

View File

@@ -1,26 +1,26 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.network.wired;
import dan200.computercraft.api.peripheral.IPeripheral;
import java.util.Map;
import javax.annotation.Nonnull;
import java.util.Map;
import dan200.computercraft.api.peripheral.IPeripheral;
/**
* Represents a change to the objects on a wired network.
*
* @see IWiredElement#networkChanged(IWiredNetworkChange)
*/
public interface IWiredNetworkChange
{
public interface IWiredNetworkChange {
/**
* A set of peripherals which have been removed. Note that there may be entries with the same name
* in the added and removed set, but with a different peripheral.
* A set of peripherals which have been removed. Note that there may be entries with the same name in the added and removed set, but with a different
* peripheral.
*
* @return The set of removed peripherals.
*/
@@ -28,8 +28,8 @@ public interface IWiredNetworkChange
Map<String, IPeripheral> peripheralsRemoved();
/**
* A set of peripherals which have been added. Note that there may be entries with the same name
* in the added and removed set, but with a different peripheral.
* A set of peripherals which have been added. Note that there may be entries with the same name in the added and removed set, but with a different
* peripheral.
*
* @return The set of added peripherals.
*/

View File

@@ -1,32 +1,31 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.network.wired;
import dan200.computercraft.api.network.IPacketNetwork;
import dan200.computercraft.api.peripheral.IPeripheral;
import java.util.Map;
import javax.annotation.Nonnull;
import java.util.Map;
import dan200.computercraft.api.network.IPacketNetwork;
import dan200.computercraft.api.peripheral.IPeripheral;
/**
* Wired nodes act as a layer between {@link IWiredElement}s and {@link IWiredNetwork}s.
*
* Firstly, a node acts as a packet network, capable of sending and receiving modem messages to connected nodes. These
* methods may be safely used on any thread.
* Firstly, a node acts as a packet network, capable of sending and receiving modem messages to connected nodes. These methods may be safely used on any
* thread.
*
* When sending a packet, the system will attempt to find the shortest path between the two nodes based on their
* element's position. Note that packet senders and receivers can have different locations from their associated
* element: the distance between the two will be added to the total packet's distance.
* When sending a packet, the system will attempt to find the shortest path between the two nodes based on their element's position. Note that packet
* senders and receivers can have different locations from their associated element: the distance between the two will be added to the total packet's
* distance.
*
* Wired nodes also provide several convenience methods for interacting with a wired network. These should only ever
* be used on the main server thread.
* Wired nodes also provide several convenience methods for interacting with a wired network. These should only ever be used on the main server thread.
*/
public interface IWiredNode extends IPacketNetwork
{
public interface IWiredNode extends IPacketNetwork {
/**
* The associated element for this network node.
*
@@ -35,17 +34,6 @@ public interface IWiredNode extends IPacketNetwork
@Nonnull
IWiredElement getElement();
/**
* The network this node is currently connected to. Note that this may change
* after any network operation, so it should not be cached.
*
* This should only be used on the server thread.
*
* @return This node's network.
*/
@Nonnull
IWiredNetwork getNetwork();
/**
* Create a connection from this node to another.
*
@@ -56,11 +44,20 @@ public interface IWiredNode extends IPacketNetwork
* @see IWiredNetwork#connect(IWiredNode, IWiredNode)
* @see IWiredNode#disconnectFrom(IWiredNode)
*/
default boolean connectTo( @Nonnull IWiredNode node )
{
return getNetwork().connect( this, node );
default boolean connectTo(@Nonnull IWiredNode node) {
return this.getNetwork().connect(this, node);
}
/**
* The network this node is currently connected to. Note that this may change after any network operation, so it should not be cached.
*
* This should only be used on the server thread.
*
* @return This node's network.
*/
@Nonnull
IWiredNetwork getNetwork();
/**
* Destroy a connection between this node and another.
*
@@ -72,38 +69,32 @@ public interface IWiredNode extends IPacketNetwork
* @see IWiredNetwork#disconnect(IWiredNode, IWiredNode)
* @see IWiredNode#connectTo(IWiredNode)
*/
default boolean disconnectFrom( @Nonnull IWiredNode node )
{
return getNetwork().disconnect( this, node );
default boolean disconnectFrom(@Nonnull IWiredNode node) {
return this.getNetwork().disconnect(this, node);
}
/**
* Sever all connections this node has, removing it from this network.
*
* This should only be used on the server thread. You should only call this on nodes
* that your network element owns.
* This should only be used on the server thread. You should only call this on nodes that your network element owns.
*
* @return Whether this node was removed from the network. One cannot remove a node from a network where it is the
* only element.
* @return Whether this node was removed from the network. One cannot remove a node from a network where it is the only element.
* @throws IllegalArgumentException If the node is not in the network.
* @see IWiredNetwork#remove(IWiredNode)
*/
default boolean remove()
{
return getNetwork().remove( this );
default boolean remove() {
return this.getNetwork().remove(this);
}
/**
* Mark this node's peripherals as having changed.
*
* This should only be used on the server thread. You should only call this on nodes
* that your network element owns.
* This should only be used on the server thread. You should only call this on nodes that your network element owns.
*
* @param peripherals The new peripherals for this node.
* @see IWiredNetwork#updatePeripherals(IWiredNode, Map)
*/
default void updatePeripherals( @Nonnull Map<String, IPeripheral> peripherals )
{
getNetwork().updatePeripherals( this, peripherals );
default void updatePeripherals(@Nonnull Map<String, IPeripheral> peripherals) {
this.getNetwork().updatePeripherals(this, peripherals);
}
}

View File

@@ -1,28 +1,25 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.network.wired;
import dan200.computercraft.api.network.IPacketSender;
import javax.annotation.Nonnull;
import dan200.computercraft.api.network.IPacketSender;
/**
* An object on a {@link IWiredNetwork} capable of sending packets.
*
* Unlike a regular {@link IPacketSender}, this must be associated with the node you are attempting to
* to send the packet from.
* Unlike a regular {@link IPacketSender}, this must be associated with the node you are attempting to to send the packet from.
*/
public interface IWiredSender extends IPacketSender
{
public interface IWiredSender extends IPacketSender {
/**
* The node in the network representing this object.
*
* This should be used as a proxy for the main network. One should send packets
* and register receivers through this object.
* This should be used as a proxy for the main network. One should send packets and register receivers through this object.
*
* @return The node for this element.
*/

View File

@@ -1,10 +0,0 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
@API( owner = "ComputerCraft", provides = "ComputerCraft|API|Network|Wired", apiVersion = "${version}" )
package dan200.computercraft.api.network.wired;
import net.minecraftforge.fml.common.API;

View File

@@ -1,10 +0,0 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
@API( owner = "ComputerCraft", provides = "ComputerCraft|API", apiVersion = "${version}" )
package dan200.computercraft.api;
import net.minecraftforge.fml.common.API;

View File

@@ -1,167 +1,160 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.peripheral;
import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.filesystem.IMount;
import dan200.computercraft.api.filesystem.IWritableMount;
import net.minecraft.world.World;
import java.util.Map;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Collections;
import java.util.Map;
import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.filesystem.IMount;
import dan200.computercraft.api.filesystem.IWritableMount;
import dan200.computercraft.api.lua.ILuaCallback;
import dan200.computercraft.api.lua.ILuaContext;
import dan200.computercraft.api.lua.ILuaTask;
import dan200.computercraft.api.lua.MethodResult;
import net.minecraft.world.World;
/**
* The interface passed to peripherals by computers or turtles, providing methods
* that they can call. This should not be implemented by your classes. Do not interact
* with computers except via this interface.
* The interface passed to peripherals by computers or turtles, providing methods that they can call. This should not be implemented by your classes. Do not
* interact with computers except via this interface.
*/
public interface IComputerAccess
{
public interface IComputerAccess {
/**
* Mount a mount onto the computer's file system in a read only mode.
*
* @param desiredLocation The location on the computer's file system where you would like the mount to be mounted.
* @param mount The mount object to mount on the computer.
* @return The location on the computer's file system where you the mount mounted, or {@code null} if there was already a
* file in the desired location. Store this value if you wish to unmount the mount later.
* @throws RuntimeException If the peripheral has been detached.
* @param mount The mount object to mount on the computer.
* @return The location on the computer's file system where you the mount mounted, or {@code null} if there was already a file in the desired location.
* Store this value if you wish to unmount the mount later.
* @throws NotAttachedException If the peripheral has been detached.
* @see ComputerCraftAPI#createSaveDirMount(World, String, long)
* @see ComputerCraftAPI#createResourceMount(Class, String, String)
* @see ComputerCraftAPI#createResourceMount(String, String)
* @see #mount(String, IMount, String)
* @see #mountWritable(String, IWritableMount)
* @see #unmount(String)
* @see IMount
*/
@Nullable
default String mount( @Nonnull String desiredLocation, @Nonnull IMount mount )
{
return mount( desiredLocation, mount, getAttachmentName() );
default String mount(@Nonnull String desiredLocation, @Nonnull IMount mount) {
return this.mount(desiredLocation, mount, this.getAttachmentName());
}
/**
* Mount a mount onto the computer's file system in a read only mode.
*
* @param desiredLocation The location on the computer's file system where you would like the mount to be mounted.
* @param mount The mount object to mount on the computer.
* @param driveName A custom name to give for this mount location, as returned by {@code fs.getDrive()}.
* @return The location on the computer's file system where you the mount mounted, or {@code null} if there was already a
* file in the desired location. Store this value if you wish to unmount the mount later.
* @throws RuntimeException If the peripheral has been detached.
* @param mount The mount object to mount on the computer.
* @param driveName A custom name to give for this mount location, as returned by {@code fs.getDrive()}.
* @return The location on the computer's file system where you the mount mounted, or {@code null} if there was already a file in the desired location.
* Store this value if you wish to unmount the mount later.
* @throws NotAttachedException If the peripheral has been detached.
* @see ComputerCraftAPI#createSaveDirMount(World, String, long)
* @see ComputerCraftAPI#createResourceMount(Class, String, String)
* @see ComputerCraftAPI#createResourceMount(String, String)
* @see #mount(String, IMount)
* @see #mountWritable(String, IWritableMount)
* @see #unmount(String)
* @see IMount
*/
@Nullable
String mount( @Nonnull String desiredLocation, @Nonnull IMount mount, @Nonnull String driveName );
String mount(@Nonnull String desiredLocation, @Nonnull IMount mount, @Nonnull String driveName);
/**
* Get a string, unique to the computer, by which the computer refers to this peripheral. For directly attached peripherals this will be
* "left","right","front","back",etc, but for peripherals attached remotely it will be different. It is good practice to supply this string when raising
* events to the computer, so that the computer knows from which peripheral the event came.
*
* @return A string unique to the computer, but not globally.
* @throws NotAttachedException If the peripheral has been detached.
*/
@Nonnull
String getAttachmentName();
/**
* Mount a mount onto the computer's file system in a writable mode.
*
* @param desiredLocation The location on the computer's file system where you would like the mount to be mounted.
* @param mount The mount object to mount on the computer.
* @return The location on the computer's file system where you the mount mounted, or null if there was already a
* file in the desired location. Store this value if you wish to unmount the mount later.
* @throws RuntimeException If the peripheral has been detached.
* @param mount The mount object to mount on the computer.
* @return The location on the computer's file system where you the mount mounted, or null if there was already a file in the desired location. Store
* this value if you wish to unmount the mount later.
* @throws NotAttachedException If the peripheral has been detached.
* @see ComputerCraftAPI#createSaveDirMount(World, String, long)
* @see ComputerCraftAPI#createResourceMount(Class, String, String)
* @see ComputerCraftAPI#createResourceMount(String, String)
* @see #mount(String, IMount)
* @see #unmount(String)
* @see IMount
*/
@Nullable
default String mountWritable( @Nonnull String desiredLocation, @Nonnull IWritableMount mount )
{
return mountWritable( desiredLocation, mount, getAttachmentName() );
default String mountWritable(@Nonnull String desiredLocation, @Nonnull IWritableMount mount) {
return this.mountWritable(desiredLocation, mount, this.getAttachmentName());
}
/**
* Mount a mount onto the computer's file system in a writable mode.
*
* @param desiredLocation The location on the computer's file system where you would like the mount to be mounted.
* @param mount The mount object to mount on the computer.
* @param driveName A custom name to give for this mount location, as returned by {@code fs.getDrive()}.
* @return The location on the computer's file system where you the mount mounted, or null if there was already a
* file in the desired location. Store this value if you wish to unmount the mount later.
* @throws RuntimeException If the peripheral has been detached.
* @param mount The mount object to mount on the computer.
* @param driveName A custom name to give for this mount location, as returned by {@code fs.getDrive()}.
* @return The location on the computer's file system where you the mount mounted, or null if there was already a file in the desired location. Store
* this value if you wish to unmount the mount later.
* @throws NotAttachedException If the peripheral has been detached.
* @see ComputerCraftAPI#createSaveDirMount(World, String, long)
* @see ComputerCraftAPI#createResourceMount(Class, String, String)
* @see ComputerCraftAPI#createResourceMount(String, String)
* @see #mount(String, IMount)
* @see #unmount(String)
* @see IMount
*/
String mountWritable( @Nonnull String desiredLocation, @Nonnull IWritableMount mount, @Nonnull String driveName );
String mountWritable(@Nonnull String desiredLocation, @Nonnull IWritableMount mount, @Nonnull String driveName);
/**
* Unmounts a directory previously mounted onto the computers file system by {@link #mount(String, IMount)}
* or {@link #mountWritable(String, IWritableMount)}.
* Unmounts a directory previously mounted onto the computers file system by {@link #mount(String, IMount)} or {@link #mountWritable(String,
* IWritableMount)}.
*
* When a directory is unmounted, it will disappear from the computers file system, and the user will no longer be
* able to access it. All directories mounted by a mount or mountWritable are automatically unmounted when the
* peripheral is attached if they have not been explicitly unmounted.
* When a directory is unmounted, it will disappear from the computers file system, and the user will no longer be able to access it. All directories
* mounted by a mount or mountWritable are automatically unmounted when the peripheral is attached if they have not been explicitly unmounted.
*
* Note that you cannot unmount another peripheral's mounts.
*
* @param location The desired location in the computers file system of the directory to unmount.
* This must be the location of a directory previously mounted by {@link #mount(String, IMount)} or
* {@link #mountWritable(String, IWritableMount)}, as indicated by their return value.
* @throws RuntimeException If the peripheral has been detached.
* @throws RuntimeException If the mount does not exist, or was mounted by another peripheral.
* @param location The desired location in the computers file system of the directory to unmount. This must be the location of a directory
* previously mounted by {@link #mount(String, IMount)} or {@link #mountWritable(String, IWritableMount)}, as indicated by their return value.
* @throws NotAttachedException If the peripheral has been detached.
* @throws IllegalStateException If the mount does not exist, or was mounted by another peripheral.
* @see #mount(String, IMount)
* @see #mountWritable(String, IWritableMount)
*/
void unmount( @Nullable String location );
void unmount(@Nullable String location);
/**
* Returns the numerical ID of this computer.
*
* This is the same number obtained by calling {@code os.getComputerID()} or running the "id" program from lua,
* and is guaranteed unique. This number will be positive.
* This is the same number obtained by calling {@code os.getComputerID()} or running the "id" program from lua, and is guaranteed unique. This number
* will be positive.
*
* @return The identifier.
*/
int getID();
/**
* Causes an event to be raised on this computer, which the computer can respond to by calling
* {@code os.pullEvent()}. This can be used to notify the computer when things happen in the world or to
* this peripheral.
* Causes an event to be raised on this computer, which the computer can respond to by calling {@code os.pullEvent()}. This can be used to notify the
* computer when things happen in the world or to this peripheral.
*
* @param event A string identifying the type of event that has occurred, this will be
* returned as the first value from {@code os.pullEvent()}. It is recommended that you
* you choose a name that is unique, and recognisable as originating from your
* peripheral. eg: If your peripheral type is "button", a suitable event would be
* "button_pressed".
* @param arguments In addition to a name, you may pass an array of extra arguments to the event, that will
* be supplied as extra return values to os.pullEvent(). Objects in the array will be converted
* to lua data types in the same fashion as the return values of IPeripheral.callMethod().
* @param event A string identifying the type of event that has occurred, this will be returned as the first value from {@code os.pullEvent()}. It
* is recommended that you you choose a name that is unique, and recognisable as originating from your peripheral. eg: If your peripheral type is
* "button", a suitable event would be "button_pressed".
* @param arguments In addition to a name, you may pass an array of extra arguments to the event, that will be supplied as extra return values to
* os.pullEvent(). Objects in the array will be converted to lua data types in the same fashion as the return values of IPeripheral.callMethod().
*
* You may supply {@code null} to indicate that no arguments are to be supplied.
* @throws RuntimeException If the peripheral has been detached.
* @see dan200.computercraft.api.peripheral.IPeripheral#callMethod
* You may supply {@code null} to indicate that no arguments are to be supplied.
* @throws NotAttachedException If the peripheral has been detached.
* @see MethodResult#pullEvent(String, ILuaCallback)
*/
void queueEvent( @Nonnull String event, @Nullable Object[] arguments );
/**
* Get a string, unique to the computer, by which the computer refers to this peripheral.
* For directly attached peripherals this will be "left","right","front","back",etc, but
* for peripherals attached remotely it will be different. It is good practice to supply
* this string when raising events to the computer, so that the computer knows from
* which peripheral the event came.
*
* @return A string unique to the computer, but not globally.
* @throws RuntimeException If the peripheral has been detached.
*/
@Nonnull
String getAttachmentName();
void queueEvent(@Nonnull String event, @Nullable Object... arguments);
/**
* Get a set of peripherals that this computer access can "see", along with their attachment name.
@@ -169,26 +162,36 @@ public interface IComputerAccess
* This may include other peripherals on the wired network or peripherals on other sides of the computer.
*
* @return All reachable peripherals
* @throws NotAttachedException If the peripheral has been detached.
* @see #getAttachmentName()
* @see #getAvailablePeripheral(String)
*/
@Nonnull
default Map<String, IPeripheral> getAvailablePeripherals()
{
return Collections.emptyMap();
}
Map<String, IPeripheral> getAvailablePeripherals();
/**
* Get a reachable peripheral with the given attachement name. This is a equivalent to
* {@link #getAvailablePeripherals()}{@code .get(name)}, though may be more performant.
* Get a reachable peripheral with the given attachment name. This is a equivalent to {@link #getAvailablePeripherals()}{@code .get(name)}, though may
* be more efficient.
*
* @param name The peripheral's attached name
* @return The reachable peripheral, or {@code null} if none can be found.
* @see #getAvailablePeripherals()
*/
@Nullable
default IPeripheral getAvailablePeripheral( @Nonnull String name )
{
return null;
}
IPeripheral getAvailablePeripheral(@Nonnull String name);
/**
* Get a {@link IWorkMonitor} for tasks your peripheral might execute on the main (server) thread.
*
* This should be used to ensure your peripheral integrates with ComputerCraft's monitoring and limiting of how much server time each computer consumes.
* You should not need to use this if you use {@link ILuaContext#issueMainThreadTask(ILuaTask)} - this is intended for mods with their own system for
* running work on the main thread.
*
* Please note that the returned implementation is <em>not</em> thread-safe, and should only be used from the main thread.
*
* @return The work monitor for the main thread, or {@code null} if this computer does not have one.
* @throws NotAttachedException If the peripheral has been detached.
*/
@Nonnull
IWorkMonitor getMainThreadMonitor();
}

View File

@@ -0,0 +1,53 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.peripheral;
import javax.annotation.Nonnull;
import dan200.computercraft.api.lua.IArguments;
import dan200.computercraft.api.lua.IDynamicLuaObject;
import dan200.computercraft.api.lua.ILuaContext;
import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.api.lua.LuaFunction;
import dan200.computercraft.api.lua.MethodResult;
/**
* A peripheral whose methods are not known at runtime.
*
* This behaves similarly to {@link IDynamicLuaObject}, though also accepting the current {@link IComputerAccess}. Generally one may use {@link LuaFunction}
* instead of implementing this interface.
*/
public interface IDynamicPeripheral extends IPeripheral {
/**
* Should return an array of strings that identify the methods that this peripheral exposes to Lua. This will be called once before each attachment, and
* should not change when called multiple times.
*
* @return An array of strings representing method names.
* @see #callMethod
*/
@Nonnull
String[] getMethodNames();
/**
* This is called when a lua program on an attached computer calls {@code peripheral.call()} with one of the methods exposed by {@link
* #getMethodNames()}.
*
* Be aware that this will be called from the ComputerCraft Lua thread, and must be thread-safe when interacting with Minecraft objects.
*
* @param computer The interface to the computer that is making the call. Remember that multiple computers can be attached to a peripheral at once.
* @param context The context of the currently running lua thread. This can be used to wait for events or otherwise yield.
* @param method An integer identifying which of the methods from getMethodNames() the computercraft wishes to call. The integer indicates the index
* into the getMethodNames() table that corresponds to the string passed into peripheral.call()
* @param arguments The arguments for this method.
* @return A {@link MethodResult} containing the values to return or the action to perform.
* @throws LuaException If you throw any exception from this function, a lua error will be raised with the same message as your exception. Use this
* to throw appropriate errors if the wrong arguments are supplied to your method.
* @see #getMethodNames()
*/
@Nonnull
MethodResult callMethod(@Nonnull IComputerAccess computer, @Nonnull ILuaContext context, int method, @Nonnull IArguments arguments) throws LuaException;
}

View File

@@ -1,25 +1,27 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.peripheral;
import dan200.computercraft.api.lua.ILuaContext;
import dan200.computercraft.api.lua.LuaException;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import dan200.computercraft.api.lua.LuaFunction;
/**
* The interface that defines a peripheral. See {@link IPeripheralProvider} for how to associate blocks with peripherals.
* The interface that defines a peripheral.
*
* In order to expose a peripheral for your block or tile entity, you 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}.
*/
public interface IPeripheral
{
public interface IPeripheral {
/**
* Should return a string that uniquely identifies this type of peripheral.
* This can be queried from lua by calling {@code peripheral.getType()}
* Should return a string that uniquely identifies this type of peripheral. This can be queried from lua by calling {@code peripheral.getType()}
*
* @return A string identifying the type of peripheral.
*/
@@ -27,113 +29,56 @@ public interface IPeripheral
String getType();
/**
* Should return an array of strings that identify the methods that this
* peripheral exposes to Lua. This will be called once before each attachment,
* and should not change when called multiple times.
* Is called when when a computer is attaching to the peripheral.
*
* @return An array of strings representing method names.
* @see #callMethod
*/
@Nonnull
String[] getMethodNames();
/**
* This is called when a lua program on an attached computer calls {@code peripheral.call()} with
* one of the methods exposed by {@link #getMethodNames()}.
* This will occur when a peripheral is placed next to an active computer, when a computer is turned on next to a peripheral, when a turtle travels into
* a square next to a peripheral, or when a wired modem adjacent to this peripheral is does any of the above.
*
* Be aware that this will be called from the ComputerCraft Lua thread, and must be thread-safe
* when interacting with Minecraft objects.
* Between calls to attach and {@link #detach}, the attached computer can make method calls on the peripheral using {@code peripheral.call()}. This
* method can be used to keep track of which computers are attached to the peripheral, or to take action when attachment occurs.
*
* @param computer The interface to the computer that is making the call. Remember that multiple
* computers can be attached to a peripheral at once.
* @param context The context of the currently running lua thread. This can be used to wait for events
* or otherwise yield.
* @param method An integer identifying which of the methods from getMethodNames() the computercraft
* wishes to call. The integer indicates the index into the getMethodNames() table
* that corresponds to the string passed into peripheral.call()
* @param arguments An array of objects, representing the arguments passed into {@code peripheral.call()}.<br>
* Lua values of type "string" will be represented by Object type String.<br>
* Lua values of type "number" will be represented by Object type Double.<br>
* Lua values of type "boolean" will be represented by Object type Boolean.<br>
* Lua values of type "table" will be represented by Object type Map.<br>
* Lua values of any other type will be represented by a null object.<br>
* This array will be empty if no arguments are passed.
* @return An array of objects, representing values you wish to return to the lua program. Integers, Doubles, Floats,
* Strings, Booleans, Maps and ILuaObject and null be converted to their corresponding lua type. All other types
* will be converted to nil.
* Be aware that will be called from both the server thread and ComputerCraft Lua thread, and so must be thread-safe and reentrant.
*
* You may return null to indicate no values should be returned.
* @throws LuaException If you throw any exception from this function, a lua error will be raised with the
* same message as your exception. Use this to throw appropriate errors if the wrong
* arguments are supplied to your method.
* @throws InterruptedException If the user shuts down or reboots the computer the coroutine is suspended,
* InterruptedException will be thrown. This exception must not be caught or
* intercepted, or the computer will leak memory and end up in a broken state.
* @see #getMethodNames
*/
@Nullable
Object[] callMethod( @Nonnull IComputerAccess computer, @Nonnull ILuaContext context, int method, @Nonnull Object[] arguments ) throws LuaException, InterruptedException;
/**
* Is called when canAttachToSide has returned true, and a computer is attaching to the peripheral.
*
* This will occur when a peripheral is placed next to an active computer, when a computer is turned on next to a
* peripheral, or when a turtle travels into a square next to a peripheral.
*
* Between calls to attach() and detach(), the attached computer can make method calls on the peripheral using
* {@code peripheral.call()}. This method can be used to keep track of which computers are attached to the
* peripheral, or to take action when attachment occurs.
*
* Be aware that this will be called from the ComputerCraft Lua thread, and must be thread-safe
* when interacting with Minecraft objects.
*
* @param computer The interface to the computer that is being attached. Remember that multiple
* computers can be attached to a peripheral at once.
* @param computer The interface to the computer that is being attached. Remember that multiple computers can be attached to a peripheral at once.
* @see #detach
*/
default void attach( @Nonnull IComputerAccess computer )
{
default void attach(@Nonnull IComputerAccess computer) {
}
/**
* Is called when a computer is detaching from the peripheral.
* Called when a computer is detaching from the peripheral.
*
* This will occur when a computer shuts down, when the peripheral is removed while attached to computers,
* or when a turtle moves away from a square attached to a peripheral. This method can be used to keep track of
* which computers are attached to the peripheral, or to take action when detachment
* occurs.
* This will occur when a computer shuts down, when the peripheral is removed while attached to computers, when a turtle moves away from a block
* attached to a peripheral, or when a wired modem adjacent to this peripheral is detached.
*
* Be aware that this will be called from the ComputerCraft Lua thread, and must be thread-safe
* when interacting with Minecraft objects.
* This method can be used to keep track of which computers are attached to the peripheral, or to take action when detachment occurs.
*
* @param computer The interface to the computer that is being detached. Remember that multiple
* computers can be attached to a peripheral at once.
* @see #detach
* Be aware that this will be called from both the server and ComputerCraft Lua thread, and must be thread-safe and reentrant.
*
* @param computer The interface to the computer that is being detached. Remember that multiple computers can be attached to a peripheral at once.
* @see #attach
*/
default void detach( @Nonnull IComputerAccess computer )
{
default void detach(@Nonnull IComputerAccess computer) {
}
/**
* Get the object that this peripheral provides methods for. This will generally be the tile entity
* or block, but may be an inventory, entity, etc...
* Get the object that this peripheral provides methods for. This will generally be the tile entity or block, but may be an inventory, entity, etc...
*
* @return The object this peripheral targets
*/
@Nonnull
default Object getTarget()
{
return this;
@Nullable
default Object getTarget() {
return null;
}
/**
* Determine whether this peripheral is equivalent to another one.
*
* The minimal example should at least check whether they are the same object. However, you may wish to check if
* they point to the same block or tile entity.
* The minimal example should at least check whether they are the same object. However, you may wish to check if they point to the same block or tile
* entity.
*
* @param other The peripheral to compare against. This may be {@code null}.
* @return Whether these peripherals are equivalent.
*/
boolean equals( @Nullable IPeripheral other );
boolean equals(@Nullable IPeripheral other);
}

View File

@@ -1,35 +1,38 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.peripheral;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import java.util.Optional;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.World;
/**
* This interface is used to create peripheral implementations for blocks.
*
* If you have a {@link BlockEntity} which acts as a peripheral, you may alternatively expose the {@link IPeripheral} capability.
*
* @see dan200.computercraft.api.ComputerCraftAPI#registerPeripheralProvider(IPeripheralProvider)
*/
@FunctionalInterface
public interface IPeripheralProvider
{
public interface IPeripheralProvider {
/**
* Produce an peripheral implementation from a block location.
*
* @param world The world the block is in.
* @param pos The position the block is at.
* @param side The side to get the peripheral from.
* @return A peripheral, or {@code null} if there is not a peripheral here you'd like to handle.
* @param pos The position the block is at.
* @param side The side to get the peripheral from.
* @return A peripheral, or {@link Optional#empty()} if there is not a peripheral here you'd like to handle.
* @see dan200.computercraft.api.ComputerCraftAPI#registerPeripheralProvider(IPeripheralProvider)
*/
@Nullable
IPeripheral getPeripheral( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull EnumFacing side );
@Nonnull
IPeripheral getPeripheral(@Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side);
}

View File

@@ -0,0 +1,31 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.peripheral;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.World;
/**
* A {@link net.minecraft.block.entity.BlockEntity} which may act as a peripheral.
*
* If you need more complex capabilities (such as handling TEs not belonging to your mod), you should use {@link IPeripheralProvider}.
*/
public interface IPeripheralTile {
/**
* Get the peripheral on the given {@code side}.
*
* @param side The side to get the peripheral from.
* @return A peripheral, or {@code null} if there is not a peripheral here.
* @see IPeripheralProvider#getPeripheral(World, BlockPos, Direction)
*/
@Nullable
IPeripheral getPeripheral(@Nonnull Direction side);
}

View File

@@ -0,0 +1,75 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.peripheral;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nonnull;
/**
* Monitors "work" associated with a computer, keeping track of how much a computer has done, and ensuring every computer receives a fair share of any
* processing time.
*
* This is primarily intended for work done by peripherals on the main thread (such as on a tile entity's tick), but could be used for other purposes (such
* as complex computations done on another thread).
*
* Before running a task, one should call {@link #canWork()} to determine if the computer is currently allowed to execute work. If that returns true, you
* should execute the task and use {@link #trackWork(long, TimeUnit)} to inform the monitor how long that task took.
*
* Alternatively, use {@link #runWork(Runnable)} to run and keep track of work.
*
* @see IComputerAccess#getMainThreadMonitor()
*/
public interface IWorkMonitor {
/**
* If the owning computer is currently allowed to execute work, and has ample time to do so.
*
* This is effectively a more restrictive form of {@link #canWork()}. One should use that in order to determine if you may do an initial piece of work,
* and shouldWork to determine if any additional task may be performed.
*
* @return If we should execute work right now.
*/
boolean shouldWork();
/**
* Run a task if possible, and inform the monitor of how long it took.
*
* @param runnable The task to run.
* @return If the task was actually run (namely, {@link #canWork()} returned {@code true}).
*/
default boolean runWork(@Nonnull Runnable runnable) {
Objects.requireNonNull(runnable, "runnable should not be null");
if (!this.canWork()) {
return false;
}
long start = System.nanoTime();
try {
runnable.run();
} finally {
this.trackWork(System.nanoTime() - start, TimeUnit.NANOSECONDS);
}
return true;
}
/**
* If the owning computer is currently allowed to execute work.
*
* @return If we can execute work right now.
*/
boolean canWork();
/**
* Inform the monitor how long some piece of work took to execute.
*
* @param time The time some task took to run
* @param unit The unit that {@code time} was measured in.
*/
void trackWork(long time, @Nonnull TimeUnit unit);
}

View File

@@ -0,0 +1,22 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.peripheral;
/**
* Thrown when performing operations on {@link IComputerAccess} when the current peripheral is no longer attached to the computer.
*/
public class NotAttachedException extends IllegalStateException {
private static final long serialVersionUID = 1221244785535553536L;
public NotAttachedException() {
super("You are not attached to this computer");
}
public NotAttachedException(String s) {
super(s);
}
}

View File

@@ -1,10 +0,0 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
@API( owner = "ComputerCraft", provides = "ComputerCraft|API|Peripheral", apiVersion = "${version}" )
package dan200.computercraft.api.peripheral;
import net.minecraftforge.fml.common.API;

View File

@@ -1,42 +0,0 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.permissions;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
/**
* This interface is used to restrict where turtles can move or build.
*
* Turtles will call these methods before attempting to perform an action, allowing them to be cancelled.
*
* @see dan200.computercraft.api.ComputerCraftAPI#registerPermissionProvider(ITurtlePermissionProvider)
*/
public interface ITurtlePermissionProvider
{
/**
* Determine whether a block can be entered by a turtle.
*
* @param world The world the block exists in
* @param pos The location of the block.
* @return Whether the turtle can move into this block.
*/
boolean isBlockEnterable( @Nonnull World world, @Nonnull BlockPos pos );
/**
* Determine whether a block can be modified by a turtle.
*
* This includes breaking and placing blocks.
*
* @param world The world the block exists in
* @param pos The location of the block.
* @return Whether the turtle can modify this block.
*/
boolean isBlockEditable( @Nonnull World world, @Nonnull BlockPos pos );
}

View File

@@ -1,10 +0,0 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
@API( owner = "ComputerCraft", provides = "ComputerCraft|API|Permissions", apiVersion = "${version}" )
package dan200.computercraft.api.permissions;
import net.minecraftforge.fml.common.API;

View File

@@ -0,0 +1,60 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.pocket;
import javax.annotation.Nonnull;
import net.minecraft.item.ItemConvertible;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;
import net.minecraft.util.Util;
/**
* A base class for {@link IPocketUpgrade}s.
*
* One does not have to use this, but it does provide a convenient template.
*/
public abstract class AbstractPocketUpgrade implements IPocketUpgrade {
private final Identifier id;
private final String adjective;
private final ItemStack stack;
protected AbstractPocketUpgrade(Identifier id, ItemConvertible item) {
this(id, Util.createTranslationKey("upgrade", id) + ".adjective", item);
}
protected AbstractPocketUpgrade(Identifier id, String adjective, ItemConvertible item) {
this.id = id;
this.adjective = adjective;
this.stack = new ItemStack(item);
}
protected AbstractPocketUpgrade(Identifier id, String adjective, ItemStack stack) {
this.id = id;
this.adjective = adjective;
this.stack = stack;
}
@Nonnull
@Override
public final Identifier getUpgradeID() {
return this.id;
}
@Nonnull
@Override
public final String getUnlocalisedAdjective() {
return this.adjective;
}
@Nonnull
@Override
public final ItemStack getCraftingItem() {
return this.stack;
}
}

View File

@@ -1,29 +1,32 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.pocket;
import dan200.computercraft.api.peripheral.IPeripheral;
import net.minecraft.entity.Entity;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.ResourceLocation;
import java.util.Map;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Map;
import dan200.computercraft.api.peripheral.IPeripheral;
import net.minecraft.entity.Entity;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.util.Identifier;
/**
* Wrapper class for pocket computers
* Wrapper class for pocket computers.
*/
public interface IPocketAccess
{
public interface IPocketAccess {
/**
* Gets the entity holding this item.
*
* @return The holding entity. This may be {@code null}.
* This must be called on the server thread.
*
* @return The holding entity, or {@code null} if none exists.
*/
@Nullable
Entity getEntity();
@@ -31,8 +34,7 @@ public interface IPocketAccess
/**
* Get the colour of this pocket computer as a RGB number.
*
* @return The colour this pocket computer is. This will be a RGB colour between {@code 0x000000} and
* {@code 0xFFFFFF} or -1 if it has no colour.
* @return The colour this pocket computer is. This will be a RGB colour between {@code 0x000000} and {@code 0xFFFFFF} or -1 if it has no colour.
* @see #setColour(int)
*/
int getColour();
@@ -40,17 +42,16 @@ public interface IPocketAccess
/**
* Set the colour of the pocket computer to a RGB number.
*
* @param colour The colour this pocket computer should be changed to. This should be a RGB colour between
* {@code 0x000000} and {@code 0xFFFFFF} or -1 to reset to the default colour.
* @param colour The colour this pocket computer should be changed to. This should be a RGB colour between {@code 0x000000} and {@code 0xFFFFFF} or
* -1 to reset to the default colour.
* @see #getColour()
*/
void setColour( int colour );
void setColour(int colour);
/**
* Get the colour of this pocket computer's light as a RGB number.
*
* @return The colour this light is. This will be a RGB colour between {@code 0x000000} and {@code 0xFFFFFF} or
* -1 if it has no colour.
* @return The colour this light is. This will be a RGB colour between {@code 0x000000} and {@code 0xFFFFFF} or -1 if it has no colour.
* @see #setLight(int)
*/
int getLight();
@@ -58,11 +59,11 @@ public interface IPocketAccess
/**
* Set the colour of the pocket computer's light to a RGB number.
*
* @param colour The colour this modem's light will be changed to. This should be a RGB colour between
* {@code 0x000000} and {@code 0xFFFFFF} or -1 to reset to the default colour.
* @param colour The colour this modem's light will be changed to. This should be a RGB colour between {@code 0x000000} and {@code 0xFFFFFF} or -1
* to reset to the default colour.
* @see #getLight()
*/
void setLight( int colour );
void setLight(int colour);
/**
* Get the upgrade-specific NBT.
@@ -73,7 +74,7 @@ public interface IPocketAccess
* @see #updateUpgradeNBTData()
*/
@Nonnull
NBTTagCompound getUpgradeNBTData();
CompoundTag getUpgradeNBTData();
/**
* Mark the upgrade-specific NBT as dirty.
@@ -93,5 +94,5 @@ public interface IPocketAccess
* @return A collection of all upgrade names.
*/
@Nonnull
Map<ResourceLocation, IPeripheral> getUpgrades();
Map<Identifier, IPeripheral> getUpgrades();
}

View File

@@ -1,102 +1,61 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.pocket;
import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.api.turtle.ITurtleUpgrade;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.IUpgradeBase;
import dan200.computercraft.api.peripheral.IPeripheral;
import net.minecraft.world.World;
/**
* Additional peripherals for pocket computers.
*
* This is similar to {@link dan200.computercraft.api.turtle.ITurtleUpgrade}.
* @see ComputerCraftAPI#registerPocketUpgrade(IPocketUpgrade)
*/
public interface IPocketUpgrade
public interface IPocketUpgrade extends IUpgradeBase
{
/**
* Gets a unique identifier representing this type of turtle upgrade. eg: "computercraft:wireless_modem" or
* "my_mod:my_upgrade".
*
* You should use a unique resource domain to ensure this upgrade is uniquely identified. The upgrade will fail
* registration if an already used ID is specified.
*
* @return The upgrade's id.
* @see IPocketUpgrade#getUpgradeID()
* @see ComputerCraftAPI#registerPocketUpgrade(IPocketUpgrade)
*/
@Nonnull
ResourceLocation getUpgradeID();
/**
* Return an unlocalised string to describe the type of pocket computer this upgrade provides.
*
* An example of a built-in adjectives is "Wireless" - this is converted to "Wireless Pocket Computer".
*
* @return The unlocalised adjective.
* @see ITurtleUpgrade#getUnlocalisedAdjective()
*/
@Nonnull
String getUnlocalisedAdjective();
/**
* Return an item stack representing the type of item that a pocket computer must be crafted with to create a
* pocket computer which holds this upgrade. This item stack is also used to determine the upgrade given by
* {@code pocket.equip()}/{@code pocket.unequip()}.
*
* @return The item stack used for crafting. This can be {@link ItemStack#EMPTY} if crafting is disabled.
*/
@Nonnull
ItemStack getCraftingItem();
/**
* Creates a peripheral for the pocket computer.
*
* The peripheral created will be stored for the lifetime of the upgrade, will be passed an argument to
* {@link #update(IPocketAccess, IPeripheral)} and will be attached, detached and have methods called in the same
* manner as an ordinary peripheral.
* The peripheral created will be stored for the lifetime of the upgrade, will be passed an argument to {@link #update(IPocketAccess, IPeripheral)} and
* will be attached, detached and have methods called in the same manner as an ordinary peripheral.
*
* @param access The access object for the pocket item stack.
* @return The newly created peripheral.
* @see #update(IPocketAccess, IPeripheral)
*/
@Nullable
IPeripheral createPeripheral( @Nonnull IPocketAccess access );
IPeripheral createPeripheral(@Nonnull IPocketAccess access);
/**
* Called when the pocket computer item stack updates.
*
* @param access The access object for the pocket item stack.
* @param access The access object for the pocket item stack.
* @param peripheral The peripheral for this upgrade.
* @see #createPeripheral(IPocketAccess)
*/
default void update( @Nonnull IPocketAccess access, @Nullable IPeripheral peripheral )
{
default void update(@Nonnull IPocketAccess access, @Nullable IPeripheral peripheral) {
}
/**
* Called when the pocket computer is right clicked.
*
* @param world The world the computer is in.
* @param access The access object for the pocket item stack.
* @param world The world the computer is in.
* @param access The access object for the pocket item stack.
* @param peripheral The peripheral for this upgrade.
* @return {@code true} to stop the GUI from opening, otherwise false. You should always provide some code path
* which returns {@code false}, such as requiring the player to be sneaking - otherwise they will be unable to
* access the GUI.
* @return {@code true} to stop the GUI from opening, otherwise false. You should always provide some code path which returns {@code false}, such as
* requiring the player to be sneaking - otherwise they will be unable to access the GUI.
* @see #createPeripheral(IPocketAccess)
*/
default boolean onRightClick( @Nonnull World world, @Nonnull IPocketAccess access, @Nullable IPeripheral peripheral )
{
default boolean onRightClick(@Nonnull World world, @Nonnull IPocketAccess access, @Nullable IPeripheral peripheral) {
return false;
}
}

View File

@@ -1,34 +1,32 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.redstone;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.World;
/**
* This interface is used to provide bundled redstone output for blocks.
*
* @see dan200.computercraft.api.ComputerCraftAPI#registerBundledRedstoneProvider(IBundledRedstoneProvider)
*/
@FunctionalInterface
public interface IBundledRedstoneProvider
{
public interface IBundledRedstoneProvider {
/**
* Produce an bundled redstone output from a block location.
*
* @param world The world this block is in.
* @param pos The position this block is at.
* @param side The side to extract the bundled redstone output from.
* @return A number in the range 0-65535 to indicate this block is providing output, or -1 if you do not wish to
* handle this block.
* @param pos The position this block is at.
* @param side The side to extract the bundled redstone output from.
* @return A number in the range 0-65535 to indicate this block is providing output, or -1 if you do not wish to handle this block.
* @see dan200.computercraft.api.ComputerCraftAPI#registerBundledRedstoneProvider(IBundledRedstoneProvider)
*/
int getBundledRedstoneOutput( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull EnumFacing side );
int getBundledRedstoneOutput(@Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side);
}

View File

@@ -1,10 +0,0 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
@API( owner = "ComputerCraft", provides = "ComputerCraft|API|Redstone", apiVersion = "${version}" )
package dan200.computercraft.api.redstone;
import net.minecraftforge.fml.common.API;

View File

@@ -0,0 +1,70 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.turtle;
import javax.annotation.Nonnull;
import net.minecraft.item.ItemConvertible;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;
import net.minecraft.util.Util;
/**
* A base class for {@link ITurtleUpgrade}s.
*
* One does not have to use this, but it does provide a convenient template.
*/
public abstract class AbstractTurtleUpgrade implements ITurtleUpgrade {
private final Identifier id;
private final TurtleUpgradeType type;
private final String adjective;
private final ItemStack stack;
protected AbstractTurtleUpgrade(Identifier id, TurtleUpgradeType type, String adjective, ItemConvertible item) {
this(id, type, adjective, new ItemStack(item));
}
protected AbstractTurtleUpgrade(Identifier id, TurtleUpgradeType type, String adjective, ItemStack stack) {
this.id = id;
this.type = type;
this.adjective = adjective;
this.stack = stack;
}
protected AbstractTurtleUpgrade(Identifier id, TurtleUpgradeType type, ItemConvertible item) {
this(id, type, new ItemStack(item));
}
protected AbstractTurtleUpgrade(Identifier id, TurtleUpgradeType type, ItemStack stack) {
this(id, type, Util.createTranslationKey("upgrade", id) + ".adjective", stack);
}
@Nonnull
@Override
public final Identifier getUpgradeID() {
return this.id;
}
@Nonnull
@Override
public final String getUnlocalisedAdjective() {
return this.adjective;
}
@Nonnull
@Override
public final TurtleUpgradeType getType() {
return this.type;
}
@Nonnull
@Override
public final ItemStack getCraftingItem() {
return this.stack;
}
}

View File

@@ -0,0 +1,267 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2018. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.api.turtle;
import java.util.Collection;
import java.util.OptionalInt;
import java.util.UUID;
import javax.annotation.Nullable;
import javax.crypto.Cipher;
import com.mojang.authlib.GameProfile;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import net.minecraft.block.entity.CommandBlockBlockEntity;
import net.minecraft.block.entity.SignBlockEntity;
import net.minecraft.command.argument.EntityAnchorArgumentType;
import net.minecraft.entity.Entity;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.effect.StatusEffectInstance;
import net.minecraft.entity.passive.HorseBaseEntity;
import net.minecraft.inventory.Inventory;
import net.minecraft.item.ItemStack;
import net.minecraft.network.ClientConnection;
import net.minecraft.network.MessageType;
import net.minecraft.network.NetworkSide;
import net.minecraft.network.NetworkState;
import net.minecraft.network.Packet;
import net.minecraft.network.packet.c2s.play.RequestCommandCompletionsC2SPacket;
import net.minecraft.network.packet.c2s.play.VehicleMoveC2SPacket;
import net.minecraft.recipe.Recipe;
import net.minecraft.screen.NamedScreenHandlerFactory;
import net.minecraft.screen.ScreenHandler;
import net.minecraft.server.network.ServerPlayNetworkHandler;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.network.ServerPlayerInteractionManager;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvent;
import net.minecraft.text.Text;
import net.minecraft.util.Hand;
import net.minecraft.util.collection.DefaultedList;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.village.TradeOfferList;
import net.minecraft.world.GameMode;
/**
* A wrapper for {@link ServerPlayerEntity} which denotes a "fake" player.
*
* Please note that this does not implement any of the traditional fake player behaviour. It simply exists to prevent me passing in normal players.
*/
public class FakePlayer extends ServerPlayerEntity {
public FakePlayer(ServerWorld world, GameProfile gameProfile) {
super(world.getServer(), world, gameProfile, new ServerPlayerInteractionManager(world));
this.networkHandler = new FakeNetHandler(this);
}
// region Direct networkHandler access
@Override
public void enterCombat() { }
@Override
public void endCombat() { }
@Override
public void tick() { }
@Override
public void playerTick() { }
@Override
public void onDeath(DamageSource damage) { }
@Override
public Entity moveToWorld(ServerWorld destination) {
return this;
}
@Override
public void wakeUp(boolean bl, boolean updateSleepingPlayers) {
}
@Override
public boolean startRiding(Entity entity, boolean flag) {
return false;
}
@Override
public void stopRiding() { }
@Override
public void openEditSignScreen(SignBlockEntity tile) { }
@Override
public OptionalInt openHandledScreen(@Nullable NamedScreenHandlerFactory container) {
return OptionalInt.empty();
}
@Override
public void sendTradeOffers(int id, TradeOfferList list, int level, int experience, boolean levelled, boolean refreshable) { }
@Override
public void openHorseInventory(HorseBaseEntity horse, Inventory inventory) { }
@Override
public void openEditBookScreen(ItemStack stack, Hand hand) { }
@Override
public void openCommandBlockScreen(CommandBlockBlockEntity block) { }
@Override
public void onSlotUpdate(ScreenHandler container, int slot, ItemStack stack) { }
@Override
public void onHandlerRegistered(ScreenHandler container, DefaultedList<ItemStack> defaultedList) { }
@Override
public void onPropertyUpdate(ScreenHandler container, int key, int value) { }
@Override
public void closeHandledScreen() { }
@Override
public void updateCursorStack() { }
@Override
public int unlockRecipes(Collection<Recipe<?>> recipes) {
return 0;
}
// Indirect
@Override
public int lockRecipes(Collection<Recipe<?>> recipes) {
return 0;
}
@Override
public void sendMessage(Text textComponent, boolean status) { }
@Override
protected void consumeItem() { }
@Override
public void lookAt(EntityAnchorArgumentType.EntityAnchor anchor, Vec3d vec3d) {}
@Override
public void method_14222(EntityAnchorArgumentType.EntityAnchor self, Entity entity, EntityAnchorArgumentType.EntityAnchor target) { }
@Override
protected void onStatusEffectApplied(StatusEffectInstance statusEffectInstance) { }
@Override
protected void onStatusEffectUpgraded(StatusEffectInstance statusEffectInstance, boolean particles) { }
@Override
protected void onStatusEffectRemoved(StatusEffectInstance statusEffectInstance) { }
@Override
public void requestTeleport(double x, double y, double z) { }
@Override
public void setGameMode(GameMode gameMode) { }
@Override
public void sendMessage(Text message, MessageType type, UUID senderUuid) {
}
@Override
public String getIp() {
return "[Fake Player]";
}
@Override
public void sendResourcePackUrl(String url, String hash) { }
@Override
public void onStoppedTracking(Entity entity) { }
@Override
public void setCameraEntity(Entity entity) { }
@Override
public void teleport(ServerWorld serverWorld, double x, double y, double z, float pitch, float yaw) { }
@Override
public void sendInitialChunkPackets(ChunkPos chunkPos, Packet<?> packet, Packet<?> packet2) { }
@Override
public void sendUnloadChunkPacket(ChunkPos chunkPos) { }
@Override
public void playSound(SoundEvent soundEvent, SoundCategory soundCategory, float volume, float pitch) { }
private static class FakeNetHandler extends ServerPlayNetworkHandler {
FakeNetHandler(ServerPlayerEntity player) {
super(player.server, new FakeConnection(), player);
}
@Override
public void disconnect(Text message) { }
@Override
public void onVehicleMove(VehicleMoveC2SPacket move) { }
@Override
public void onRequestCommandCompletions(RequestCommandCompletionsC2SPacket packet) { }
@Override
public void sendPacket(Packet<?> packet, @Nullable GenericFutureListener<? extends Future<? super Void>> listener) { }
}
private static class FakeConnection extends ClientConnection {
FakeConnection() {
super(NetworkSide.CLIENTBOUND);
}
@Override
public void channelActive(ChannelHandlerContext active) {
}
@Override
public void setState(NetworkState state) {
}
@Override
public void exceptionCaught(ChannelHandlerContext context, Throwable err) {
}
@Override
protected void channelRead0(ChannelHandlerContext context, Packet<?> packet) {
}
@Override
public void send(Packet<?> packet, @Nullable GenericFutureListener<? extends Future<? super Void>> listener) {
}
@Override
public void tick() {
}
@Override
public void disconnect(Text message) {
}
@Override
public void setupEncryption(Cipher cipher, Cipher cipher2) {
super.setupEncryption(cipher, cipher2);
}
@Override
public void disableAutoRead() {
}
@Override
public void setCompressionThreshold(int size) {
}
}
}

View File

@@ -1,34 +1,33 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.turtle;
import com.mojang.authlib.GameProfile;
import dan200.computercraft.api.lua.ILuaContext;
import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.api.peripheral.IPeripheral;
import net.minecraft.inventory.IInventory;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.items.IItemHandlerModifiable;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import com.mojang.authlib.GameProfile;
import dan200.computercraft.api.lua.ILuaCallback;
import dan200.computercraft.api.lua.MethodResult;
import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.shared.util.ItemStorage;
import net.minecraft.inventory.Inventory;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
/**
* The interface passed to turtle by turtles, providing methods that they can call.
*
* This should not be implemented by your classes. Do not interact with turtles except via this interface and
* {@link ITurtleUpgrade}.
* This should not be implemented by your classes. Do not interact with turtles except via this interface and {@link ITurtleUpgrade}.
*/
public interface ITurtleAccess
{
public interface ITurtleAccess {
/**
* Returns the world in which the turtle resides.
*
@@ -48,28 +47,25 @@ public interface ITurtleAccess
/**
* Attempt to move this turtle to a new position.
*
* This will preserve the turtle's internal state, such as it's inventory, computer and upgrades. It should
* be used before playing a movement animation using {@link #playAnimation(TurtleAnimation)}.
* This will preserve the turtle's internal state, such as it's inventory, computer and upgrades. It should be used before playing a movement animation
* using {@link #playAnimation(TurtleAnimation)}.
*
* @param world The new world to move it to
* @param pos The new position to move it to.
* @return Whether the movement was successful. It may fail if the block was not loaded or the block placement
* was cancelled. Note this will not check
* {@link dan200.computercraft.api.permissions.ITurtlePermissionProvider#isBlockEnterable(World, BlockPos)}.
* @param pos The new position to move it to.
* @return Whether the movement was successful. It may fail if the block was not loaded or the block placement was cancelled.
* @throws UnsupportedOperationException When attempting to teleport on the client side.
*/
boolean teleportTo( @Nonnull World world, @Nonnull BlockPos pos );
boolean teleportTo(@Nonnull World world, @Nonnull BlockPos pos);
/**
* Returns a vector containing the floating point co-ordinates at which the turtle is rendered.
* This will shift when the turtle is moving.
* Returns a vector containing the floating point co-ordinates at which the turtle is rendered. This will shift when the turtle is moving.
*
* @param f The subframe fraction.
* @return A vector containing the floating point co-ordinates at which the turtle resides.
* @see #getVisualYaw(float)
*/
@Nonnull
Vec3d getVisualPosition( float f );
Vec3d getVisualPosition(float f);
/**
* Returns the yaw the turtle is facing when it is rendered.
@@ -78,25 +74,25 @@ public interface ITurtleAccess
* @return The yaw the turtle is facing.
* @see #getVisualPosition(float)
*/
float getVisualYaw( float f );
float getVisualYaw(float f);
/**
* Returns the world direction the turtle is currently facing.
*
* @return The world direction the turtle is currently facing.
* @see #setDirection(EnumFacing)
* @see #setDirection(Direction)
*/
@Nonnull
EnumFacing getDirection();
Direction getDirection();
/**
* Set the direction the turtle is facing. Note that this will not play a rotation animation, you will also need to
* call {@link #playAnimation(TurtleAnimation)} to do so.
* Set the direction the turtle is facing. Note that this will not play a rotation animation, you will also need to call {@link
* #playAnimation(TurtleAnimation)} to do so.
*
* @param dir The new direction to set. This should be on either the x or z axis (so north, south, east or west).
* @see #getDirection()
*/
void setDirection( @Nonnull EnumFacing dir );
void setDirection(@Nonnull Direction dir);
/**
* Get the currently selected slot in the turtle's inventory.
@@ -110,60 +106,38 @@ public interface ITurtleAccess
/**
* Set the currently selected slot in the turtle's inventory.
*
* @param slot The slot to set. This must be greater or equal to 0 and less than the inventory size. Otherwise no
* action will be taken.
* @param slot The slot to set. This must be greater or equal to 0 and less than the inventory size. Otherwise no action will be taken.
* @throws UnsupportedOperationException When attempting to change the slot on the client side.
* @see #getInventory()
* @see #getSelectedSlot()
*/
void setSelectedSlot( int slot );
/**
* Set the colour of the turtle to a RGB number.
*
* @param colour The colour this turtle should be changed to. This should be a RGB colour between {@code 0x000000}
* and {@code 0xFFFFFF} or -1 to reset to the default colour.
* @see #getColour()
*/
void setColour( int colour );
void setSelectedSlot(int slot);
/**
* Get the colour of this turtle as a RGB number.
*
* @return The colour this turtle is. This will be a RGB colour between {@code 0x000000} and {@code 0xFFFFFF} or
* -1 if it has no colour.
* @return The colour this turtle is. This will be a RGB colour between {@code 0x000000} and {@code 0xFFFFFF} or -1 if it has no colour.
* @see #setColour(int)
*/
int getColour();
/**
* Set the colour of the turtle to a RGB number.
*
* @param colour The colour this turtle should be changed to. This should be a RGB colour between {@code 0x000000} and {@code 0xFFFFFF} or -1 to
* reset to the default colour.
* @see #getColour()
*/
void setColour(int colour);
/**
* Get the player who owns this turtle, namely whoever placed it.
*
* @return This turtle's owner.
*/
@Nonnull
@Nullable
GameProfile getOwningPlayer();
/**
* Get the inventory of this turtle
*
* @return This turtle's inventory
* @see #getItemHandler()
*/
@Nonnull
IInventory getInventory();
/**
* Get the inventory of this turtle as an {@link IItemHandlerModifiable}.
*
* @return This turtle's inventory
* @see #getInventory()
* @see IItemHandlerModifiable
* @see net.minecraftforge.items.CapabilityItemHandler#ITEM_HANDLER_CAPABILITY
*/
@Nonnull
IItemHandlerModifiable getItemHandler();
/**
* Determine whether this turtle will require fuel when performing actions.
*
@@ -183,8 +157,7 @@ public interface ITurtleAccess
int getFuelLevel();
/**
* Set the fuel level to a new value. It is generally preferred to use {@link #consumeFuel(int)}} or {@link #addFuel(int)}
* instead.
* Set the fuel level to a new value. It is generally preferred to use {@link #consumeFuel(int)}} or {@link #addFuel(int)} instead.
*
* @param fuel The new amount of fuel. This must be between 0 and the fuel limit.
* @see #getFuelLevel()
@@ -192,7 +165,7 @@ public interface ITurtleAccess
* @see #addFuel(int)
* @see #consumeFuel(int)
*/
void setFuelLevel( int fuel );
void setFuelLevel(int fuel);
/**
* Get the maximum amount of fuel a turtle can hold.
@@ -205,11 +178,11 @@ public interface ITurtleAccess
* Removes some fuel from the turtles fuel supply. Negative numbers can be passed in to INCREASE the fuel level of the turtle.
*
* @param fuel The amount of fuel to consume.
* @return Whether the turtle was able to consume the amount of fuel specified. Will return false if you supply a number
* greater than the current fuel level of the turtle. No fuel will be consumed if {@code false} is returned.
* @return Whether the turtle was able to consume the amount of fuel specified. Will return false if you supply a number greater than the current fuel
* level of the turtle. No fuel will be consumed if {@code false} is returned.
* @throws UnsupportedOperationException When attempting to consume fuel on the client side.
*/
boolean consumeFuel( int fuel );
boolean consumeFuel(int fuel);
/**
* Increase the turtle's fuel level by the given amount.
@@ -217,40 +190,31 @@ public interface ITurtleAccess
* @param fuel The amount to refuel with.
* @throws UnsupportedOperationException When attempting to refuel on the client side.
*/
void addFuel( int fuel );
void addFuel(int fuel);
/**
* Adds a custom command to the turtles command queue. Unlike peripheral methods, these custom commands will be executed
* on the main thread, so are guaranteed to be able to access Minecraft objects safely, and will be queued up
* with the turtles standard movement and tool commands. An issued command will return an unique integer, which will
* be supplied as a parameter to a "turtle_response" event issued to the turtle after the command has completed. Look at the
* lua source code for "rom/apis/turtle" for how to build a lua wrapper around this functionality.
* Adds a custom command to the turtles command queue. Unlike peripheral methods, these custom commands will be executed on the main thread, so are
* guaranteed to be able to access Minecraft objects safely, and will be queued up with the turtles standard movement and tool commands. An issued
* command will return an unique integer, which will be supplied as a parameter to a "turtle_response" event issued to the turtle after the command has
* completed. Look at the lua source code for "rom/apis/turtle" for how to build a lua wrapper around this functionality.
*
* @param context The Lua context to pull events from.
* @param command An object which will execute the custom command when its point in the queue is reached
* @return The objects the command returned when executed. you should probably return these to the player
* unchanged if called from a peripheral method.
* @return The objects the command returned when executed. you should probably return these to the player unchanged if called from a peripheral method.
* @throws UnsupportedOperationException When attempting to execute a command on the client side.
* @throws LuaException If the user presses CTRL+T to terminate the current program while {@code executeCommand()} is
* waiting for an event, a "Terminated" exception will be thrown here.
* @throws InterruptedException If the user shuts down or reboots the computer while pullEvent() is waiting for an
* event, InterruptedException will be thrown. This exception must not be caught or
* intercepted, or the computer will leak memory and end up in a broken state.
* @see ITurtleCommand
* @see ILuaContext#pullEvent(String)
* @see MethodResult#pullEvent(String, ILuaCallback)
*/
@Nonnull
Object[] executeCommand( @Nonnull ILuaContext context, @Nonnull ITurtleCommand command ) throws LuaException, InterruptedException;
MethodResult executeCommand(@Nonnull ITurtleCommand command);
/**
* Start playing a specific animation. This will prevent other turtle commands from executing until
* it is finished.
* Start playing a specific animation. This will prevent other turtle commands from executing until it is finished.
*
* @param animation The animation to play.
* @throws UnsupportedOperationException When attempting to execute play an animation on the client side.
* @see TurtleAnimation
*/
void playAnimation( @Nonnull TurtleAnimation animation );
void playAnimation(@Nonnull TurtleAnimation animation);
/**
* Returns the turtle on the specified side of the turtle, if there is one.
@@ -260,16 +224,16 @@ public interface ITurtleAccess
* @see #setUpgrade(TurtleSide, ITurtleUpgrade)
*/
@Nullable
ITurtleUpgrade getUpgrade( @Nonnull TurtleSide side );
ITurtleUpgrade getUpgrade(@Nonnull TurtleSide side);
/**
* Set the upgrade for a given side, resetting peripherals and clearing upgrade specific data.
*
* @param side The side to set the upgrade on.
* @param side The side to set the upgrade on.
* @param upgrade The upgrade to set, may be {@code null} to clear.
* @see #getUpgrade(TurtleSide)
*/
void setUpgrade( @Nonnull TurtleSide side, @Nullable ITurtleUpgrade upgrade );
void setUpgrade(@Nonnull TurtleSide side, @Nullable ITurtleUpgrade upgrade);
/**
* Returns the peripheral created by the upgrade on the specified side of the turtle, if there is one.
@@ -278,27 +242,40 @@ public interface ITurtleAccess
* @return The peripheral created by the upgrade on the specified side of the turtle, {@code null} if none exists.
*/
@Nullable
IPeripheral getPeripheral( @Nonnull TurtleSide side );
IPeripheral getPeripheral(@Nonnull TurtleSide side);
/**
* Get an upgrade-specific NBT compound, which can be used to store arbitrary data.
*
* This will be persisted across turtle restarts and chunk loads, as well as being synced to the client. You must
* call {@link #updateUpgradeNBTData(TurtleSide)} after modifying it.
* This will be persisted across turtle restarts and chunk loads, as well as being synced to the client. You must call {@link
* #updateUpgradeNBTData(TurtleSide)} after modifying it.
*
* @param side The side to get the upgrade data for.
* @return The upgrade-specific data.
* @see #updateUpgradeNBTData(TurtleSide)
*/
@Nonnull
NBTTagCompound getUpgradeNBTData( @Nullable TurtleSide side );
CompoundTag getUpgradeNBTData(@Nullable TurtleSide side);
/**
* Mark the upgrade-specific data as dirty on a specific side. This is required for the data to be synced to the
* client and persisted.
* Mark the upgrade-specific data as dirty on a specific side. This is required for the data to be synced to the client and persisted.
*
* @param side The side to mark dirty.
* @see #updateUpgradeNBTData(TurtleSide)
*/
void updateUpgradeNBTData( @Nonnull TurtleSide side );
void updateUpgradeNBTData(@Nonnull TurtleSide side);
default ItemStorage getItemHandler() {
return ItemStorage.wrap(this.getInventory());
}
/**
* Get the inventory of this turtle.
*
* Note: this inventory should only be accessed and modified on the server thread.
*
* @return This turtle's inventory
*/
@Nonnull
Inventory getInventory();
}

View File

@@ -1,36 +1,33 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.turtle;
import dan200.computercraft.api.lua.ILuaContext;
import javax.annotation.Nonnull;
/**
* An interface for objects executing custom turtle commands, used with {@link ITurtleAccess#executeCommand(ILuaContext, ITurtleCommand)}.
* An interface for objects executing custom turtle commands, used with {@link ITurtleAccess#executeCommand(ITurtleCommand)}.
*
* @see ITurtleAccess#executeCommand(ILuaContext, ITurtleCommand)
* @see ITurtleAccess#executeCommand(ITurtleCommand)
*/
@FunctionalInterface
public interface ITurtleCommand
{
public interface ITurtleCommand {
/**
* Will be called by the turtle on the main thread when it is time to execute the custom command.
*
* The handler should either perform the work of the command, and return success, or return
* failure with an error message to indicate the command cannot be executed at this time.
* The handler should either perform the work of the command, and return success, or return failure with an error message to indicate the command cannot
* be executed at this time.
*
* @param turtle Access to the turtle for whom the command was issued.
* @return A result, indicating whether this action succeeded or not.
* @see ITurtleAccess#executeCommand(ILuaContext, ITurtleCommand)
* @see ITurtleAccess#executeCommand(ITurtleCommand)
* @see TurtleCommandResult#success()
* @see TurtleCommandResult#failure(String)
* @see TurtleCommandResult
*/
@Nonnull
TurtleCommandResult execute( @Nonnull ITurtleAccess turtle );
TurtleCommandResult execute(@Nonnull ITurtleAccess turtle);
}

View File

@@ -1,70 +1,31 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.turtle;
import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.api.turtle.event.TurtleAttackEvent;
import dan200.computercraft.api.turtle.event.TurtleBlockEvent;
import net.minecraft.client.renderer.block.model.IBakedModel;
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.event.entity.player.AttackEntityEvent;
import net.minecraftforge.event.world.BlockEvent;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import org.apache.commons.lang3.tuple.Pair;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.vecmath.Matrix4f;
import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.IUpgradeBase;
import dan200.computercraft.api.client.TransformedModel;
import dan200.computercraft.api.peripheral.IPeripheral;
import net.minecraft.util.math.Direction;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
/**
* The primary interface for defining an update for Turtles. A turtle update
* can either be a new tool, or a new peripheral.
* The primary interface for defining an update for Turtles. A turtle update can either be a new tool, or a new peripheral.
*
* @see ComputerCraftAPI#registerTurtleUpgrade(ITurtleUpgrade)
*/
public interface ITurtleUpgrade
public interface ITurtleUpgrade extends IUpgradeBase
{
/**
* Gets a unique identifier representing this type of turtle upgrade. eg: "computercraft:wireless_modem" or "my_mod:my_upgrade".
* You should use a unique resource domain to ensure this upgrade is uniquely identified.
* The turtle will fail registration if an already used ID is specified.
*
* @return The unique ID for this upgrade.
* @see ComputerCraftAPI#registerTurtleUpgrade(ITurtleUpgrade)
*/
@Nonnull
ResourceLocation getUpgradeID();
/**
* Gets a numerical identifier representing this type of turtle upgrade,
* for backwards compatibility with pre-1.76 worlds. If your upgrade was
* not released for older ComputerCraft versions, you can return -1 here.
* The turtle will fail registration if an already used positive ID is specified.
*
* @return The legacy ID, or -1 if is needed.
* @see ComputerCraftAPI#registerTurtleUpgrade(ITurtleUpgrade)
*/
int getLegacyUpgradeID();
/**
* Return an unlocalised string to describe this type of turtle in turtle item names.
*
* Examples of built-in adjectives are "Wireless", "Mining" and "Crafty".
*
* @return The localisation key for this upgrade's adjective.
*/
@Nonnull
String getUnlocalisedAdjective();
/**
* Return whether this turtle adds a tool or a peripheral to the turtle.
*
@@ -74,81 +35,55 @@ public interface ITurtleUpgrade
@Nonnull
TurtleUpgradeType getType();
/**
* Return an item stack representing the type of item that a turtle must be crafted
* with to create a turtle which holds this upgrade. This item stack is also used
* to determine the upgrade given by {@code turtle.equip()}
*
* @return The item stack to craft with, or {@link ItemStack#EMPTY} if it cannot be crafted.
*/
@Nonnull
ItemStack getCraftingItem();
/**
* Will only be called for peripheral upgrades. Creates a peripheral for a turtle being placed using this upgrade.
*
* The peripheral created will be stored for the lifetime of the upgrade and will be passed as an argument to
* {@link #update(ITurtleAccess, TurtleSide)}. It will be attached, detached and have methods called in the same
* manner as a Computer peripheral.
* The peripheral created will be stored for the lifetime of the upgrade and will be passed as an argument to {@link #update(ITurtleAccess,
* TurtleSide)}. It will be attached, detached and have methods called in the same manner as a Computer peripheral.
*
* @param turtle Access to the turtle that the peripheral is being created for.
* @param side Which side of the turtle (left or right) that the upgrade resides on.
* @return The newly created peripheral. You may return {@code null} if this upgrade is a Tool
* and this method is not expected to be called.
* @param side Which side of the turtle (left or right) that the upgrade resides on.
* @return The newly created peripheral. You may return {@code null} if this upgrade is a Tool and this method is not expected to be called.
*/
@Nullable
default IPeripheral createPeripheral( @Nonnull ITurtleAccess turtle, @Nonnull TurtleSide side )
{
default IPeripheral createPeripheral(@Nonnull ITurtleAccess turtle, @Nonnull TurtleSide side) {
return null;
}
/**
* Will only be called for Tool turtle. Called when turtle.dig() or turtle.attack() is called
* by the turtle, and the tool is required to do some work.
* Will only be called for Tool turtle. Called when turtle.dig() or turtle.attack() is called by the turtle, and the tool is required to do some work.
*
* Conforming implementations should fire {@link BlockEvent.BreakEvent} and {@link TurtleBlockEvent.Dig}for digging,
* {@link AttackEntityEvent} and {@link TurtleAttackEvent} for attacking.
*
* @param turtle Access to the turtle that the tool resides on.
* @param side Which side of the turtle (left or right) the tool resides on.
* @param verb Which action (dig or attack) the turtle is being called on to perform.
* @param direction Which world direction the action should be performed in, relative to the turtles
* position. This will either be up, down, or the direction the turtle is facing, depending on
* whether dig, digUp or digDown was called.
* @return Whether the turtle was able to perform the action, and hence whether the {@code turtle.dig()}
* or {@code turtle.attack()} lua method should return true. If true is returned, the tool will perform
* a swinging animation. You may return {@code null} if this turtle is a Peripheral and this method is not expected
* to be called.
* @param turtle Access to the turtle that the tool resides on.
* @param side Which side of the turtle (left or right) the tool resides on.
* @param verb Which action (dig or attack) the turtle is being called on to perform.
* @param direction Which world direction the action should be performed in, relative to the turtles position. This will either be up, down, or the
* direction the turtle is facing, depending on whether dig, digUp or digDown was called.
* @return Whether the turtle was able to perform the action, and hence whether the {@code turtle.dig()} or {@code turtle.attack()} lua method should
* return true. If true is returned, the tool will perform a swinging animation. You may return {@code null} if this turtle is a Peripheral and
* this method is not expected to be called.
*/
@Nonnull
default TurtleCommandResult useTool( @Nonnull ITurtleAccess turtle, @Nonnull TurtleSide side, @Nonnull TurtleVerb verb, @Nonnull EnumFacing direction )
{
default TurtleCommandResult useTool(@Nonnull ITurtleAccess turtle, @Nonnull TurtleSide side, @Nonnull TurtleVerb verb, @Nonnull Direction direction) {
return TurtleCommandResult.failure();
}
/**
* Called to obtain the model to be used when rendering a turtle peripheral.
*
* This can be obtained from {@link net.minecraft.client.renderer.ItemModelMesher#getItemModel(ItemStack)},
* {@link net.minecraft.client.renderer.block.model.ModelManager#getModel(ModelResourceLocation)} or any other
* source.
*
* @param turtle Access to the turtle that the upgrade resides on. This will be null when getting item models!
* @param side Which side of the turtle (left or right) the upgrade resides on.
* @return The model that you wish to be used to render your upgrade, and a transformation to apply to it. Returning
* a transformation of {@code null} has the same effect as the identify matrix.
* @param side Which side of the turtle (left or right) the upgrade resides on.
* @return The model that you wish to be used to render your upgrade.
*/
@Nonnull
@SideOnly( Side.CLIENT )
Pair<IBakedModel, Matrix4f> getModel( @Nullable ITurtleAccess turtle, @Nonnull TurtleSide side );
@Environment (EnvType.CLIENT)
TransformedModel getModel(@Nullable ITurtleAccess turtle, @Nonnull TurtleSide side);
/**
* Called once per tick for each turtle which has the upgrade equipped.
*
* @param turtle Access to the turtle that the upgrade resides on.
* @param side Which side of the turtle (left or right) the upgrade resides on.
* @param side Which side of the turtle (left or right) the upgrade resides on.
*/
default void update( @Nonnull ITurtleAccess turtle, @Nonnull TurtleSide side )
{
default void update(@Nonnull ITurtleAccess turtle, @Nonnull TurtleSide side) {
}
}

View File

@@ -1,6 +1,6 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
@@ -13,75 +13,70 @@ package dan200.computercraft.api.turtle;
*
* @see ITurtleAccess#playAnimation(TurtleAnimation)
*/
public enum TurtleAnimation
{
public enum TurtleAnimation {
/**
* An animation which does nothing. This takes no time to complete.
*
* @see #Wait
* @see #ShortWait
* @see #WAIT
* @see #SHORT_WAIT
*/
None,
NONE,
/**
* Make the turtle move forward. Note that the animation starts from the block <em>behind</em> it, and
* moves into this one.
* Make the turtle move forward. Note that the animation starts from the block <em>behind</em> it, and moves into this one.
*/
MoveForward,
MOVE_FORWARD,
/**
* Make the turtle move backwards. Note that the animation starts from the block <em>in front</em> it, and
* moves into this one.
* Make the turtle move backwards. Note that the animation starts from the block <em>in front</em> it, and moves into this one.
*/
MoveBack,
MOVE_BACK,
/**
* Make the turtle move backwards. Note that the animation starts from the block <em>above</em> it, and
* moves into this one.
* Make the turtle move backwards. Note that the animation starts from the block <em>above</em> it, and moves into this one.
*/
MoveUp,
MOVE_UP,
/**
* Make the turtle move backwards. Note that the animation starts from the block <em>below</em> it, and
* moves into this one.
* Make the turtle move backwards. Note that the animation starts from the block <em>below</em> it, and moves into this one.
*/
MoveDown,
MOVE_DOWN,
/**
* Turn the turtle to the left. Note that the animation starts with the turtle facing <em>right</em>, and
* the turtle turns to face in the current direction.
* Turn the turtle to the left. Note that the animation starts with the turtle facing <em>right</em>, and the turtle turns to face in the current
* direction.
*/
TurnLeft,
TURN_LEFT,
/**
* Turn the turtle to the left. Note that the animation starts with the turtle facing <em>right</em>, and
* the turtle turns to face in the current direction.
* Turn the turtle to the left. Note that the animation starts with the turtle facing <em>right</em>, and the turtle turns to face in the current
* direction.
*/
TurnRight,
TURN_RIGHT,
/**
* Swing the tool on the left.
*/
SwingLeftTool,
SWING_LEFT_TOOL,
/**
* Swing the tool on the right.
*/
SwingRightTool,
SWING_RIGHT_TOOL,
/**
* Wait until the animation has finished, performing no movement.
*
* @see #ShortWait
* @see #None
* @see #SHORT_WAIT
* @see #NONE
*/
Wait,
WAIT,
/**
* Wait until the animation has finished, performing no movement. This takes 4 ticks to complete.
*
* @see #Wait
* @see #None
* @see #WAIT
* @see #NONE
*/
ShortWait,
SHORT_WAIT,
}

View File

@@ -1,13 +1,11 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.turtle;
import net.minecraft.util.EnumFacing;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -15,12 +13,20 @@ import javax.annotation.Nullable;
* Used to indicate the result of executing a turtle command.
*
* @see ITurtleCommand#execute(ITurtleAccess)
* @see ITurtleUpgrade#useTool(ITurtleAccess, TurtleSide, TurtleVerb, EnumFacing)
* @see ITurtleUpgrade#useTool(ITurtleAccess, TurtleSide, TurtleVerb, Direction)
*/
public final class TurtleCommandResult
{
private static final TurtleCommandResult EMPTY_SUCCESS = new TurtleCommandResult( true, null, null );
private static final TurtleCommandResult EMPTY_FAILURE = new TurtleCommandResult( false, null, null );
public final class TurtleCommandResult {
private static final TurtleCommandResult EMPTY_SUCCESS = new TurtleCommandResult(true, null, null);
private static final TurtleCommandResult EMPTY_FAILURE = new TurtleCommandResult(false, null, null);
private final boolean success;
private final String errorMessage;
private final Object[] results;
private TurtleCommandResult(boolean success, String errorMessage, Object[] results) {
this.success = success;
this.errorMessage = errorMessage;
this.results = results;
}
/**
* Create a successful command result with no result.
@@ -28,8 +34,7 @@ public final class TurtleCommandResult
* @return A successful command result with no values.
*/
@Nonnull
public static TurtleCommandResult success()
{
public static TurtleCommandResult success() {
return EMPTY_SUCCESS;
}
@@ -40,10 +45,11 @@ public final class TurtleCommandResult
* @return A successful command result with the given values.
*/
@Nonnull
public static TurtleCommandResult success( @Nullable Object[] results )
{
if( results == null || results.length == 0 ) return EMPTY_SUCCESS;
return new TurtleCommandResult( true, null, results );
public static TurtleCommandResult success(@Nullable Object[] results) {
if (results == null || results.length == 0) {
return EMPTY_SUCCESS;
}
return new TurtleCommandResult(true, null, results);
}
/**
@@ -52,8 +58,7 @@ public final class TurtleCommandResult
* @return A failed command result with no message.
*/
@Nonnull
public static TurtleCommandResult failure()
{
public static TurtleCommandResult failure() {
return EMPTY_FAILURE;
}
@@ -64,21 +69,11 @@ public final class TurtleCommandResult
* @return A failed command result with a message.
*/
@Nonnull
public static TurtleCommandResult failure( @Nullable String errorMessage )
{
if( errorMessage == null ) return EMPTY_FAILURE;
return new TurtleCommandResult( false, errorMessage, null );
}
private final boolean success;
private final String errorMessage;
private final Object[] results;
private TurtleCommandResult( boolean success, String errorMessage, Object[] results )
{
this.success = success;
this.errorMessage = errorMessage;
this.results = results;
public static TurtleCommandResult failure(@Nullable String errorMessage) {
if (errorMessage == null) {
return EMPTY_FAILURE;
}
return new TurtleCommandResult(false, errorMessage, null);
}
/**
@@ -86,9 +81,8 @@ public final class TurtleCommandResult
*
* @return If the command was successful.
*/
public boolean isSuccess()
{
return success;
public boolean isSuccess() {
return this.success;
}
/**
@@ -97,9 +91,8 @@ public final class TurtleCommandResult
* @return The command's error message, or {@code null} if it was a success.
*/
@Nullable
public String getErrorMessage()
{
return errorMessage;
public String getErrorMessage() {
return this.errorMessage;
}
/**
@@ -108,8 +101,7 @@ public final class TurtleCommandResult
* @return The command's result, or {@code null} if it was a failure.
*/
@Nullable
public Object[] getResults()
{
return results;
public Object[] getResults() {
return this.results;
}
}

View File

@@ -1,6 +1,6 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
@@ -9,15 +9,14 @@ package dan200.computercraft.api.turtle;
/**
* An enum representing the two sides of the turtle that a turtle turtle might reside.
*/
public enum TurtleSide
{
public enum TurtleSide {
/**
* The turtle's left side (where the pickaxe usually is on a Wireless Mining Turtle)
* The turtle's left side (where the pickaxe usually is on a Wireless Mining Turtle).
*/
Left,
LEFT,
/**
* The turtle's right side (where the modem usually is on a Wireless Mining Turtle)
* The turtle's right side (where the modem usually is on a Wireless Mining Turtle).
*/
Right,
RIGHT,
}

View File

@@ -1,6 +1,6 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
@@ -11,34 +11,30 @@ package dan200.computercraft.api.turtle;
*
* @see ITurtleUpgrade#getType()
*/
public enum TurtleUpgradeType
{
public enum TurtleUpgradeType {
/**
* A tool is rendered as an item on the side of the turtle, and responds to the {@code turtle.dig()}
* and {@code turtle.attack()} methods (Such as pickaxe or sword on Mining and Melee turtles).
* A tool is rendered as an item on the side of the turtle, and responds to the {@code turtle.dig()} and {@code turtle.attack()} methods (Such as
* pickaxe or sword on Mining and Melee turtles).
*/
Tool,
TOOL,
/**
* A peripheral adds a special peripheral which is attached to the side of the turtle,
* and can be interacted with the {@code peripheral} API (Such as the modem on Wireless Turtles).
* A peripheral adds a special peripheral which is attached to the side of the turtle, and can be interacted with the {@code peripheral} API (Such as
* the modem on Wireless Turtles).
*/
Peripheral,
PERIPHERAL,
/**
* An upgrade which provides both a tool and a peripheral. This can be used when you wish
* your upgrade to also provide methods. For example, a pickaxe could provide methods
* determining whether it can break the given block or not.
* An upgrade which provides both a tool and a peripheral. This can be used when you wish your upgrade to also provide methods. For example, a pickaxe
* could provide methods determining whether it can break the given block or not.
*/
Both;
BOTH;
public boolean isTool()
{
return this == Tool || this == Both;
public boolean isTool() {
return this == TOOL || this == BOTH;
}
public boolean isPeripheral()
{
return this == Peripheral || this == Both;
public boolean isPeripheral() {
return this == PERIPHERAL || this == BOTH;
}
}

View File

@@ -1,29 +1,25 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.turtle;
import net.minecraft.util.EnumFacing;
/**
* An enum representing the different actions that an {@link ITurtleUpgrade} of type Tool may be called on to perform by
* a turtle.
* An enum representing the different actions that an {@link ITurtleUpgrade} of type Tool may be called on to perform by a turtle.
*
* @see ITurtleUpgrade#getType()
* @see ITurtleUpgrade#useTool(ITurtleAccess, TurtleSide, TurtleVerb, EnumFacing)
* @see ITurtleUpgrade#useTool(ITurtleAccess, TurtleSide, TurtleVerb, Direction)
*/
public enum TurtleVerb
{
public enum TurtleVerb {
/**
* The turtle called {@code turtle.dig()}, {@code turtle.digUp()} or {@code turtle.digDown()}
* The turtle called {@code turtle.dig()}, {@code turtle.digUp()} or {@code turtle.digDown()}.
*/
Dig,
DIG,
/**
* The turtle called {@code turtle.attack()}, {@code turtle.attackUp()} or {@code turtle.attackDown()}
* The turtle called {@code turtle.attack()}, {@code turtle.attackUp()} or {@code turtle.attackDown()}.
*/
Attack,
ATTACK,
}

View File

@@ -1,6 +1,6 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
@@ -11,8 +11,7 @@ package dan200.computercraft.api.turtle.event;
*
* @see TurtleActionEvent
*/
public enum TurtleAction
{
public enum TurtleAction {
/**
* A turtle moves to a new position.
*
@@ -71,7 +70,7 @@ public enum TurtleAction
EQUIP,
/**
* Inspect a block in world
* Inspect a block in world.
*
* @see TurtleBlockEvent.Inspect
*/

View File

@@ -1,39 +1,36 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.turtle.event;
import dan200.computercraft.api.turtle.ITurtleAccess;
import dan200.computercraft.api.turtle.TurtleCommandResult;
import net.minecraftforge.fml.common.eventhandler.Cancelable;
import java.util.Objects;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Objects;
import dan200.computercraft.api.turtle.ITurtleAccess;
import dan200.computercraft.api.turtle.TurtleCommandResult;
/**
* An event fired when a turtle is performing a known action.
*/
@Cancelable
public class TurtleActionEvent extends TurtleEvent
{
public class TurtleActionEvent extends TurtleEvent {
private final TurtleAction action;
private String failureMessage;
private boolean cancelled = false;
public TurtleActionEvent( @Nonnull ITurtleAccess turtle, @Nonnull TurtleAction action )
{
super( turtle );
public TurtleActionEvent(@Nonnull ITurtleAccess turtle, @Nonnull TurtleAction action) {
super(turtle);
Objects.requireNonNull( action, "action cannot be null" );
Objects.requireNonNull(action, "action cannot be null");
this.action = action;
}
public TurtleAction getAction()
{
return action;
public TurtleAction getAction() {
return this.action;
}
/**
@@ -45,11 +42,9 @@ public class TurtleActionEvent extends TurtleEvent
* @see TurtleCommandResult#failure()
* @deprecated Use {@link #setCanceled(boolean, String)} instead.
*/
@Override
@Deprecated
public void setCanceled( boolean cancel )
{
setCanceled( cancel, null );
public void setCanceled(boolean cancel) {
this.setCanceled(cancel, null);
}
/**
@@ -57,13 +52,12 @@ public class TurtleActionEvent extends TurtleEvent
*
* If {@code cancel} is {@code true}, this action will not be carried out.
*
* @param cancel The new canceled value.
* @param cancel The new canceled value.
* @param failureMessage The message to return to the user explaining the failure.
* @see TurtleCommandResult#failure(String)
*/
public void setCanceled( boolean cancel, @Nullable String failureMessage )
{
super.setCanceled( cancel );
public void setCanceled(boolean cancel, @Nullable String failureMessage) {
this.cancelled = true;
this.failureMessage = cancel ? failureMessage : null;
}
@@ -75,8 +69,11 @@ public class TurtleActionEvent extends TurtleEvent
* @see #setCanceled(boolean, String)
*/
@Nullable
public String getFailureMessage()
{
return failureMessage;
public String getFailureMessage() {
return this.failureMessage;
}
public boolean isCancelled() {
return this.cancelled;
}
}

View File

@@ -1,45 +1,38 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.turtle.event;
import java.util.Objects;
import javax.annotation.Nonnull;
import dan200.computercraft.api.turtle.FakePlayer;
import dan200.computercraft.api.turtle.ITurtleAccess;
import dan200.computercraft.api.turtle.ITurtleUpgrade;
import dan200.computercraft.api.turtle.TurtleSide;
import dan200.computercraft.api.turtle.TurtleVerb;
import net.minecraft.entity.Entity;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.common.util.FakePlayer;
import net.minecraftforge.event.entity.player.AttackEntityEvent;
import javax.annotation.Nonnull;
import java.util.Objects;
import net.minecraft.entity.Entity;
/**
* Fired when a turtle attempts to attack an entity.
*
* This must be fired by {@link ITurtleUpgrade#useTool(ITurtleAccess, TurtleSide, TurtleVerb, EnumFacing)},
* as the base {@code turtle.attack()} command does not fire it.
*
* Note that such commands should also fire {@link AttackEntityEvent}, so you do not need to listen to both.
*
* @see TurtleAction#ATTACK
*/
public class TurtleAttackEvent extends TurtlePlayerEvent
{
public class TurtleAttackEvent extends TurtlePlayerEvent {
private final Entity target;
private final ITurtleUpgrade upgrade;
private final TurtleSide side;
public TurtleAttackEvent( @Nonnull ITurtleAccess turtle, @Nonnull FakePlayer player, @Nonnull Entity target, @Nonnull ITurtleUpgrade upgrade, @Nonnull TurtleSide side )
{
super( turtle, TurtleAction.ATTACK, player );
Objects.requireNonNull( target, "target cannot be null" );
Objects.requireNonNull( upgrade, "upgrade cannot be null" );
Objects.requireNonNull( side, "side cannot be null" );
public TurtleAttackEvent(@Nonnull ITurtleAccess turtle, @Nonnull FakePlayer player, @Nonnull Entity target, @Nonnull ITurtleUpgrade upgrade,
@Nonnull TurtleSide side) {
super(turtle, TurtleAction.ATTACK, player);
Objects.requireNonNull(target, "target cannot be null");
Objects.requireNonNull(upgrade, "upgrade cannot be null");
Objects.requireNonNull(side, "side cannot be null");
this.target = target;
this.upgrade = upgrade;
this.side = side;
@@ -51,9 +44,8 @@ public class TurtleAttackEvent extends TurtlePlayerEvent
* @return The entity being attacked.
*/
@Nonnull
public Entity getTarget()
{
return target;
public Entity getTarget() {
return this.target;
}
/**
@@ -62,9 +54,8 @@ public class TurtleAttackEvent extends TurtlePlayerEvent
* @return The upgrade responsible for attacking.
*/
@Nonnull
public ITurtleUpgrade getUpgrade()
{
return upgrade;
public ITurtleUpgrade getUpgrade() {
return this.upgrade;
}
/**
@@ -73,8 +64,7 @@ public class TurtleAttackEvent extends TurtlePlayerEvent
* @return The upgrade's side.
*/
@Nonnull
public TurtleSide getSide()
{
return side;
public TurtleSide getSide() {
return this.side;
}
}

View File

@@ -1,54 +1,46 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.turtle.event;
import dan200.computercraft.api.lua.ILuaContext;
import dan200.computercraft.api.peripheral.IComputerAccess;
import java.util.Map;
import java.util.Objects;
import javax.annotation.Nonnull;
import dan200.computercraft.api.lua.MethodResult;
import dan200.computercraft.api.turtle.FakePlayer;
import dan200.computercraft.api.turtle.ITurtleAccess;
import dan200.computercraft.api.turtle.ITurtleUpgrade;
import dan200.computercraft.api.turtle.TurtleSide;
import dan200.computercraft.api.turtle.TurtleVerb;
import net.minecraft.block.state.IBlockState;
import net.minecraft.block.BlockState;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.common.util.FakePlayer;
import net.minecraftforge.event.world.BlockEvent;
import net.minecraftforge.fml.common.eventhandler.Cancelable;
import javax.annotation.Nonnull;
import java.util.Map;
import java.util.Objects;
/**
* A general event for when a turtle interacts with a block or region.
*
* You should generally listen to one of the sub-events instead, cancelling them where
* appropriate.
* You should generally listen to one of the sub-events instead, cancelling them where appropriate.
*
* Note that you are not guaranteed to receive this event, if it has been cancelled by other
* mechanisms, such as block protection systems.
* Note that you are not guaranteed to receive this event, if it has been cancelled by other mechanisms, such as block protection systems.
*
* Be aware that some events (such as {@link TurtleInventoryEvent}) do not necessarily interact
* with a block, simply objects within that block space.
* Be aware that some events (such as {@link TurtleInventoryEvent}) do not necessarily interact with a block, simply objects within that block space.
*/
@Cancelable
public abstract class TurtleBlockEvent extends TurtlePlayerEvent
{
public abstract class TurtleBlockEvent extends TurtlePlayerEvent {
private final World world;
private final BlockPos pos;
protected TurtleBlockEvent( @Nonnull ITurtleAccess turtle, @Nonnull TurtleAction action, @Nonnull FakePlayer player, @Nonnull World world, @Nonnull BlockPos pos )
{
super( turtle, action, player );
protected TurtleBlockEvent(@Nonnull ITurtleAccess turtle, @Nonnull TurtleAction action, @Nonnull FakePlayer player, @Nonnull World world,
@Nonnull BlockPos pos) {
super(turtle, action, player);
Objects.requireNonNull( world, "world cannot be null" );
Objects.requireNonNull( pos, "pos cannot be null" );
Objects.requireNonNull(world, "world cannot be null");
Objects.requireNonNull(pos, "pos cannot be null");
this.world = world;
this.pos = pos;
}
@@ -58,46 +50,36 @@ public abstract class TurtleBlockEvent extends TurtlePlayerEvent
*
* @return The world the turtle is interacting in.
*/
public World getWorld()
{
return world;
public World getWorld() {
return this.world;
}
/**
* Get the position the turtle is interacting with. Note that this is different
* to {@link ITurtleAccess#getPosition()}.
* Get the position the turtle is interacting with. Note that this is different to {@link ITurtleAccess#getPosition()}.
*
* @return The position the turtle is interacting with.
*/
public BlockPos getPos()
{
return pos;
public BlockPos getPos() {
return this.pos;
}
/**
* Fired when a turtle attempts to dig a block.
*
* This must be fired by {@link ITurtleUpgrade#useTool(ITurtleAccess, TurtleSide, TurtleVerb, EnumFacing)},
* as the base {@code turtle.dig()} command does not fire it.
*
* Note that such commands should also fire {@link BlockEvent.BreakEvent}, so you do not need to listen to both.
*
* @see TurtleAction#DIG
*/
@Cancelable
public static class Dig extends TurtleBlockEvent
{
private final IBlockState block;
public static class Dig extends TurtleBlockEvent {
private final BlockState block;
private final ITurtleUpgrade upgrade;
private final TurtleSide side;
public Dig( @Nonnull ITurtleAccess turtle, @Nonnull FakePlayer player, @Nonnull World world, @Nonnull BlockPos pos, @Nonnull IBlockState block, @Nonnull ITurtleUpgrade upgrade, @Nonnull TurtleSide side )
{
super( turtle, TurtleAction.DIG, player, world, pos );
public Dig(@Nonnull ITurtleAccess turtle, @Nonnull FakePlayer player, @Nonnull World world, @Nonnull BlockPos pos, @Nonnull BlockState block,
@Nonnull ITurtleUpgrade upgrade, @Nonnull TurtleSide side) {
super(turtle, TurtleAction.DIG, player, world, pos);
Objects.requireNonNull( block, "block cannot be null" );
Objects.requireNonNull( upgrade, "upgrade cannot be null" );
Objects.requireNonNull( side, "side cannot be null" );
Objects.requireNonNull(block, "block cannot be null");
Objects.requireNonNull(upgrade, "upgrade cannot be null");
Objects.requireNonNull(side, "side cannot be null");
this.block = block;
this.upgrade = upgrade;
this.side = side;
@@ -109,20 +91,18 @@ public abstract class TurtleBlockEvent extends TurtlePlayerEvent
* @return The block which is going to be broken.
*/
@Nonnull
public IBlockState getBlock()
{
return block;
public BlockState getBlock() {
return this.block;
}
/**
* Get the upgrade doing the digging
* Get the upgrade doing the digging.
*
* @return The upgrade doing the digging.
*/
@Nonnull
public ITurtleUpgrade getUpgrade()
{
return upgrade;
public ITurtleUpgrade getUpgrade() {
return this.upgrade;
}
/**
@@ -131,9 +111,8 @@ public abstract class TurtleBlockEvent extends TurtlePlayerEvent
* @return The upgrade's side.
*/
@Nonnull
public TurtleSide getSide()
{
return side;
public TurtleSide getSide() {
return this.side;
}
}
@@ -142,12 +121,9 @@ public abstract class TurtleBlockEvent extends TurtlePlayerEvent
*
* @see TurtleAction#MOVE
*/
@Cancelable
public static class Move extends TurtleBlockEvent
{
public Move( @Nonnull ITurtleAccess turtle, @Nonnull FakePlayer player, @Nonnull World world, @Nonnull BlockPos pos )
{
super( turtle, TurtleAction.MOVE, player, world, pos );
public static class Move extends TurtleBlockEvent {
public Move(@Nonnull ITurtleAccess turtle, @Nonnull FakePlayer player, @Nonnull World world, @Nonnull BlockPos pos) {
super(turtle, TurtleAction.MOVE, player, world, pos);
}
}
@@ -156,16 +132,13 @@ public abstract class TurtleBlockEvent extends TurtlePlayerEvent
*
* @see TurtleAction#PLACE
*/
@Cancelable
public static class Place extends TurtleBlockEvent
{
public static class Place extends TurtleBlockEvent {
private final ItemStack stack;
public Place( @Nonnull ITurtleAccess turtle, @Nonnull FakePlayer player, @Nonnull World world, @Nonnull BlockPos pos, @Nonnull ItemStack stack )
{
super( turtle, TurtleAction.PLACE, player, world, pos );
public Place(@Nonnull ITurtleAccess turtle, @Nonnull FakePlayer player, @Nonnull World world, @Nonnull BlockPos pos, @Nonnull ItemStack stack) {
super(turtle, TurtleAction.PLACE, player, world, pos);
Objects.requireNonNull( stack, "stack cannot be null" );
Objects.requireNonNull(stack, "stack cannot be null");
this.stack = stack;
}
@@ -175,9 +148,8 @@ public abstract class TurtleBlockEvent extends TurtlePlayerEvent
* @return The item stack to be placed.
*/
@Nonnull
public ItemStack getStack()
{
return stack;
public ItemStack getStack() {
return this.stack;
}
}
@@ -188,18 +160,16 @@ public abstract class TurtleBlockEvent extends TurtlePlayerEvent
*
* @see TurtleAction#INSPECT
*/
@Cancelable
public static class Inspect extends TurtleBlockEvent
{
private final IBlockState state;
public static class Inspect extends TurtleBlockEvent {
private final BlockState state;
private final Map<String, Object> data;
public Inspect( @Nonnull ITurtleAccess turtle, @Nonnull FakePlayer player, @Nonnull World world, @Nonnull BlockPos pos, @Nonnull IBlockState state, @Nonnull Map<String, Object> data )
{
super( turtle, TurtleAction.INSPECT, player, world, pos );
public Inspect(@Nonnull ITurtleAccess turtle, @Nonnull FakePlayer player, @Nonnull World world, @Nonnull BlockPos pos, @Nonnull BlockState state,
@Nonnull Map<String, Object> data) {
super(turtle, TurtleAction.INSPECT, player, world, pos);
Objects.requireNonNull( state, "state cannot be null" );
Objects.requireNonNull( data, "data cannot be null" );
Objects.requireNonNull(state, "state cannot be null");
Objects.requireNonNull(data, "data cannot be null");
this.data = data;
this.state = state;
}
@@ -210,9 +180,8 @@ public abstract class TurtleBlockEvent extends TurtlePlayerEvent
* @return The inspected block state.
*/
@Nonnull
public IBlockState getState()
{
return state;
public BlockState getState() {
return this.state;
}
/**
@@ -221,21 +190,18 @@ public abstract class TurtleBlockEvent extends TurtlePlayerEvent
* @return This block's inspection data.
*/
@Nonnull
public Map<String, Object> getData()
{
return data;
public Map<String, Object> getData() {
return this.data;
}
/**
* Add new information to the inspection result. Note this will override fields with the same name.
*
* @param newData The data to add. Note all values should be convertable to Lua (see
* {@link dan200.computercraft.api.peripheral.IPeripheral#callMethod(IComputerAccess, ILuaContext, int, Object[])}).
* @param newData The data to add. Note all values should be convertible to Lua (see {@link MethodResult#of(Object)}).
*/
public void addData( @Nonnull Map<String, ?> newData )
{
Objects.requireNonNull( newData, "newData cannot be null" );
data.putAll( newData );
public void addData(@Nonnull Map<String, ?> newData) {
Objects.requireNonNull(newData, "newData cannot be null");
this.data.putAll(newData);
}
}
}

View File

@@ -1,43 +1,49 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.turtle.event;
import dan200.computercraft.api.turtle.ITurtleAccess;
import net.minecraftforge.fml.common.eventhandler.Event;
import javax.annotation.Nonnull;
import java.util.Objects;
import javax.annotation.Nonnull;
import com.google.common.eventbus.EventBus;
import dan200.computercraft.api.turtle.ITurtleAccess;
/**
* A base class for all events concerning a turtle. This will only ever constructed and fired on the server side,
* so sever specific methods on {@link ITurtleAccess} are safe to use.
* A base class for all events concerning a turtle. This will only ever constructed and fired on the server side, so sever specific methods on {@link
* ITurtleAccess} are safe to use.
*
* You should generally not need to subscribe to this event, preferring one of the more specific classes.
*
* @see TurtleActionEvent
*/
public abstract class TurtleEvent extends Event
{
public abstract class TurtleEvent {
public static final EventBus EVENT_BUS = new EventBus();
private final ITurtleAccess turtle;
protected TurtleEvent( @Nonnull ITurtleAccess turtle )
{
Objects.requireNonNull( turtle, "turtle cannot be null" );
protected TurtleEvent(@Nonnull ITurtleAccess turtle) {
Objects.requireNonNull(turtle, "turtle cannot be null");
this.turtle = turtle;
}
public static boolean post(TurtleActionEvent event) {
EVENT_BUS.post(event);
return event.isCancelled();
}
/**
* Get the turtle which is performing this action.
*
* @return The access for this turtle.
*/
@Nonnull
public ITurtleAccess getTurtle()
{
return turtle;
public ITurtleAccess getTurtle() {
return this.turtle;
}
}

View File

@@ -0,0 +1,85 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.turtle.event;
import java.util.Map;
import java.util.Objects;
import javax.annotation.Nonnull;
import dan200.computercraft.api.lua.MethodResult;
import dan200.computercraft.api.turtle.ITurtleAccess;
import net.minecraft.item.ItemStack;
/**
* 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 may be fired on the computer thread, and so any
* operations on it must be thread safe.
*
* @see TurtleAction#INSPECT_ITEM
*/
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);
Objects.requireNonNull(stack, "stack cannot be null");
Objects.requireNonNull(data, "data cannot be null");
this.stack = stack;
this.data = data;
this.mainThread = mainThread;
}
/**
* The item which is currently being inspected.
*
* @return The item stack which is being inspected. This should <b>not</b> be modified.
*/
@Nonnull
public ItemStack getStack() {
return this.stack;
}
/**
* Get the "inspection data" from this item, which will be returned to the user.
*
* @return This items's inspection data.
*/
@Nonnull
public Map<String, Object> getData() {
return this.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 this.mainThread;
}
/**
* Add new information to the inspection result. Note this will override fields with the same name.
*
* @param newData The data to add. Note all values should be convertible to Lua (see {@link MethodResult#of(Object)}).
*/
public void addData(@Nonnull Map<String, ?> newData) {
Objects.requireNonNull(newData, "newData cannot be null");
this.data.putAll(newData);
}
}

View File

@@ -1,46 +1,44 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.turtle.event;
import dan200.computercraft.api.turtle.ITurtleAccess;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.common.util.FakePlayer;
import net.minecraftforge.fml.common.eventhandler.Cancelable;
import net.minecraftforge.items.IItemHandler;
import java.util.Objects;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Objects;
import dan200.computercraft.api.turtle.FakePlayer;
import dan200.computercraft.api.turtle.ITurtleAccess;
import net.minecraft.inventory.Inventory;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
/**
* Fired when a turtle attempts to interact with an inventory.
*/
@Cancelable
public abstract class TurtleInventoryEvent extends TurtleBlockEvent
{
private final IItemHandler handler;
public abstract class TurtleInventoryEvent extends TurtleBlockEvent {
private final Inventory handler;
protected TurtleInventoryEvent( @Nonnull ITurtleAccess turtle, @Nonnull TurtleAction action, @Nonnull FakePlayer player, @Nonnull World world, @Nonnull BlockPos pos, @Nullable IItemHandler handler )
{
super( turtle, action, player, world, pos );
protected TurtleInventoryEvent(@Nonnull ITurtleAccess turtle, @Nonnull TurtleAction action, @Nonnull FakePlayer player, @Nonnull World world,
@Nonnull BlockPos pos, @Nullable Inventory handler) {
super(turtle, action, player, world, pos);
this.handler = handler;
}
/**
* Get the inventory being interacted with
* Get the inventory being interacted with.
*
* @return The inventory being interacted with, {@code null} if the item will be dropped to/sucked from the world.
*/
@Nullable
public IItemHandler getItemHandler()
{
return handler;
public Inventory getItemHandler() {
return this.handler;
}
/**
@@ -48,12 +46,9 @@ public abstract class TurtleInventoryEvent extends TurtleBlockEvent
*
* @see TurtleAction#SUCK
*/
@Cancelable
public static class Suck extends TurtleInventoryEvent
{
public Suck( @Nonnull ITurtleAccess turtle, @Nonnull FakePlayer player, @Nonnull World world, @Nonnull BlockPos pos, @Nullable IItemHandler handler )
{
super( turtle, TurtleAction.SUCK, player, world, pos, handler );
public static class Suck extends TurtleInventoryEvent {
public Suck(@Nonnull ITurtleAccess turtle, @Nonnull FakePlayer player, @Nonnull World world, @Nonnull BlockPos pos, @Nullable Inventory handler) {
super(turtle, TurtleAction.SUCK, player, world, pos, handler);
}
}
@@ -62,29 +57,25 @@ public abstract class TurtleInventoryEvent extends TurtleBlockEvent
*
* @see TurtleAction#DROP
*/
@Cancelable
public static class Drop extends TurtleInventoryEvent
{
public static class Drop extends TurtleInventoryEvent {
private final ItemStack stack;
public Drop( @Nonnull ITurtleAccess turtle, @Nonnull FakePlayer player, @Nonnull World world, @Nonnull BlockPos pos, @Nullable IItemHandler handler, @Nonnull ItemStack stack )
{
super( turtle, TurtleAction.DROP, player, world, pos, handler );
public Drop(@Nonnull ITurtleAccess turtle, @Nonnull FakePlayer player, @Nonnull World world, @Nonnull BlockPos pos, @Nullable Inventory handler,
@Nonnull ItemStack stack) {
super(turtle, TurtleAction.DROP, player, world, pos, handler);
Objects.requireNonNull( stack, "stack cannot be null" );
Objects.requireNonNull(stack, "stack cannot be null");
this.stack = stack;
}
/**
* The item which will be inserted into the inventory/dropped on the ground.
*
* Note that this is a copy of the original stack, and so should not be modified, as that will have no effect.
*
* @return The item stack which will be dropped.
* @return The item stack which will be dropped. This should <b>not</b> be modified.
*/
public ItemStack getStack()
{
return stack.copy();
@Nonnull
public ItemStack getStack() {
return this.stack;
}
}
}

View File

@@ -1,31 +1,30 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.turtle.event;
import dan200.computercraft.api.turtle.ITurtleAccess;
import net.minecraftforge.common.util.FakePlayer;
import java.util.Objects;
import javax.annotation.Nonnull;
import java.util.Objects;
import dan200.computercraft.api.turtle.FakePlayer;
import dan200.computercraft.api.turtle.ITurtleAccess;
/**
* An action done by a turtle which is normally done by a player.
*
* {@link #getPlayer()} may be used to modify the player's attributes or perform permission checks.
*/
public abstract class TurtlePlayerEvent extends TurtleActionEvent
{
public abstract class TurtlePlayerEvent extends TurtleActionEvent {
private final FakePlayer player;
protected TurtlePlayerEvent( @Nonnull ITurtleAccess turtle, @Nonnull TurtleAction action, @Nonnull FakePlayer player )
{
super( turtle, action );
protected TurtlePlayerEvent(@Nonnull ITurtleAccess turtle, @Nonnull TurtleAction action, @Nonnull FakePlayer player) {
super(turtle, action);
Objects.requireNonNull( player, "player cannot be null" );
Objects.requireNonNull(player, "player cannot be null");
this.player = player;
}
@@ -37,8 +36,7 @@ public abstract class TurtlePlayerEvent extends TurtleActionEvent
* @return A {@link FakePlayer} representing this turtle.
*/
@Nonnull
public FakePlayer getPlayer()
{
return player;
public FakePlayer getPlayer() {
return this.player;
}
}

View File

@@ -0,0 +1,85 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.turtle.event;
import java.util.Objects;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import dan200.computercraft.api.turtle.ITurtleAccess;
import net.minecraft.item.ItemStack;
/**
* Fired when a turtle attempts to refuel from an item.
*
* One may use {@link #setCanceled(boolean, String)} to prevent refueling from this specific item. Additionally, you may use {@link #setHandler(Handler)} to
* register a custom fuel provider.
*/
public class TurtleRefuelEvent extends TurtleActionEvent {
private final ItemStack stack;
private Handler handler;
public TurtleRefuelEvent(@Nonnull ITurtleAccess turtle, @Nonnull ItemStack stack) {
super(turtle, TurtleAction.REFUEL);
Objects.requireNonNull(turtle, "turtle cannot be null");
this.stack = stack;
}
/**
* Get the stack we are attempting to refuel from.
*
* Do not modify the returned stack - all modifications should be done within the {@link Handler}.
*
* @return The stack to refuel from.
*/
public ItemStack getStack() {
return this.stack;
}
/**
* Get the refuel handler for this stack.
*
* @return The refuel handler, or {@code null} if none has currently been set.
* @see #setHandler(Handler)
*/
@Nullable
public Handler getHandler() {
return this.handler;
}
/**
* Set the refuel handler for this stack.
*
* You should call this if you can actually refuel from this item, and ideally only if there are no existing handlers.
*
* @param handler The new refuel handler.
* @see #getHandler()
*/
public void setHandler(@Nullable Handler handler) {
this.handler = handler;
}
/**
* Handles refuelling a turtle from a specific item.
*/
@FunctionalInterface
public interface Handler {
/**
* Refuel a turtle using an item.
*
* @param turtle The turtle to refuel.
* @param stack The stack to refuel with.
* @param slot The slot the stack resides within. This may be used to modify the inventory afterwards.
* @param limit The maximum number of refuel operations to perform. This will often correspond to the number of items to consume.
* @return The amount of fuel gained.
*/
int refuel(@Nonnull ITurtleAccess turtle, @Nonnull ItemStack stack, int slot, int limit);
}
}

View File

@@ -1,10 +0,0 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
@API( owner = "ComputerCraft", provides = "ComputerCraft|API|Turtle|Event", apiVersion = "${version}" )
package dan200.computercraft.api.turtle.event;
import net.minecraftforge.fml.common.API;

View File

@@ -1,10 +0,0 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
@API( owner = "ComputerCraft", provides = "ComputerCraft|API|Turtle", apiVersion = "${version}" )
package dan200.computercraft.api.turtle;
import net.minecraftforge.fml.common.API;

View File

@@ -0,0 +1,123 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.client;
import java.util.HashSet;
import java.util.function.Consumer;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.ComputerCraftRegistry;
import dan200.computercraft.shared.common.IColouredItem;
import dan200.computercraft.shared.media.items.ItemDisk;
import dan200.computercraft.shared.media.items.ItemTreasureDisk;
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
import dan200.computercraft.shared.util.Colour;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.ModelLoader;
import net.minecraft.client.render.model.ModelRotation;
import net.minecraft.client.render.model.UnbakedModel;
import net.minecraft.client.texture.SpriteAtlasTexture;
import net.minecraft.client.util.ModelIdentifier;
import net.minecraft.resource.ResourceManager;
import net.minecraft.util.Identifier;
import net.fabricmc.fabric.api.client.rendering.v1.ColorProviderRegistry;
import net.fabricmc.fabric.api.event.client.ClientSpriteRegistryCallback;
/**
* Registers textures and models for items.
*/
@SuppressWarnings ({
"MethodCallSideOnly",
"LocalVariableDeclarationSideOnly"
})
public final class ClientRegistry {
private static final String[] EXTRA_MODELS = new String[] {
"turtle_modem_normal_off_left",
"turtle_modem_normal_on_left",
"turtle_modem_normal_off_right",
"turtle_modem_normal_on_right",
"turtle_modem_advanced_off_left",
"turtle_modem_advanced_on_left",
"turtle_modem_advanced_off_right",
"turtle_modem_advanced_on_right",
"turtle_crafting_table_left",
"turtle_crafting_table_right",
"turtle_speaker_upgrade_left",
"turtle_speaker_upgrade_right",
"turtle_colour",
"turtle_elf_overlay",
};
private static final String[] EXTRA_TEXTURES = new String[] {
// TODO: Gather these automatically from the model. Sadly the model loader isn't available
// when stitching textures.
"block/turtle_colour",
"block/turtle_elf_overlay",
"block/turtle_crafty_face",
"block/turtle_speaker_face",
};
private ClientRegistry() {}
public static void onTextureStitchEvent(SpriteAtlasTexture atlasTexture, ClientSpriteRegistryCallback.Registry registry) {
for (String extra : EXTRA_TEXTURES) {
registry.register(new Identifier(ComputerCraft.MOD_ID, extra));
}
}
@SuppressWarnings ("NewExpressionSideOnly")
public static void onModelBakeEvent(ResourceManager manager, Consumer<ModelIdentifier> out) {
for (String model : EXTRA_MODELS) {
out.accept(new ModelIdentifier(new Identifier(ComputerCraft.MOD_ID, model), "inventory"));
}
}
public static void onItemColours() {
ColorProviderRegistry.ITEM.register((stack, layer) -> {
return layer == 1 ? ((ItemDisk) stack.getItem()).getColour(stack) : 0xFFFFFF;
}, ComputerCraftRegistry.ModItems.DISK);
ColorProviderRegistry.ITEM.register((stack, layer) -> layer == 1 ? ItemTreasureDisk.getColour(stack) : 0xFFFFFF,
ComputerCraftRegistry.ModItems.TREASURE_DISK);
ColorProviderRegistry.ITEM.register((stack, layer) -> {
switch (layer) {
case 0:
default:
return 0xFFFFFF;
case 1: // Frame colour
return IColouredItem.getColourBasic(stack);
case 2: // Light colour
{
int light = ItemPocketComputer.getLightState(stack);
return light == -1 ? Colour.BLACK.getHex() : light;
}
}
}, ComputerCraftRegistry.ModItems.POCKET_COMPUTER_NORMAL, ComputerCraftRegistry.ModItems.POCKET_COMPUTER_ADVANCED);
// Setup turtle colours
ColorProviderRegistry.ITEM.register((stack, tintIndex) -> tintIndex == 0 ? ((IColouredItem) stack.getItem()).getColour(stack) : 0xFFFFFF,
ComputerCraftRegistry.ModBlocks.TURTLE_NORMAL,
ComputerCraftRegistry.ModBlocks.TURTLE_ADVANCED);
}
private static BakedModel bake(ModelLoader loader, UnbakedModel model, Identifier identifier) {
model.getTextureDependencies(loader::getOrLoadModel, new HashSet<>());
return model.bake(loader,
spriteIdentifier -> MinecraftClient.getInstance()
.getSpriteAtlas(spriteIdentifier.getAtlasId())
.apply(spriteIdentifier.getTextureId()),
ModelRotation.X0_Y0,
identifier);
}
}

View File

@@ -1,81 +1,91 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.client;
import javax.annotation.Nullable;
import dan200.computercraft.fabric.mixin.ChatHudAccess;
import dan200.computercraft.shared.command.text.ChatHelpers;
import dan200.computercraft.shared.command.text.TableBuilder;
import dan200.computercraft.shared.command.text.TableFormatter;
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.GuiNewChat;
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 net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.hud.ChatHud;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.util.math.MathHelper;
public class ClientTableFormatter implements TableFormatter
{
@SuppressWarnings ({
"MethodCallSideOnly",
"LocalVariableDeclarationSideOnly"
})
public class ClientTableFormatter implements TableFormatter {
public static final ClientTableFormatter INSTANCE = new ClientTableFormatter();
private static Int2IntOpenHashMap lastHeights = new Int2IntOpenHashMap();
private FontRenderer renderer()
{
return Minecraft.getMinecraft().fontRenderer;
}
@Override
@Nullable
public ITextComponent getPadding( ITextComponent component, int width )
{
int extraWidth = width - getWidth( component );
if( extraWidth <= 0 ) return null;
public Text getPadding(Text component, int width) {
int extraWidth = width - this.getWidth(component);
if (extraWidth <= 0) {
return null;
}
FontRenderer renderer = renderer();
TextRenderer renderer = renderer();
float spaceWidth = renderer.getCharWidth( ' ' );
int spaces = MathHelper.floor( extraWidth / spaceWidth );
float spaceWidth = renderer.getWidth(" ");
int spaces = MathHelper.floor(extraWidth / spaceWidth);
int extra = extraWidth - (int) (spaces * spaceWidth);
return ChatHelpers.coloured( StringUtils.repeat( ' ', spaces ) + StringUtils.repeat( (char) 712, extra ), TextFormatting.GRAY );
return ChatHelpers.coloured(StringUtils.repeat(' ', spaces) + StringUtils.repeat((char) 712, extra), Formatting.GRAY);
}
private static TextRenderer renderer() {
return MinecraftClient.getInstance().textRenderer;
}
@Override
public int getColumnPadding()
{
public int getColumnPadding() {
return 3;
}
@Override
public int getWidth( ITextComponent component )
{
return renderer().getStringWidth( component.getFormattedText() );
public int getWidth(Text component) {
return renderer().getWidth(component);
}
@Override
public void writeLine( int id, ITextComponent component )
{
Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessageWithOptionalDeletion( component, id );
public void writeLine(int id, Text component) {
MinecraftClient mc = MinecraftClient.getInstance();
ChatHud chat = mc.inGameHud.getChatHud();
// 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 );
((ChatHudAccess)chat).callAddMessage(component, id);
}
@Override
public int display( TableBuilder table )
{
GuiNewChat chat = Minecraft.getMinecraft().ingameGUI.getChatGUI();
public int display(TableBuilder table) {
ChatHud chat = MinecraftClient.getInstance().inGameHud.getChatHud();
int lastHeight = lastHeights.get( table.getId() );
int lastHeight = lastHeights.get(table.getId());
int height = TableFormatter.super.display( table );
lastHeights.put( table.getId(), height );
int height = TableFormatter.super.display(table);
lastHeights.put(table.getId(), height);
for( int i = height; i < lastHeight; i++ ) chat.deleteChatLine( i + table.getId() );
for (int i = height; i < lastHeight; i++) {
((ChatHudAccess)chat).callRemoveMessage(i + table.getId());
}
return height;
}
}

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